DateTime.TryParse无法解析DateTime.MinValue

Ala*_*ain 6 c# datetime json .net-4.0 json.net

我正在使用一个名为Json.NET的库,它在内部使用以下代码将JSON字符串解析为DateTime:

if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
     dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
     SetToken(JsonToken.Date, dt);
     return dt;
}
Run Code Online (Sandbox Code Playgroud)

我认为Json.NET搞砸了转换,但看起来它是DateTime.TryParse本身就是拙劣的价值.

当我解析以下有效的Iso日期(对应于UTC DateTime.MinValue)时:

string json = "0001-01-01T00:00:00+00:00";
DateTime dt;
DateTime.TryParse(json, invariantCulture, DateTimeStyles.RoundtripKind, out dt);
Run Code Online (Sandbox Code Playgroud)

结果是一个本地化的DateTime : {0001-01-01 8:00:00 PM},当转换回Utc时给出{0001-01-02 0:00:00 PM}.基本上,日期下溢,这正是您期望DateTimeStyles.RoundtripKind要避免的问题.

我该如何避免这种情况?

Dou*_*oug 3

为什么使用 DateTimeStyles.RoundtripKind?RoundtripKind 的文档说:

当使用“o”或“r”标准格式说明符将 DateTime 对象转换为字符串,然后将该字符串转换回 DateTime 对象时,会保留日期的 DateTimeKind 字段。

“o”或“r”标准格式说明符输出的字符串与您尝试解析的 ISO 8601 字符串不同。在我看来,RoundtripKind 并不真正应该适用于任何日期时间字符串格式。当字符串采用特定格式时,听起来好像往返是针对 DateTime.Kind 属性的。

既然您知道要解析的字符串的格式,那么我建议使用 DateTime.TryParseExact。

我必须支持几个不同版本的 ISO 8601 字符串 - 这些格式中的任何一个都是 ISO 8601 中的有效日期时间值(并且对于日期、时间和小数秒还有更多选项,但我没有这些) :

0001-01-01T00:00:00+00:00

0001-01-01T00:00:00Z

这是一个可以处理这两种格式的方法:

private bool TryParseIso8601(string s, out DateTime result)
{
    if (!string.IsNullOrEmpty(s))
    {
        string format = s.EndsWith("Z") ? "yyyy-MM-ddTHH:mm:ssZ" : "yyyy-MM-ddTHH:mm:sszzz";
        return DateTime.TryParseExact(s, format, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out result);
    }

    result = new DateTime(0L, DateTimeKind.Utc);
    return false;
}
Run Code Online (Sandbox Code Playgroud)