Reputation: 1210
We have a Scala/Java back end that is generating the equivalent of DateTime.MaxValue
in .NET.
I am sent the following date as a string "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).
I didn't expect this, since I was calling TryParse. Perhaps returning false would have been more intuitive?
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!
DateTime.TryParse("9998-12-31T23:59:59.999999999Z", out var dateTime);
dateTime.ToString().Dump();
Outputs: 01/01/9999 00:00:00
If I reduce the precision of the ms by 2, then it works:
DateTime.TryParse("9998-12-31T23:59:59.9999999Z", out var dateTime);
dateTime.ToString().Dump();
Outputs: 31/12/9998 23:59:59
This really looks like a bug in .NET? Is this expected behaviour?
Upvotes: 14
Views: 3558
Reputation: 11
Adding DateTimeStyles.AdjustToUniversal
as argument fix it for .NET Framework
e.g. for Windows Powershell:
$d = [DateTime]::Parse("9999-12-31T23:59:59.9999999Z", $null, 16)
Get-Date $d
Upvotes: 1
Reputation:
You have too many nines in your string. 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", i.e. two less nines at the end.
Use "9999-12-31T23:59:59.9999999Z"
as an input and it will parse successfully into DateTime.MaxValue.
PS: TryParse will also convert this value to your local timezone, which I assume is not somewhat you would anticipate. Use extended version instead:
DateTime.TryParse("9999-12-31T23:59:59.9999999Z", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime);
Upvotes: 2
Reputation: 846
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:
Replace special values in your Scala/Java output with your own "encoding". For example as "MaxValue", or take your pick as your see fit. On the .Net side you will detect special values and translate them accordingly.
Insert some simple preprocessing into your .Net code. For example check
"9999-12-31T23:59:59.999999999".StartsWith("9999")
for max values.
Upvotes: 1