问题描述
我有CSV数据文件,带有时间戳的记录在当地时间。不幸的是,数据文件涵盖夏令时变化的时期(2013年11月3日),因此记录的时间戳的时间分量为: 12:45,1:00,1:15,1:30 ,1:45,1:00,1:15,1:30,1:45,2:00
。我希望能够以数据库的形式将数据转换并存储为UTC。 不幸的是,标准的 DateTime.Parse()
函数将解析为(2013年11月3日):
时间字符串|解析当地时间|在DST |解析当地时间UTC
| 12:45 am | 12:45 am |是| 4:45 am
| 12:59:59 am | 12:59:59 am |是| 4:59:59 am
| 01:00 am | 1:00 am |不| 6:00 am
| 01:15 am |上午1:15 |不| 6:15 am
所以它从来没有看到 1:00-1: 59:59 am
范围为DST,我解析的UTC时间戳在一小时内跳转。
有没有一个图书馆或类会让我解析时间戳,并考虑到DST的变化?像一些可实例化的类,将记住已经收到的时间戳流,并相应地调整解析的时间戳?
解析时可以进行的数据的假设:
- 在本地和UTC本文件的标题部分,我有文件的开始时间(第一个记录的时间戳)。
- 记录按时间戳顺序
- 所有本地时间都在东部标准
- 数据也可以转到另一个方式:从DST进入
- 记录包含以下格式的完整时间戳记:
yyyy / mm / dd HH:mm:ss
(2013/11/03 00:45:00
)
注意:虽然我的软件在C#中,我没有特别标记C#/ .NET,因为我想我可以使用任何语言的解决方案的实现,如果需要,重新编码。
在C#中:
//定义输入值。
string [] input =
{
2013-11-03 00:45:00,
2013-11-03 01:00:00,
2013-11-03 01:15:00,
2013-11-03 01:30:00,
2013-11-03 01:45:00,
2013-11-03 01:00:00,
2013-11-03 01:15:00,
2013-11-03 01:30:00
2013-11-03 01:45:00,
2013-11-03 02:00:00,
};
//获取输入意图被解释的时区。
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(Eastern Standard Time);
//为输出值创建一个数组
DateTimeOffset [] output = new DateTimeOffset [input.Length];
//从假设DST处于活动状态开始,当将
//从日光时间移动到标准时间时,会发生歧义。
bool dst = true;
//通过输入迭代。 (int i = 0; i< input.Length; i ++)
{
//将输入字符串解析为具有未指定类型的DateTime
DateTime dt = DateTime。 ParseExact(input [i],yyyy-MM-dd HH:mm:ss,
CultureInfo.InvariantCulture);
//确定偏移量。
TimeSpan offset;
if(tz.IsAmbiguousTime(dt))
{
//获取可能的偏移量,并使用DST标志和上一个条目
//来确定我们是否过去过渡点。这只能工作
//,因为我们有外界的知识,这些项目是顺序的。
TimeSpan [] offsets = tz.GetAmbiguousTimeOffsets(dt);
offset = dst&&& (i == 0 || dt> = output [i - 1] .DateTime)
?偏移量[1]:偏移量[0];
}
else
{
//该值是明确的,所以只需获得单个偏移量即可。
offset = tz.GetUtcOffset(dt);
}
//使用确定的值构造DateTimeOffset
DateTimeOffset dto = new DateTimeOffset(dt,offset);
//我们可以明确地检查一个DateTimeOffset为夏令时,
//设置下一次迭代的DST标志。
dst = tz.IsDaylightSavingTime(dto);
//将DateTimeOffset保存到输出数组。
output [i] = dto;
}
//显示调试输出
foreach(输出中为var dto)
{
Console.WriteLine({ 0:yyyy-MM-dd HH:mm:ss zzzz} => {1:yyyy-MM-dd HH:mm:ss} UTC,
dto,dto.UtcDateTime);
}
输出:
2013-11-03 00:45:00 -04:00 => 2013-11-03 04:45:00 UTC
2013-11-03 01:00:00 -04:00 => 2013-11-03 05:00:00 UTC
2013-11-03 01:15:00 -04:00 => 2013-11-03 05:15:00 UTC
2013-11-03 01:30:00 -04:00 => 2013-11-03 05:30:00 UTC
2013-11-03 01:45:00 -04:00 => 2013-11-03 05:45:00 UTC
2013-11-03 01:00:00 -05:00 => 2013-11-03 06:00:00 UTC
2013-11-03 01:15:00 -05:00 => 2013-11-03 06:15:00 UTC
2013-11-03 01:30:00 -05:00 => 2013-11-03 06:30:00 UTC
2013-11-03 01:45:00 -05:00 => 2013-11-03 06:45:00 UTC
2013-11-03 02:00:00 -05:00 => 2013-11-03 07:00:00 UTC
请注意,这是假设您第一次遇到一个不明确的时间,如1:00,它将在DST。说你的列表被截断到最后的5个条目 - 你不会知道那些在标准的时间。在这种情况下,你可以做的不多。
I have CSV data files with timestamped records that are in local time. Unfortunately the data files cover the period where daylight saving time changes (Nov 3rd 2013) so the time component of the timestamps for the records go: 12:45, 1:00, 1:15, 1:30, 1:45, 1:00, 1:15, 1:30, 1:45, 2:00
. I want to be able to convert and store the values in the database as UTC.
Unfortunately the standard DateTime.Parse()
function of .NET will parse as this (all November 3rd 2013):
| Time String | Parsed Local Time | In DST | Parsed Local Time to UTC
| 12:45 am | 12:45 am | Yes | 4:45 am
| 12:59:59 am | 12:59:59 am | Yes | 4:59:59 am
| 01:00 am | 1:00 am | No | 6:00 am
| 01:15 am | 1:15 am | No | 6:15 am
So it never sees the 1:00-1:59:59 am
range as being in DST and my parsed timestamps in UTC jumps an hour.
Is there a library or class out there that will allow me to parse the timestamps and take into account the change in DST? Like some instantiatable class that will remember the stream of timestamps it's already received and adjust the parsed timestamp accordingly?
Assumptions about the data that can be made while parsing:
- I have the start time of file (timestamp of the first record) in the header section of the file in both local and UTC.
- The records are in order by timestamp
- All local times are in Eastern Standard
- The data could also go the other way: from out of DST into it
- The records contain a full timestamp in the format:
yyyy/mm/dd HH:mm:ss
(2013/11/03 00:45:00
)
Note: While my software is in C#, I did not tag C#/.NET specifically as I figured I could use any language's implementation of a solution and recode if necessary.
In C#:
// Define the input values.
string[] input =
{
"2013-11-03 00:45:00",
"2013-11-03 01:00:00",
"2013-11-03 01:15:00",
"2013-11-03 01:30:00",
"2013-11-03 01:45:00",
"2013-11-03 01:00:00",
"2013-11-03 01:15:00",
"2013-11-03 01:30:00",
"2013-11-03 01:45:00",
"2013-11-03 02:00:00",
};
// Get the time zone the input is meant to be interpreted in.
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
// Create an array for the output values
DateTimeOffset[] output = new DateTimeOffset[input.Length];
// Start with the assumption that DST is active, as ambiguities occur when moving
// out of daylight time into standard time.
bool dst = true;
// Iterate through the input.
for (int i = 0; i < input.Length; i++)
{
// Parse the input string as a DateTime with Unspecified kind
DateTime dt = DateTime.ParseExact(input[i], "yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture);
// Determine the offset.
TimeSpan offset;
if (tz.IsAmbiguousTime(dt))
{
// Get the possible offsets, and use the DST flag and the previous entry
// to determine if we are past the transition point. This only works
// because we have outside knowledge that the items are in sequence.
TimeSpan[] offsets = tz.GetAmbiguousTimeOffsets(dt);
offset = dst && (i == 0 || dt >= output[i - 1].DateTime)
? offsets[1] : offsets[0];
}
else
{
// The value is unambiguous, so just get the single offset it can be.
offset = tz.GetUtcOffset(dt);
}
// Use the determined values to construct a DateTimeOffset
DateTimeOffset dto = new DateTimeOffset(dt, offset);
// We can unambiguously check a DateTimeOffset for daylight saving time,
// which sets up the DST flag for the next iteration.
dst = tz.IsDaylightSavingTime(dto);
// Save the DateTimeOffset to the output array.
output[i] = dto;
}
// Show the output for debugging
foreach (var dto in output)
{
Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss zzzz} => {1:yyyy-MM-dd HH:mm:ss} UTC",
dto, dto.UtcDateTime);
}
Output:
2013-11-03 00:45:00 -04:00 => 2013-11-03 04:45:00 UTC
2013-11-03 01:00:00 -04:00 => 2013-11-03 05:00:00 UTC
2013-11-03 01:15:00 -04:00 => 2013-11-03 05:15:00 UTC
2013-11-03 01:30:00 -04:00 => 2013-11-03 05:30:00 UTC
2013-11-03 01:45:00 -04:00 => 2013-11-03 05:45:00 UTC
2013-11-03 01:00:00 -05:00 => 2013-11-03 06:00:00 UTC
2013-11-03 01:15:00 -05:00 => 2013-11-03 06:15:00 UTC
2013-11-03 01:30:00 -05:00 => 2013-11-03 06:30:00 UTC
2013-11-03 01:45:00 -05:00 => 2013-11-03 06:45:00 UTC
2013-11-03 02:00:00 -05:00 => 2013-11-03 07:00:00 UTC
Note that this assumes that the first time you encounter an ambiguous time like 1:00 that it will be in DST. Say your list was truncated to just the last 5 entries - you wouldn't know that those were in standard time. There's not much you could do in that particular case.
这篇关于在观察夏令时期间,分析当地时间(至UTC)的有序时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!