2016-09-19 77 views
5

我正在閱讀回答者的帖子here,我遇到了這個我試圖理解的調查員DateTimeStyles.RoundtripKind。我看着MSDN here它說:DateTimeStyles.RoundtripKind枚舉是什麼意思?

當DateTime對象 被轉換爲使用「○」或「r」標準格式 說明符字符串的日期的DateTimeKind字段被保留,並且該字符串是然後轉換回DateTime對象。

在後輸入時間戳我提到是這樣的:

<timestamp time='2016-09-16T13:45:30'> 

我跑到她的代碼,它仍然有效。現在,它是所有一團糟連接所有我掌握的信息:

  1. 上述時間標記包含了一些標識T
  2. MSDN文檔談到or格式說明它不知道是什麼?
  3. 如果您在MSDN鏈接上查詢更多關於DateTimeKind枚舉的詳細信息,我已經在上面引用了它,並沒有提到or格式說明符。 Here是說的鏈接:

成員名稱說明

本地=>爲代表的時間是當地時間。

未指定=>所表示的時間未指定爲本地時間或協調世界時(UTC)。

Utc =>所代表的時間是UTC。

P.S.我試着在上面創建一個表,但它似乎沒有本地支持創建表格結構。

那麼有人可以幫我理解DateTimeStyles.RoundtripKind枚舉和它是如何工作的?

+2

有關o和r的詳細信息,請參閱https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx –

+1

「T」只是ISO-8601的一部分格式 –

+1

在示例中,「T」不是格式說明符。 –

回答

6

所以,我終於能理解這一點,並在這裏共享相同的信息,如果它可以爲他人有所幫助過:

第一部分是轉換C#DateTime對象轉換爲字符串。有很多格式說明符可以做到這一點,但對於我們來說,關於DateTimeStyles.RoundtripKind,「r」和「o」格式說明符是我們關心的。您可以看到所有日期時間格式說明符here。請參閱使用的格式說明,當我們做轉換髮生在代碼是什麼:

//r corresponds to RFC 1123 format (GMT date time format) 
var gmtDateTimeString = DateTime.Now.ToString("r"); //gives Fri, 23 Sep 2016 15:39:21 GMT 

//o corresponds to ISO 8601 (Local date time format) 
var localDateTimeString = DateTime.Now.ToString("o"); //gives 2016-09-23T15:39:21.8899216+05:30 

你可以清楚地看到,字符串日期時間是輸出有提示嵌入了信息:

  • Fri, 23 Sep 2016 15:39:21 GMTDateTimeKind.Utc( 「GMT」 文本存在時)
  • 2016-09-23T15:39:21.8899216+05:30表示DateTimeKind.Local的日期時間( 「T」 字的存在按照ISO 8601標準)

現在來看第二部分。如果我必須將這些日期時間字符串gmtDateTimeStringlocalDateTimeString轉換回日期時間對象,那麼我們需要解析它們。因此,在DateTimeStyles.RoundtripKind枚舉值的幫助下,您將傳遞給DateTime.Parse API,它實際上表示時區信息已經在字符串中烘焙,並且API會使用該信息適當地分析日期時間。

通常,當日期時間數據以XML格式通過網絡傳輸時,則使用ISO 8601格式,這是我在發佈此主題中提到的問題之前所引用的帖子中看到的。因此,在解析從XML文檔獲得的日期時間字符串時,根據字符串中存在的時區信息使用DateTimeStyles.RoundtripKind來獲取正確的日期時間值是適當的。

2

往返格式是爲了「機器消耗」 - 它可以很容易地解析回相同的DateTime值。
其他大多數格式都是爲了「人類消費」,向一個人展示日期(可能包括時間)。

2

我很難理解其他答案,所以我決定自己做一些研究。幸運的是,.NET庫的源代碼可以在線獲得。

DateTimeStyles.RoundTripKind has a comment in the source

// Attempt to preserve whether the input is unspecified, local or UTC 

它或多或少正如含糊上DateTimeStyles.RoundTripKind MSDN文檔:

當DateTime對象轉換爲一個日期的DateTimeKind字段被保留字符串使用「o」或「r」標準格式說明符,然後將該字符串轉換回DateTime對象。

通過瀏覽Reference Source網站,可以看出DateTimeStyles.RoundTripKind的使用非常少。實質上,如果該標誌被設置,則it may modify the kind of the DateTime to DateTimeKind.Utc。因此,這是設置此標誌的效果:有時,解析的DateTime值的Kind屬性設置爲Utc

恰好當這種情況發生時,由內部標誌ParseFlags.TimeZoneUtc控制。確定何時設置此標誌更爲複雜,但據我所知,如果使用ZGMT指定時區,解析器將設置此標誌。有a comment about this in the source code

// NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time). 

我的結論是,如果一個時間戳使用格式化或者orDateTimeStyles.RoundTripKind在解析時間戳然後將得到的DateTimeKind是,如果時區的設置爲Utc使用字符串是UTC時區。

但是,如果未設置標誌,會發生什麼情況?確定這一點的最好方法是對兩種格式說明符進行一些實際測試。

往返(「O」,「O」)格式說明

當使用o格式說明時間戳的時區要麼是Z對於UTC或+/-的從UTC偏移(例如2017-02-26T22:55:15.4923368+01:00) 。下面是顯示DateTime值從往返時間戳解析的Kind屬性的值表:

 
Timezone | RoundTripKind | Kind 
---------+---------------+------ 
"Z"  | Not specified | Local 
"Z"  | Specified  | Utc 
Not "Z" | Not specified | Local 
Not "Z" | Specified  | Local 

如果要分析在往返格式的時間戳和您所期望的時區時間戳爲UTC,則應指定DateTimeStyles.RoundTripKind以確保解析的DateTime值具有種類Utc

的RFC1123(「R」,「R」)格式說明

當使用r格式說明的時間戳將總是包含GMT(即使那種原來DateTime的是不Utc),因此表對於r格式不需要Timezone列。然而,我發現,DateTime.ParseDateTime.ParseExact不同的行爲時,RFC1123時間戳解析:

 
Method  | RoundTripKind | Kind 
-----------+---------------+------------ 
Parse  | Not specified | Local 
Parse  | Specified  | Utc 
ParseExact | Not specified | Unspecified 
ParseExact | Specified  | Unspecified 

當使用Parse方法在RFC1123格式的時間戳的行爲一樣往返格式的UTC時間戳。但是,由於某些原因,ParseExact方法忽略DateTimeStyles.RoundTripKind標誌。當分析往返格式的時間戳時,情況並非如此。

如果你想在解析格式RFC1123的時間戳您應該使用Parse方法,並指定DateTimeStyles.RoundTripKind,或者如果你喜歡ParseExact方法,你將不得不修改的那種解析時間戳來Utc。您可以使用DateTime.SpecifyKind方法創建新時間戳。

結論

當解析往返和RFC1123時間戳指定DateTimeStyles.RoundTripKind,以確保解析DateTimeKind屬性爲Utc

如果往返時間戳具有非零偏移量,那麼您將不得不將時間戳解析爲DateTimeOffset值以保留偏移量(Local不會告訴您偏移量是什麼 - 只是它可能不同於0)。

請勿使用DateTime.ParseExact解析RFC1123時間戳(或在解析時間戳後將類型更改爲Utc)。