C# 为什么不';t DateTime.ToString(";R";)和DateTime.TryParseExact往返?

C# 为什么不';t DateTime.ToString(";R";)和DateTime.TryParseExact往返?,c#,datetime,datetimeoffset,C#,Datetime,Datetimeoffset,我正在Web服务中实现条件请求。后端可以轻松检索实体的最后修改日期,因此我将发送last modified,并在修改后返回。指定与相同的格式 问题是DateTime.ToString(“R”)格式正确,但是将“R”传递到ParseExact不会读回时区(有一个“往返”说明符,“O”,但它不是我需要的格式)。以下是LinqPad中的一个示例: DateTime lastModified = new DateTime(2015, 10, 01, 00, 00, 00, DateTimeKind.Ut

我正在Web服务中实现条件请求。后端可以轻松检索实体的最后修改日期,因此我将发送last modified,并在修改后返回。指定与相同的格式

问题是
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
上的方法将其强制转换为我想要的格式,但是我如何才能让框架使用已经存在的数据呢?

我偶然发现了解释这一点的参考源,因此提出并回答了我自己的问题

表示这是一个无法修复兼容性的错误

// 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更正确。事实上,根据以下文件:

DateTimeOffset值的这些用法比那些更常见 用于日期时间值。因此,应该考虑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上设置正确的属性。

是的,这很好-但请注意,最终的
种类将始终是
UTC
,因为您是从
.UtcDateTime
获得它的。但至少解析是正确的。您还将有兴趣观察到,
DateTime.Parse
确实有效-至少在传递
datetimestyle.RoundtripKind
时有效。只有
DateTime.ParseExact
没有。当然-最好使用ISO8601而不是这种可怕的格式,但仍然-很好!另外,您可能希望将此记录在-不修复它似乎很愚蠢。@MattJohnson,评论说他们无法出于兼容性目的修复它,我明白他们的观点。我同意这种格式是愚蠢的(为什么要在一个供计算机阅读的字段中包含一周中的某一天),但我正是试图遵循IRC,因为每隔一段时间就有一个规范是一种奢侈谢谢,但是我不同意把这个错误保留下来。我把它记录在这里: