您需要一個時區數據庫來執行所需的日期和時間轉換。時區比單純偏移更復雜,因爲許多時區都包含夏時制規則。
.NET框架允許您通過使用TimeZoneInfo
類來使用基礎Windows時區數據庫。但是,您可以考慮Windows時區數據庫專有的。 IANA保留Best Current Practice (BCP) 175中描述的Time Zone Database (TZDB)。
庫Noda Time具有支持TZDB和提供的本地時間戳作爲.NET DateTime
和可以計算相應的UTC時間戳的時區標識符:
var localDateTime = LocalDateTime.FromDateTime(dateTime);
var timeZoneId = "America/New_York"];
var timeZone = DateTimeZoneProviders.Tzdb[timeZoneId];
var zonedDateTime = timeZone.AtLeniently(localDateTime);
var utcDateTime = zonedDateTime.ToDateTimeUtc();
注意,本地時間戳可以是不明確的或無效。這種情況發生在夏令時轉換期間,當地時鐘向後移動(造成歧義)或轉發(創建無效時間)。 AtLeniently
方法對如何處理歧義和無效時間戳做出了一些假設。這可能是您的應用程序中的錯誤來源。
當你有一個UTC時間戳,你可以轉換爲本地時間以同樣的方式時區ID:在http://www.citytimezones.info/
var instant = Instant.FromDateTimeUtc(utcDateTime);
var timeZone = DateTimeZoneProviders.Tzdb[timeZoneId];
var zonedDateTime = instant.InZone(timeZone);
var localDateTime = zonedDateTime.ToDateTimeUnspecified();
服用後一看似乎cities.txt
包含Windows時區ID爲最後一列中的每個城市。這使您可以根據城市查找Windows時區ID。
然後,您可以使用此代碼轉換本地DateTime
到UTC:
var timeZoneId = "Eastern Standard Time";
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
var utcDateTime = TimeZoneInfo.ConvertTimeToUtc(localDateTime, timeZoneInfo);
注意ConvertTimeToUtc
如果本地時間戳是模糊的或無效將拋出ArgumentException
。
從UTC爲本地時間的逆變換:
var localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZoneInfo);
如果未來的時區規則發生變化,那麼未來的UTC時間可能會變得不正確。時區規則經常令人驚訝地發生變化。顯然,這個問題適用於所有多時區調度應用程序,我認爲唯一的解決方案是存儲原始本地時間,以便在將來適用的時區規則發生變化時重新計算UTC時間。 –
@MartinLiversage是的,我打算存儲這樣做。調度還會保存當地時間,以便我們可以重新計算UTC時間。 – Emmanuel
我不知道爲什麼這被標記爲「DateTime vs DateTimeOffset」的重複。這太荒謬了,因爲另一個問題甚至沒有談到時區之間的翻譯。充其量,這可能是「谷歌地圖時區API vs DateTimeOffset」,但這是它的延伸。 – Emmanuel