2016-12-14 208 views
2

我有一个臭名昭着的夏令时问题。夏令时和DateTime.AddHour()

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

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

迭代它

timeIterator = timeIterator.AddHours(1); 

,并检查每个迭代,如果在时间点出现在列表中。

夏令时出现问题。我以2014年为例,时钟在02年3月30日移动到0300.所以,在0159到达0300之后。但是DateTime.AddHours()完全忽略了夏令时。如果timeIterator在{30.03.2014 01:00:00},我打电话AddHours(1),我得到{30.03.2014 02:00:00}这显然不存在。

如果我现在根据这个数据点测试列表,它是(自然地)不在列表中,并且我抛出了一个错误的“丢失的数据点错误”。

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

由于提前,
弗兰克

+0

嗯,这实际上取决于你在谈论哪一个国家。 –

+0

您有关[此](http://stackoverflow.com/questions/5811267/net-accounting-for-daylight-savings)有关TimezoneInfo的答案。 –

+0

另请阅读[这里](http://codeofmatt.com/2015/03/06/common-daylight-saving-time-mistakes-for-net-developers/),搜索*验证您的输入!*。 –

回答

2

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

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

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出于某种原因,你也可以使用以下功能:

TimeZoneInfo tzi = /* the timezone */; 
DateTime timeIterator = /* the time */; 
if (tzi.IsAmbiguousTime(timeIterator)) 
{ 
    /* Expect multiple data entries */ 
} 
if (tzi.IsInvalidTime(timeIterator)) 
{ 
    /* Expect no data entries */ 
} 
+0

问题是,如果他们继续按当地时间存储日期,他们将不会在其一年中的其他转换点找到他们是否缺少信息。例如。如果数据的存储时间为0100 UTC,0200 UTC和0400 UTC,但在UTC时间0300时钟已经设置回来,他们将在当地时间0100,0200和0300存储数据,但实际上他们丢失了本应创建的数据0300 UTC也映射到当地时间0200,他们仍然不会在这里找到它。 –

+0

@Damien_The_Unbeliever真实的故事。如果问题作者没有检查外部数据(没有影响),现在肯定是改进日期时间存储的时候了。但是,如果任务是检查现有的历史数据,那么损害就会完成,并且双倍时间不能再通过价值比较来分开。猜猜我要编辑我的问题来澄清一些事情。 – grek40

+0

嘿,我检查外部数据 - 我的问题是,我最终(夏令时)检查一个无效的日期。重点是:我必须知道时区以避免这种情况,否则我无法知道这是否是有效的日期。猜测我会切换到NodaTime以更有意识地处理它... – Aaginor

0

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

然后改造它:(可能使用一种推广方法)

private DateTime TransformToTimezone(DateTime datetime) 
{ 
      TimeZoneInfo beZone = TimeZoneInfo.FindSystemTimeZoneById("Romance Standard Time"); 

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

是的,或者用我的数据存储时区(我可能会这样做)。 ...并使用NodaTime更清晰透明。 – Aaginor