2008-10-07 240 views
244

我們正在爲Web服務客戶端開發C#應用程序。這將在Windows XP PC上運行。將UTC/GMT時間轉換爲當地時間

Web服務返回的字段之一是DateTime字段。服務器以GMT格式返回一個字段,即最後以「Z」結尾。

但是,我們發現.NET似乎做了某種隱式轉換,時間總是12小時。

下面的代碼示例在一定程度上解決了這個問題,因爲12小時的差異已經消失,但它不允許新西蘭夏令時。

CultureInfo ci = new CultureInfo("en-NZ"); 
string date = "Web service date".ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    

this date site

UTC/GMT偏移

標準時區:UTC/GMT12小時
夏令時間:1小時
目前時區偏移:UTC/GMT +13小時

我們如何調整額外的小時?這可以通過編程來完成嗎?或者這是PC上的某種設置?

+1

了`Z`時間是指UTC,而不是GMT。這兩者可以相差最多0.9秒。 – mc0e 2017-02-27 04:30:07

回答

42
TimeZone.CurrentTimeZone.ToLocalTime(date); 
+8

這隻有在系統知道正在轉換的日期是UTC時纔有效。請看我的答案。 – 2009-06-08 07:44:19

+1

但UTC是默認的,不是嗎?因此它適用於CJ7的答案中的「未指定」。 – NickG 2013-06-12 14:06:05

2

在回答德納的建議:

的代碼示例現在看起來像:

string date = "Web service date"..ToString("R", ci); 
DateTime convertedDate = DateTime.Parse(date);    
DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate); 

原來的日期是20/08/08;那種是UTC。

兩者 「convertedDate」 和 「DT」 是相同的:

21/08/08 10點00分26秒;那種是本地的

+0

請參閱我的答案對此進行解釋。 – 2009-06-08 07:46:35

1

我有一個數據集被推送通過線(web服務到客戶端),它會自動更改,因爲DataColumn的DateType字段設置爲本地的問題。確保你檢查什麼DateType是如果你推動DataSets跨。

如果你不想讓它改變,其設置爲未指定

13

我只是想補充謹慎的備忘。

如果您所做的只是從計算機的內部時鐘獲取當前時間以在顯示屏或報表上輸入日期/時間,則一切正常。但如果你是保存日期/時間信息供以後參考或者計算日期/時間,請注意!

假設您確定一艘郵輪於2007年12月20日15:00 UTC抵達檀香山。你想知道當地時間是什麼。
1.可能至少有三個「本地人」參與其中。本地可能意味着檀香山,或者它可能意味着您的計算機所在的位置,或者它可能意味着您的客戶所在的位置。
2。如果使用內置函數進行轉換,則可能是錯誤的。這是因爲夏令時(可能)目前在您的計算機上生效,但在十二月份不生效。但Windows不知道這一點......它只有一個標誌來確定夏令時是否正在生效。如果目前正在實施,那麼它甚至會在12月份的某個日期快樂地增加一個小時。
3.夏令時在各個政治分支中的實施方式不同(或根本不同)。不要認爲,僅僅因爲你的國家在特定的日期發生變化,其他國家也會這樣做。

+5

其實#2並不完全正確。事實上,在每個時區都有關於DST的規則,您的計算機將知道信息是否已安裝(和更新)。對於許多區域來說,這些規則是固定的。其他人實施「動態DST」。巴西是我的寵兒。總而言之,如果您的當地時間是十二月份的DST,假設現在和之後沒有任何變化通過法律,您的計算機可以計算出您的當地時間。 – 2011-06-16 12:04:04

+0

即使你不住在巴西,DST也是「有活力的」,因爲政治家可以隨時改變它(就像幾年前在美國所做的那樣)。由於大多數軟件都是爲了將​​來的使用而編寫的,因此意識到沒有實用的,可預測的甚至是理論的方式來了解DST規則將會生效。你可以靠近,但通過放棄完美來拯救自己一些挫敗感。 – DaveWalley 2014-05-14 20:45:31

4

如果你已經有了一個DateTime對象,不知道這是否是UTC或本地不要忘了,這是很容易使用,直接在物體上的方法:

DateTime convertedDate = DateTime.Parse(date); 
DateTime localDate = convertedDate.ToLocalTime(); 

我們如何調整額外的一小時?

除非指定.net將使用本地pc設置。我有一個讀:http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

通過長相代碼可能看起來像:

DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges(year); 

和上面仔細檢查所提到什麼時區設置您的服務器上。網上有關於如何安全地影響IIS中的更改的文章。

+0

只要你告訴系統你的日期是什麼樣的(本地/ utc /未指定),系統會爲你處理這種情況。 – 2009-06-08 07:47:43

103

我打算使用System.TimeZoneInfo類,如果你在.NET 3.5。見http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx。這應該考慮到夏令時更改正確。

// Coordinated Universal Time string from 
// DateTime.Now.ToUniversalTime().ToString("u"); 
string date = "2009-02-25 16:13:00Z"; 
// Local .NET timeZone. 
DateTime localDateTime = DateTime.Parse(date); 
DateTime utcDateTime = localDateTime.ToUniversalTime(); 

// ID from: 
// "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone" 
// See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx 
string nzTimeZoneKey = "New Zealand Standard Time"; 
TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey); 
DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone); 
+0

如果你在自己的時區(在這種情況下是en-NZ)工作,那麼你不需要處理TimeZoneInfo。這只是不必要的複雜性。看到我的答案更詳細。 – 2009-06-08 07:45:20

+32

+1不假設服務器在新西蘭 – ajbeaven 2010-09-07 07:02:11

329

字符串,例如2012-09-19 01:27:30.000DateTime.Parse分不清哪個時區的日期和時間是從。

DateTime屬性,它可以有三個時區選項之一:

  • 不明
  • 本地
  • UTC

注意如果你是希望代表UTC以外的日期/時間或當地時間e區,那麼你應該使用DateTimeOffset


所以對於你的問題代碼:

DateTime convertedDate = DateTime.Parse(dateStr); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified 

你說你知道它是什麼樣的,所以告訴它。現在

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr), 
    DateTimeKind.Utc); 

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc 

,一旦系統知道它的UTC時間,你可以叫ToLocalTime

DateTime dt = convertedDate.ToLocalTime(); 

這會給你所需要的結果。

1

我遇到了這個問題,因爲我在通過twitter API(status上的created_at字段)返回的UTC日期有問題;我需要將它們轉換爲DateTime。本頁答案中沒有任何答案/代碼樣本足以阻止我得到「字符串未被識別爲有效的DateTime」錯誤(但它是最接近我必須在SO上找到正確答案)

這裏張貼此鏈接的情況下,這可以幫助別人 - 我所需要的答案在這個博客帖子發現:http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - 基本上使用DateTime.ParseExact與格式字符串代替DateTime.Parse

15

我知道這是一個老問題,但我遇到了類似的情況,我想分享我爲未來的搜索者找到的東西,可能包括我自己:)。

DateTime.Parse()可能會很棘手 - 例如參見here

如果DateTime從Web服務或一些其它音源與已知的格式來了,你可能要考慮像

DateTime.ParseExact(dateString, 
        "MM/dd/yyyy HH:mm:ss", 
        CultureInfo.InvariantCulture, 
        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) 

,或者甚至更好,

DateTime.TryParseExact(...) 

AssumeUniversal標誌告訴解析器日期/時間已經是UTC; AssumeUniversalAdjustToUniversal的組合告訴它不要將結果轉換爲「本地」時間,默認情況下它會嘗試執行。 (我個人試圖在業務/應用/服務層中專門處理UTC,但繞過本地時間的轉換也會加快速度 - 在我的測試中速度增加50%或更多,請參閱下文。)

下面是我們在做什麼之前:我們已經成型的應用,發現DateTime.Parse代表CPU的使用顯著比例

DateTime.Parse(dateString, new CultureInfo("en-US")) 

。 (順便說一句,CultureInfo構造是一個顯著貢獻者CPU使用率。)

所以我成立了一個控制檯應用程序來解析日期/時間字符串10000次各種方式。底線:
Parse() 10秒
ParseExact()(轉換爲本地)20-45毫秒
ParseExact()(未轉換爲本地)10-15毫秒
...是,對於Parse()結果是在 ,而其他人在毫秒

15

DateTime對象默認情況下有KindUnspecified,對於ToLocalTime的用途假定爲UTC

爲了得到一個UnspecifiedDateTime對象的本地時間,所以你只需要做到這一點:

convertedDate.ToLocalTime(); 

改變DateTimeUnspecifiedKindUTC的步驟是不必要的。Unspecified被假定爲UTCToLocalTime目的:http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

1
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)