【问题标题】:Why don't DateTime.ToString("R") and DateTime.TryParseExact round trip?为什么不 DateTime.ToString("R") 和 DateTime.TryParseExact 往返?
【发布时间】:2015-10-09 20:02:43
【问题描述】:

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

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

【问题讨论】:

    标签: c# datetime datetimeoffset


    【解决方案1】:

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

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

    【讨论】:

    • 是的,这很好 - 除了注意最后的Kind始终Utc,因为您是从.UtcDateTime 获得的。但至少解析是正确的。您还会有兴趣观察 DateTime.Parse 确实 工作 - 至少当您通过 DateTimeStyles.RoundtripKind 时它确实有效。只有DateTime.ParseExact 没有。
    • 当然 - 最好使用 ISO8601 而不是这种可怕的格式,但仍然 - 很好!
    • 另外,您可能想在github.com/dotnet/coreclr/issues 记录此问题 - 不修复它似乎很愚蠢。
    • @MattJohnson,评论说出于兼容性目的他们无法修复它,我明白他们的意思。而且我同意这种格式很愚蠢(为什么要在计算机读取的字段中包含星期几)但我试图遵循 IRC 正是因为每隔一段时间拥有一个规范是一种奢侈。 ;)
    • 谢谢,但我不同意保留这个错误。我在这里记录:github.com/dotnet/coreclr/issues/1757
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多