Skip to content

#3824: the mainframe's time zone reaches the clock - #3868

Merged
squid-protocol merged 1 commit into
mainfrom
fleet/3824-time-zones
Sep 27, 2026
Merged

squid-protocol merged 1 commit into
mainfrom
fleet/3824-time-zones

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Closes #3824 (epic #3819).

What changes

  • MainframeClock (generated batch runtime) takes its zone from gitgalaxy.zone. The default is baked in from the target's culture.zone (default UTC). It never uses the JVM's default zone.
    • now() is the mainframe's wall time in that zone.
    • New zonedNow() returns a ZonedDateTime.
    • New currentDate() returns FUNCTION CURRENT-DATE's 21 characters, e.g. 2022071810301500+0530.
    • A pinned time in a DST gap moves forward (ZonedDateTime.of).
  • DB2: TIMESTAMP WITH TIME ZONE now maps to OffsetDateTime instead of LocalDateTime, so the offset is no longer dropped.
  • Equivalence harness: a case may declare "zone". The COBOL side then runs under TZ=<zone> and the JVM under gitgalaxy.zone=<zone>. Cases without it behave as before.
  • Porting rule: use currentDate() for CURRENT-DATE, and never ZoneId.systemDefault().

Tests

  • New tests/cobol_mainframe/test_time_zones.py. It includes a javac/java run asserting currentDate() for Asia/Kolkata.
  • All 761 tests/cobol_mainframe tests pass.
  • EQUIVALENCE_E2E=1 proofs (Docker GnuCOBOL + JDK 17): 37 passed.
  • pr_gates.py --fast: 5/5 pass.
  • The change is converter-only, so no engine scan output (golden masters) moves.

Drafted by an agy (Gemini 3.1 Pro) fleet agent; reviewed and tidied by Claude. The tidy-up: now() goes through zonedNow(), so pinned and unpinned times resolve a DST gap the same way, and the Javadoc was rewrapped.

🤖 Generated with Claude Code

MainframeClock takes its zone from gitgalaxy.zone (default: the target's
culture.zone), never the JVM's. now() is the mainframe's wall time in that
zone; zonedNow() and currentDate() give FUNCTION CURRENT-DATE's 21 characters
with the zone's UTC offset. A pinned time in a DST gap moves forward
(ZonedDateTime.of). DB2 TIMESTAMP WITH TIME ZONE maps to OffsetDateTime.
The equivalence harness runs both sides in a case's "zone" (TZ= for GnuCOBOL,
gitgalaxy.zone for the JVM). A porting rule points CURRENT-DATE at
currentDate() and forbids ZoneId.systemDefault().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit d276367 into main Sep 27, 2026
37 checks passed
@squid-protocol
squid-protocol deleted the fleet/3824-time-zones branch September 27, 2026 12:34
squid-protocol pushed a commit that referenced this pull request Sep 27, 2026
…ull-suite-matrix)

The mock recovers the work directory from `f"{work}:/work"` with `split(":")[0]`; on Windows
`work` is `D:\...\work`, so it kept only the drive letter and the test failed with
FileNotFoundError 'C\RETURN-CODE' on every Windows matrix run. rpartition(":") keeps it. Came in
with #3824 (#3868); fixed here because it turns this PR's Windows job red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9PBcL8evG7CEzff1zE8v5
squid-protocol added a commit that referenced this pull request Sep 27, 2026
… fixed-block EBCDIC (#3899)

* #3816 (part 2): the Unicode Gauntlet writes the mainframe seed as raw fixed-block EBCDIC

Part 1 (#3888) taught source_text the Western European EBCDIC pages and fixed-block records; the
gauntlet did not exercise them. The mainframe seed is now also written in cp037, cp273, cp277,
cp278, cp297 and cp1047 as a binary PDS download arrives: every line padded to an 80-byte card
image, no line ends. Each such estate declares its page (#3881's declared-encoding plumbing).

- ASCII seed in every page; Nordic names in cp277 / cp278 and German in cp273, the pages whose
  national positions hold those letters. Mainframe seed only; in the sampled plan, so CI runs them.
- fixed_block() refuses a line longer than a card or a character outside the page (the cell is
  skipped, as encode() already does for text a codec cannot hold).
- tests: the writer round-trips through source_text on every page; refusals; the seed fits 80
  columns; the plan holds every page for the mainframe seed and none for a rosetta language; the
  oracle-soundness run now requires every ASCII EBCDIC cell to match the UTF-8 seed (it does).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9PBcL8evG7CEzff1zE8v5

* #3816 (part 2): an EBCDIC estate keeps its reference's other languages

The first full run failed every EBCDIC cell on the PL/I include (`INCA.inc` excluded as
"Unresolved Ambiguity"). Not a decoding fault: a UTF-8 mainframe-only copy excludes it the same
way. An ambiguous `.inc` is resolved by the project's other languages (#3867), and the EBCDIC
estates held only the mainframe seed while their reference estates hold every seed language. Each
EBCDIC estate now gets every other language from its reference estate, unchanged, so the only
difference left is the mainframe files' encoding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9PBcL8evG7CEzff1zE8v5

* test_time_zones: split the docker volume at its last colon (Windows full-suite-matrix)

The mock recovers the work directory from `f"{work}:/work"` with `split(":")[0]`; on Windows
`work` is `D:\...\work`, so it kept only the drive letter and the test failed with
FileNotFoundError 'C\RETURN-CODE' on every Windows matrix run. rpartition(":") keeps it. Came in
with #3824 (#3868); fixed here because it turns this PR's Windows job red.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9PBcL8evG7CEzff1zE8v5

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

Time zones: the pinned clock has no zone; CURRENT-DATE's UTC offset follows the process TZ; harness sides can run in different zones

1 participant