Skip to content

Canonicalize the time zone of every neutralized date - #31

Merged
SimonCropp merged 1 commit into
mainfrom
time-zone-canonicalization
Sep 19, 2026
Merged

SimonCropp merged 1 commit into
mainfrom
time-zone-canonicalization

Conversation

@SimonCropp

Copy link
Copy Markdown
Owner

A date's UTC offset is made of separators, so it survived the digit zeroing and went on recording where the render happened. It varies in two ways, so there are two halves.

The sign. "+00:00" on a build agent east of Greenwich, "-00:00" on a developer machine west of it: same length either way, so Fill.Digits now forces it to '+', the spelling ISO 8601 gives a zero offset. Two tests had this backwards and asserted "-00:00" as correct output.

The whole designator. "Z" on a machine running in UTC, "+10:30" anywhere else: those are different lengths, so the two renders are different-sized documents and no length-preserving edit could ever reconcile them. CanonicalizeDateZones collapses every designator to "Z" (the shortest spelling, so an edit only ever shortens) and then repairs the metadata stream /Length, the cross-reference table offsets and startxref, exactly as the XMP packet rewrite does. Shift is now shared between the two.

It finds the dates through the NeutralizedDate list the zeroing passes fill in as they go rather than walking the keys again, so there is no second list of date keys to drift. Each entry also carries whether the zeroing already reported that occurrence, so a date both passes changed is still counted once.

A date inside stream data is a length the pass would have to restate. The metadata stream is the one it knows how to, so an edit landing in any other is dropped and left to the in-place zeroing.

Bail-outs are unchanged in spirit: no classic cross-reference table, an incremental update, or an unlocatable stream length hands the document back untouched, with the sign fix still standing.

Proving this needed a pair of documents that differ in length, which no fixture edited in place can be, so DocumentBuilder builds a complete one-page document - information dictionary, XMP metadata stream, correct xref table - with the dates spelled to order.

Normalized output now spells offsets as "Z" rather than "+00'00'" / "+00:00", so anything already normalized and committed will differ once.

A date's UTC offset is made of separators, so it survived the digit
zeroing and went on recording where the render happened. It varies in
two ways, so there are two halves.

The sign. "+00:00" on a build agent east of Greenwich, "-00:00" on a
developer machine west of it: same length either way, so Fill.Digits
now forces it to '+', the spelling ISO 8601 gives a zero offset. Two
tests had this backwards and asserted "-00:00" as correct output.

The whole designator. "Z" on a machine running in UTC, "+10:30"
anywhere else: those are different lengths, so the two renders are
different-sized documents and no length-preserving edit could ever
reconcile them. CanonicalizeDateZones collapses every designator to
"Z" (the shortest spelling, so an edit only ever shortens) and then
repairs the metadata stream /Length, the cross-reference table offsets
and startxref, exactly as the XMP packet rewrite does. Shift is now
shared between the two.

It finds the dates through the NeutralizedDate list the zeroing passes
fill in as they go rather than walking the keys again, so there is no
second list of date keys to drift. Each entry also carries whether the
zeroing already reported that occurrence, so a date both passes changed
is still counted once.

A date inside stream data is a length the pass would have to restate.
The metadata stream is the one it knows how to, so an edit landing in
any other is dropped and left to the in-place zeroing.

Bail-outs are unchanged in spirit: no classic cross-reference table, an
incremental update, or an unlocatable stream length hands the document
back untouched, with the sign fix still standing.

Proving this needed a pair of documents that differ in length, which no
fixture edited in place can be, so DocumentBuilder builds a complete
one-page document - information dictionary, XMP metadata stream,
correct xref table - with the dates spelled to order.

Normalized output now spells offsets as "Z" rather than "+00'00'" /
"+00:00", so anything already normalized and committed will differ once.
@SimonCropp SimonCropp added this to the 2.0.2 milestone Sep 19, 2026
@SimonCropp
SimonCropp merged commit a84553d into main Sep 19, 2026
6 checks passed
@SimonCropp
SimonCropp deleted the time-zone-canonicalization branch September 19, 2026 00:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant