为什么没有DateTime.ToString("R")和DateTime.TryParseExact往返?

Ste*_*ard 4 c# datetime datetimeoffset

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

问题是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
Run Code Online (Sandbox Code Playgroud)

我当然可以使用解析的方法DateTime来迫使它进入我想要的格式,但我怎么能得到的框架,使用已经存在的数据?

Ste*_*ard 7

我偶然发现了解释这个问题的参考资料,因此提出并回答了我自己的问题.

所述源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.
Run Code Online (Sandbox Code Playgroud)

因此,此注释所在的代码由DateTime.ParseExact和DateTimeOffset.ParseExact调用,并且实际上建议DateTimeOffset.ParseExact更正确.实际上,根据在DateTime和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
Run Code Online (Sandbox Code Playgroud)

这正确地将时区标识为GMT/UTC,从而在DateTime上设置正确的属性.