Repository navigation
Conversation
A Local/Unspecified DateTime is a JS Date whose local fields held its clock time, and every field read, ToString and Add* went through them. A clock time the zone skips (02:30 on a spring-forward night) therefore read as 03:30, Add* across a DST switch gained or lost that hour, and a date before the zone's first whole-minute offset read wrong fields. .NET treats all of this as tick arithmetic, whatever the kind. The Date's instant is kept real, since JavaScript interop reads it. Field reads, getDate/getTimeOfDay/getDayOfYear and format go through $clock (a Date whose UTC fields hold the ticks), create takes its ticks from the clock fields, and every Add* is tick arithmetic through $addUnits, which follows .NET 7+'s AddUnits (sub-millisecond ticks are kept; the old AddDays(-1.5) moved 2.5 days). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013thoEGD8RmeKXh9jAqp6UV
pfriesch
added this pull request to stack #178
October 19, 2026 15:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Local/Unspecified
DateTimeread its fields and did its arithmetic through the JSDate's local fields. Around a DST switch, that moved or lost an hour. .NET treats all of this as tick arithmetic, whatever the kind. Stacked on #175. This PR is the large runtime rewrite of the stack, which is why it is on its own.new DateTime(2020, 3, 29, 2, 30, 0)(a skipped hour).ToString("O")03:3002:30.AddHours(1)04:3003:30new DateTimeOffset(t, +1h).UtcDateTime02:30Z01:30Z2020-11-01 01:30(+1h) + 5h, as UTC04:30Z05:30ZKey Changes
BCL/Transpose.BCL/Resources/Date.js):$clock(d)returns a Date whose UTC fields holdd's ticks.getYear…getMillisecond,getDayOfWeek,getDayOfYearandformatread from it.createtakes its ticks from the clock fields, not from the local instant (a skipped clock time has none).$addUnitsfollows .NET 7+'sAddUnits.addDays/addHours/addMinutes/addSeconds/addMillisecondsgo through it.addTicks,add/subtract,adddt/subdt,addMonths,getDateandgetTimeOfDayare tick arithmetic.DateTimeOperatorTests: the matrix gains DST gap and overlap clock times for Berlin, New York and Sydney.Implementation Details
Date's instant stays real. JavaScript interop (DOM, hand-written JS) reads it. Only C#-visible fields and arithmetic moved to ticks. Storing the clock time in the Date's UTC fields instead would have broken every DateTime handed to JS.Add*keeps sub-millisecond ticks now. Old bugs this removes: sub-ms ticks were dropped, andAddDays(-1.5)moved 2.5 days.DateTime.ToString("u")/"r"on a Local/Unspecified DateTime prints the clock time without converting to UTC. That matches .NET. No test covers it.ToUniversalTimeof a clock time inside a DST gap (.NET uses the standard offset there).Testing
Covered: Debug runtime via
TRANSPOSE_DLL_PATH.Not covered:
HttpClient/WatchModesuites, the Release runtime build, the tesserae byte-identical gate.Needs manual verification: None
Generated by Claude Code