2016-12-14 210 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