Commit 839c101
committed
fix(time-zone): conversions clamp, adjustment rules validate (#2186)
#2186 asked five System::TimeZone parity questions, each "requiring the .NET
reference or a managed runtime that this container does not have". /rv answers all
five: three repairs, two already correct.
(1) THE CONVERSIONS CLAMP. .NET builds its result through
private static DateTime SafeCreateDateTimeFromTicks(long ticks, DateTimeKind kind = ...)
=> (ulong)ticks <= DateTime.MaxTicks ? new DateTime(ticks, kind)
: (ticks < 0 ? DateTime.MinValue : DateTime.MaxValue);
-- TimeZoneInfo.Cache.cs:340-342
so ConvertTimeFromUtc(DateTime::MaxValue, +14) is MaxValue, not an exception. The
cast to ulong is the whole trick and is reproduced: a negative tick count wraps to
something enormous, so one unsigned comparison rejects both ends at once.
ConvertTime clamps ONCE, at the end. .NET computes the result "from raw ticks to
avoid precision loss from double-clamping" (TimeZoneInfo.cs:683-685), so an
intermediate UTC value that leaves the range must not drag a representable final
answer to a bound. A mutation that clamps twice is caught.
.NET does NOT clamp everywhere, and that is recorded rather than smoothed over: its
invalid-time compatibility path builds a raw `new DateTime(...)` and lets it throw,
with a comment saying so (:661-667). That path needs TimeZoneInfoOptions and
adjustment rules this port's TimeZoneInfo does not model.
(2)+(3) THE THREE VALIDATIONS, AND THE REFERENCE CORRECTS THE TICKET ON TWO OF THEM.
#2179 measured all three as accepted and declined to repair them because "inventing
three more rejections on a recollection of the .NET source is exactly what this
review declines to do". That was right:
* the daylightDelta range is NOT +/-14 hours. It is -23.0 .. 14.0, and .NET
explains why in a comment of its own -- Samoa moved across the International
Date Line, so describing its delta needs -23. THE MESSAGE STILL SAYS "plus or
minus 14.0 hours", because it is shared with UtcOffsetOutOfRange. That
inconsistency is .NET's and is transcribed rather than tidied;
* the seconds check is not "sub-minute". It is "not a whole number of minutes",
so 1h30m30s fails as surely as 30s does;
* the time-of-day check EXEMPTS MinValue for dateStart and MaxValue for dateEnd.
One conjunct of .NET's time-of-day check is `Kind == Unspecified`. This port has no
DateTimeKind (a permanent deviation), so it is absent -- which makes this port
stricter for a UTC-kinded argument and identical for every argument it can express.
(4) TWO QUESTIONS, TWO DIFFERENT ANSWERS. TryFindSystemTimeZoneById returns false
for every failure and already matched: .NET's discards the exception outright
(TimeZoneInfo.cs:526-527). The throwing form was the divergence -- #2183 folded
three failures into one boolean and kept TimeZoneNotFoundException "rather than
guessing InvalidTimeZoneException". .NET raises InvalidTimeZoneException when the
file EXISTS but is not zone data (TimeZoneInfo.Unix.cs:697) and reserves
TimeZoneNotFoundException for an id that names nothing. Those are different answers
to different questions, and a caller catching only the first used to swallow the
second.
(5) ALREADY CORRECT, AND THE REFERENCE CONTAINS A TRAP. TimeZone.CalculateUtcOffset
first decides isDst from the DST window, which puts an ambiguous 01:30 INSIDE
daylight -- and the next line overrides it:
if (isDst && time >= ambiguousStart && time < ambiguousEnd)
isDst = time.IsAmbiguousDaylightSavingTime(); -- TimeZone.cs:237-240
That flag is set only by a prior UTC-to-local conversion, so a DateTime built from
its fields carries false and the answer is the STANDARD offset. Reading only the
window test gives the opposite answer. #2182 chose standard and chose right; the
pin's parenthetical is now a measurement rather than a recollection.
Two gated pins inverted, three cases replacing two. Five mutations, all caught.
Downstream: neither cna nor mobile-eggbert references TimeZoneInfo or TimeZone --
zero sites in both.
Gate: 17,329 run, 17,329 passed, 0 failed, 0 skipped across 38 executables, GREEN.
docs/Migration-TimeZoneClampAndValidation.md1 parent 6404029 commit 839c101
7 files changed
Lines changed: 410 additions & 34 deletions
File tree
- docs
- modules/time-zone
- include/System
- src/System
- tests/System
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
293 | 293 | | |
294 | 294 | | |
295 | 295 | | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
296 | 358 | | |
297 | 359 | | |
298 | 360 | | |
| |||
304 | 366 | | |
305 | 367 | | |
306 | 368 | | |
307 | | - | |
| 369 | + | |
308 | 370 | | |
309 | 371 | | |
310 | 372 | | |
| |||
330 | 392 | | |
331 | 393 | | |
332 | 394 | | |
333 | | - | |
| 395 | + | |
334 | 396 | | |
335 | 397 | | |
336 | 398 | | |
| |||
782 | 844 | | |
783 | 845 | | |
784 | 846 | | |
| 847 | + | |
| 848 | + | |
| 849 | + | |
| 850 | + | |
| 851 | + | |
| 852 | + | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
785 | 878 | | |
786 | 879 | | |
787 | 880 | | |
788 | | - | |
789 | | - | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
790 | 888 | | |
791 | 889 | | |
792 | 890 | | |
| |||
796 | 894 | | |
797 | 895 | | |
798 | 896 | | |
799 | | - | |
| 897 | + | |
| 898 | + | |
800 | 899 | | |
801 | 900 | | |
802 | 901 | | |
| |||
805 | 904 | | |
806 | 905 | | |
807 | 906 | | |
808 | | - | |
| 907 | + | |
| 908 | + | |
809 | 909 | | |
810 | 910 | | |
811 | 911 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
102 | 103 | | |
103 | 104 | | |
104 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
105 | 117 | | |
106 | 118 | | |
107 | 119 | | |
108 | 120 | | |
109 | | - | |
110 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
111 | 128 | | |
112 | 129 | | |
113 | 130 | | |
| |||
262 | 279 | | |
263 | 280 | | |
264 | 281 | | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
265 | 286 | | |
266 | 287 | | |
267 | 288 | | |
| |||
0 commit comments