2013-10-17 54 views
9

我有一種情況,我想將DateTime轉換爲Instant。我相信DateTimeKind將是Local我應該如何將本地日期時間轉換爲即時?

鑑於DateTime是在一個名爲time變量,我可以在庫中找到的最接近的是:

Instant.FromDateTimeUtc(time.ToUniversalTime()) 

這似乎是合理的,但我想可以肯定,這是完全可靠的,並沒有按」不會有數據丟失或損壞的風險。我不確定這是否是進行轉換的最佳方式,或者是否有更可靠的方法來執行轉換。

我看着NodaTime的BCL Conversions頁面,它說這個方案如下:

注意,沒有轉換爲DateTime有一種Local - 這將有效地爲系統默認時間這個區域,你應該明確地開始。

回答

16

您錯過了一個關鍵點:A DateTime,其種類爲Local並不總是完全代表一個獨特的時刻。這就是爲什麼沒有直接映射到Instant

在回退DST過渡期間,本地DateTime可以表示兩個可能時刻中的任意一個。如果您打算將其轉換爲Instant,那麼您需要在某個地方決定您應該選擇哪個時間段。

在你給出的答案,我假設你從下面的一個獲得timezone

var timezone = DateTimeZoneProviders.Tzdb.GetSystemDefault(); 

var timezone = DateTimeZoneProviders.Bcl.GetSystemDefault(); 

無論是確定此任務。然後代碼你給:

var localTime = LocalDateTime.FromDateTime(time); 
var zonedTime = localTime.InZoneStrictly(timeZone); 
return zonedTime.ToInstant(); 

這是完全正確的,但因爲你使用InZoneStrictly,你將回退轉變過程中得到一個AmbiguousTimeException

您可以通過使用InZoneLeniently來避免這種情況,它將選擇後兩種可能性(通常是「標準」時間)。但更重要的是,您可以改爲使用InZone,並提供標準或自定義resolver以更精確地控制行爲。

關於你的原始的做法:

Instant.FromDateTimeUtc(time.ToUniversalTime()) 

這是確定,不會破壞你的數據,但明白這將依賴於當地的通用轉換BCL的行爲。它與InZoneLeniently相同,因爲模糊值將被視爲「標準」時間。

這是NodaTime如何提供更精確的API的一個很好的例子。與其做出假設,您有機會具體並提供自定義行爲。最後你獲得了同樣的結果,但它將這個問題帶到了前臺而不是隱藏它。

+0

感謝您花時間解釋這一點。我認爲這對其他對圖書館不熟悉的人會有幫助。 – Sam

1

我才意識到,我可以在本地時間轉換爲NodaTimeLocalDateTime,然後使用的InZone方法之後ToInstant一個它映射到一個瞬間。這裏有一個例子假設在timeZone提供了時間的時區,你想,如果時間無效拋出一個錯誤:

var localTime = LocalDateTime.FromDateTime(time); 
var zonedTime = localTime.InZoneStrictly(timeZone); 
return zonedTime.ToInstant(); 

請記住,這是假設time確實Local。如果不是,我相信結果會不正確。

相關問題