2015-10-09 22 views
4

我在Web服務中實現條件請求。後端可以輕鬆地檢索實體的最後修改日期,所以我發送Last-Modified並獲取If-Modified-Since。 RFC for HTTP Dates指定的格式與"R" format specifier in .NET相同。爲什麼不DateTime.ToString(「R」)和DateTime.TryParseExact往返?

的問題是,DateTime.ToString("R")正確格式化日期,但經過"R"ParseExact不讀取時區回(有一個「往返」符,"O",但它不是在我需要的格式)。下面是LinqPad一個例子:

DateTime lastModified = new DateTime(2015, 10, 01, 00, 00, 00, DateTimeKind.Utc); 
string lastModifiedField = lastModified.ToString("R"); // Thu, 01 Oct 2015 00:00:00 GMT 
DateTime ifModifiedSince = DateTime.ParseExact(
    lastModifiedField, "R", CultureInfo.InvariantCulture); 

ifModifiedSince.Kind.Dump(); // Unspecified 

我當然可以用在解析DateTime方法來迫使它進入我想要的格式,但我怎麼能得到的框架,使用已經存在的數據?

回答

7

我偶然發現瞭解釋這一點的參考資源,因此提出並回答了我自己的問題。

source to datetimeparse.cs表示這是一個無法修復兼容性的bug。

// The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot 
// correct this mistake for DateTime.ParseExact for compatibility reasons, but we can 
// fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released 
// with this issue. 

所以這個註釋後面由兩個DateTime.ParseExact和DateTimeOffset.ParseExact調用,該代碼表明在DateTimeOffset.ParseExact更正確的效果。事實上,根據對choosing between DateTime and DateTimeOffset文檔:

這些用途的DateTimeOffset值比 DATETIME值更爲常見。因此,應將DateTimeOffset視爲應用程序開發的缺省日期和時間類型 。

因此,理想的解決方案是切換到的DateTimeOffset,但如果你仍然需要日期時間:

DateTime lastModified = new DateTime(2015, 10, 01, 00, 00, 00, DateTimeKind.Utc); 
string lastModifiedField = lastModified.ToString("R"); 
DateTimeOffset ifModifiedSinceOffset = DateTimeOffset.ParseExact(
    lastModifiedField, "R", CultureInfo.InvariantCulture); 
DateTime ifModifiedSince = ifModifiedSinceOffset.UtcDateTime; 

ifModifiedSince.Kind.Dump(); // Utc 

哪個正確識別的時區爲GMT/UTC,從而設置在日期時間將正確的屬性。

+0

是的,這是很好的 - 除了注意最後的'Kind'將*總是* Utc',因爲你從'.UtcDateTime'獲得了它。但至少解析是正確的。你也會注意到'DateTime.Parse' * does *工作 - 至少當你通過'DateTimeStyles.RoundtripKind'的時候。只有'DateTime.ParseExact'沒有。 –

+0

當然 - 最好是使用ISO8601而不是這種可怕的格式,但仍然 - 很好的抓住! –

+0

另外,你可能想在https://github.com/dotnet/coreclr/issues上記錄這個 - 看起來很愚蠢,不能解決它。 –

相關問題