为什么不使用DateTime.ToString(" R")和DateTime.TryParseExact往返?

时间:2015-10-09 20:02:43

标签: c# datetime datetimeoffset

我在Web服务中实现条件请求。后端可以轻松检索实体的最后修改日期,因此我发送Last-Modified并返回If-Modified-Since。 RFC for HTTP Dates指定的格式与"R" format specifier in .NET相同。

问题是DateTime.ToString("R")正确地格式化了日期,但是将"R"传递给ParseExact并没有读回时区(有一个"往返行程& #34;说明符,"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上使用方法强制它使用我想要的格式,但是如何让框架使用已经存在的数据?

1 个答案:

答案 0 :(得分:7)

我偶然发现了解释这一点的参考资料来源,因此询问并回答了我自己的问题。

source to datetimeparse.cs表示这是一个无法修复以便兼容的错误。

// 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:

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,从而在DateTime上设置正确的属性。