代码之家  ›  专栏  ›  技术社区  ›  David Kiff

.NET中的日期时间溢出

  •  12
  • David Kiff  · 技术社区  · 8 年前

    我们有一个Scala/Java后端,它生成了 DateTime.MaxValue 在.net中。

    以下日期作为字符串“9999-12-31T23:59:59.99999999 Z”发送给我。

    如果我用 DateTime.TryParse("9999-12-31T23:59:59.999999999Z", out var dateTime) ,然后它抛出一个 ArgumentOutOfRangeException (添加或减去的值将导致无法表示DateTime。参数名称:value)。

    我没想到会这样,因为我打电话来 尝试 分析。或许,以假乱真会更直观些?

    如果我减少年份,我可以看到.NET正在将日期滚动到第二天,这显然不适用于最大日期/时间!

    DateTime.TryParse("9998-12-31T23:59:59.999999999Z", out var dateTime);
    dateTime.ToString().Dump();
    

    输出:01/01/9999 00:00:00

    如果我将ms的精度降低2,那么它可以工作:

    DateTime.TryParse("9998-12-31T23:59:59.9999999Z", out var dateTime);
    dateTime.ToString().Dump();
    

    输出:1998年12月31日23:59:59

    这真的像.net中的一个bug吗?这是预期的行为吗?

    2 回复  |  直到 8 年前
        1
  •  1
  •   user6674679user6674679    7 年前

    你的弦子里有太多的9你所观察到的例外是精确性问题。

    尝试执行以下操作:

    DateTime.MaxValue.ToString("o")
    
    它将导致“9999-12-31T23:59:59.9999999”而不是“9999-12-31T23:59:59.9999999Z”,即在最后减少两个9。

    使用 "9999-12-31T23:59:59.9999999Z" 作为输入,它将成功解析为DateTime.MaxValue。

    注:tryparse还将把这个值转换为您的本地时区,我认为这并不是您所期望的。改用扩展版本:

    DateTime.TryParse("9999-12-31T23:59:59.9999999Z", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime);
    
        2
  •  -1
  •   Bennie Zhitomirsky    7 年前

    在不同平台之间传递min/max/infinity等值是个坏主意。每个平台可能都有自己的特殊值表示(不仅仅是日期)。因此,唯一有效的选项是传递epoch值(在大多数情况下,毫秒选项更可取),因为双方都知道它们。

    如果由于某种原因,上述情况是不可能的,那么你有两个 丑陋的 选项:

    1. 用自己的“编码”替换Scala/Java输出中的特殊值例如“MaxValue”,或者根据需要选择在.NET端,您将检测到特殊值并相应地转换它们。

    2. 在.NET代码中插入一些简单的预处理。例如检查 "9999-12-31T23:59:59.999999999".StartsWith("9999") 对于最大值。