简体   繁体   English

.NET 中的日期时间溢出

[英]DateTime Overflow in .NET

We have a Scala/Java back end that is generating the equivalent of DateTime.MaxValue in .NET.我们有一个 Scala/Java 后端,它在 .NET 中生成等效的DateTime.MaxValue

I am sent the following date as a string "9999-12-31T23:59:59.999999999Z".我收到以下日期作为字符串“9999-12-31T23:59:59.999999999Z”。

If I used DateTime.TryParse("9999-12-31T23:59:59.999999999Z", out var dateTime) , then it throws an ArgumentOutOfRangeException (The added or subtracted value results in an un-representable DateTime.Parameter name: value).如果我使用DateTime.TryParse("9999-12-31T23:59:59.999999999Z", out var dateTime) ,那么它会抛出ArgumentOutOfRangeException (添加或减去的值会导致无法表示的 DateTime.Parameter name: value)。

I didn't expect this, since I was calling Try Parse.我没想到会这样,因为我正在调用Try Parse。 Perhaps returning false would have been more intuitive?也许返回 false 会更直观?

If I reduce the year, I can see .NET is rolling the date over to the following day, which obviously wont work on a max date/time!如果我减少年份,我可以看到 .NET 将日期滚动到第二天,这显然不适用于最大日期/时间!

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

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

If I reduce the precision of the ms by 2, then it works:如果我将 ms 的精度降低 2,那么它可以工作:

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

Outputs: 31/12/9998 23:59:59输出:31/12/9998 23:59:59

This really looks like a bug in .NET?这看起来真的像 .NET 中的错误? Is this expected behaviour?这是预期的行为吗?

You have too many nines in your string. 你的字符串中有太多的9。 The exception you observing is the precision issue. 您观察到的异常是精度问题。

Try doing the following: 尝试执行以下操作:

DateTime.MaxValue.ToString("o")
it will result in "9999-12-31T23:59:59.9999999" rather than "9999-12-31T23:59:59.999999999Z", ie two less nines at the end. 它将导致“9999-12-31T23:59:59.9999999”而不是“9999-12-31T23:59:59.999999999Z”,即最后两个小九。

Use "9999-12-31T23:59:59.9999999Z" as an input and it will parse successfully into DateTime.MaxValue. 使用"9999-12-31T23:59:59.9999999Z"作为输入,它将成功解析为DateTime.MaxValue。

PS: TryParse will also convert this value to your local timezone, which I assume is not somewhat you would anticipate. PS:TryParse还会将此值转换为您当地的时区,我认为这并不是您所期望的。 Use extended version instead: 使用扩展版本:

 DateTime.TryParse("9999-12-31T23:59:59.9999999Z", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime); 

Adding DateTimeStyles.AdjustToUniversal as argument fix it for .NET Framework添加DateTimeStyles.AdjustToUniversal作为参数修复它为 .NET 框架

eg for Windows Powershell:例如对于 Windows Powershell:

$d = [DateTime]::Parse("9999-12-31T23:59:59.9999999Z", $null, 16)
Get-Date $d

Passing Min/Max/Infinity and etc. values between different platforms is a bad idea. 在不同平台之间传递最小/最大/无限等值是个坏主意。 Each platform might have its own representation of special values (not only dates). 每个平台可能都有自己的特殊值表示(不仅仅是日期)。 Therefore the only valid option is to pass epoch values (milliseconds options are preferable in most cases), since they are known to the both parties. 因此,唯一有效的选择是传递纪元值(在大多数情况下,毫秒选项是优选的),因为它们是双方都知道的。

If the above is impossible for some reason then you have two ugly options: 如果上述因某些原因无法实现,那么您有两个丑陋的选择:

  1. Replace special values in your Scala/Java output with your own "encoding". 使用您自己的“编码”替换Scala / Java输出中的特殊值。 For example as "MaxValue", or take your pick as your see fit. 例如,作为“MaxValue”,或者根据您的需要选择。 On the .Net side you will detect special values and translate them accordingly. 在.Net端,您将检测特殊值并相应地进行转换。

  2. Insert some simple preprocessing into your .Net code. 在.Net代码中插入一些简单的预处理。 For example check "9999-12-31T23:59:59.999999999".StartsWith("9999") for max values. 例如,检查"9999-12-31T23:59:59.999999999".StartsWith("9999")表示最大值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM