-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Improve DateTime{Offset}.ParseExact performance for "O"/"o" roundtrip format #18800
Conversation
… format
Ports the code used by Utf8Parser, modified to support things Utf8Parser doesn't but DateTime{Offset{.ParseExact do, such as single-digit offset hours.
| result.SetBadDateTimeFailure(); | ||
| return false; | ||
| } | ||
| result.parsedDate = dateTime.AddTicks((long)Math.Round(fraction * Calendar.TicksPerSecond)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dateTime.AddTicks [](start = 32, length = 17)
is This possible to throw and we get different exception than what we used to get before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By construction I don't believe that's possible, as DateTime.MaxValue is "9999-12-31T23:59:59.9999999", and by this point we've already validated that the DateTime of ""9999-12-31T23:59:59" was created successfully and validated against the calendar. We've also validated that none of the fraction digits are greater than 9, and "9999999" is the largest possible value this can be.
Is there another way this could manifest? We were very skimpy on coverage here, so I added a bunch of tests in dotnet/corefx#30860, including for MaxValue:
https://github.com/dotnet/corefx/pull/30860/files#diff-a7a9c52518e52358d4f3ab8e88cbf53fR963
but if you see something missing, I can rectify that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"9999-12-31T23:59:59.9999999Z" if you parse this when having TZ before UTC (e.g. Fuji +12) this should fail the parsing. in most cases, we'll get the right exception but there is will be specific values which can cause the exception only when adding the fraction ticks per second. I can try to get the exact data if you like.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should fail the parsing
Yes... but the factoring in of timezone doesn't happen until after this point, down at the bottom of the method where it calls DetermineTimeZoneAdjustments. At this point, we've called DateTime.TryCreate, using only the data from "9999-12-31T23:59:59", creating a DateTimeKind.Unspecified, and we add the "9999999" fraction to that. It's only after this AddTicks that we then parse the 'Z' and factor in the timezone as part of DetermineTimeZoneAdjustments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, we should be fine then. thanks for clarifying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes me happy that 7,981 years from now (perhaps on another star system) our code will function correctly because we took care to correctly handle the year 9,999. 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we're very forward thinking.
Ports the code used by Utf8Parser, modified to support things Utf8Parser doesn't but DateTime{Offset{.ParseExact do, such as single-digit offset hours.
Local times (w/o timezone) improve by ~6x.
Times with timezones improve by ~2.5-2.75x.
All cases reduce allocations from 120 bytes across 5 objects down to 0.
Benchmark:
Before:
After:
cc: @jkotas, @danmosemsft, @tarekgh, @joperezr, @joperezr
Contributes to https://github.com/dotnet/corefx/issues/30612