关于c#:夏令时和DateTime.AddHour()

Daylight saving and DateTime.AddHour()

臭名昭着的夏令时我有一个问题。

我有一个数据点列表,一年中每小时一个。 要检查是否存在所有数据点,我创建一个这样的时间迭代器:

1
DateTime timeIterator = new DateTime(year, 1, 1, 0, 0, 0);

迭代它

1
timeIterator = timeIterator.AddHours(1);

如果列表中存在时间点,则检查每次迭代。

遇到夏令时时会出现问题。 我是2014年的例子,时钟在0200年3月30日从0300移动到0300.所以,在0159到0300之后。但是DateTime.AddHours()完全忽略了夏令时。 如果timeIterator在{30.03.2014 01:00:00}并且我调用AddHours(1),我得到{30.03.2014 02:00:00},这显然不存在。

如果我现在测试该数据点的列表,它(自然)不在列表中,我抛出一个错误的"缺少数据点错误"。

如果我的DateTime是有效的时间点,我如何检查?

提前致谢,
坦率


How can I check, if my DateTime is a valid point in time?

不要检查,确保它。您可以计算UTC的小时数,并将每个点转换为当地时间。

1
2
3
4
5
6
7
DateTimeOffset timeIterator = new DateTimeOffset(new DateTime(year, 1, 1, 0, 0, 0, DateTimeKind.Local));
timeIterator = timeIterator.AddHours(1);
timeIterator.LocalDateTime;

// assuming you have a TimeZoneInfo object, you can also get different local times:
TimeZoneInfo tzi = /* the timezone */;
TimeZoneInfo.ConvertTimeFromUtc(timeIterator.UtcDateTime, tzi);

但是,正如Damien_The_Unbeliever评论的那样,这只解决了问题的一部分,程序将不再检查无效日期的存在。当您的数据以本地时间存储时,会出现另一个问题。这意味着从DST到正常时间的转换将具有两个连续的小时,具有相同的本地DateTime表示。为了避免这种情况,必须使用完整信息(UTC或显式偏移)存储数据,以便以后进行比较。

编辑:

如果您的数据时区有一个有效的TimeZoneInfo对象,并且由于某种原因您不想切换到DateTimeOffset,那么您还可以使用以下函数:

1
2
3
4
5
6
7
8
9
10
TimeZoneInfo tzi = /* the timezone */;
DateTime timeIterator = /* the time */;
if (tzi.IsAmbiguousTime(timeIterator))
{
    /* Expect multiple data entries */
}
if (tzi.IsInvalidTime(timeIterator))
{
    /* Expect no data entries */
}


我也遇到过时区问题。
我建议你将日期保存为UTC值

然后转换它:(也许使用扩展方法)

1
2
3
4
5
6
7
private DateTime TransformToTimezone(DateTime datetime)
{
            TimeZoneInfo beZone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time");

            //Convert to timezone
            return TimeZoneInfo.ConvertTimeFromUtc(datetime, beZone);
}