Dyalog APL ⎕TS and GNU APL Serial Dates: Regional Time-Zone Conversion Across Dialects
0 reputation · 05 May 2022, 14:59 UTC
0 reputation · 05 May 2022, 14:59 UTC
When integrating APL applications that exchange timestamps across regional deployments, converting locale-specific date-times to a universal reference frame requires reconciling two different date-time models. Dyalog APL exposes the current instant through ⎕TS in UTC but provides no built-in operator for shifting between regional zones and universal time. GNU APL and APL2 represent dates as serial numbers, where applying a regional offset is a manual arithmetic step. The boundary between these models becomes fragile around daylight-saving transitions, when a local timestamp may be ambiguous or nonexistent.
Because ISO 8601 string parsing and formatting via ⎕FMT differ across commercial and free implementations, a portable conversion routine cannot assume a single format-code behavior. The unresolved design question is how to define a deterministic mapping from a locale-specific timestamp to universal time that remains correct when the same serial-number arithmetic is reused across dialects. Since implementations evolve, behavior should be verified against the specific APL versions in use.
What is the recommended pattern for encoding regional time-zone rules—including daylight-saving start and end—inside APL without relying on external libraries? Should applications normalize all stored timestamps to UTC at the ⎕TS boundary and defer locale rendering to the presentation layer? How can developers verify that DST edge cases behave identically in Dyalog APL and GNU APL before deployment?
35775 reputation · 05 May 2022, 20:41 UTC
Store all timestamps in UTC and apply zone offsets only at presentation time. This eliminates ambiguity around daylight-saving transitions and ensures consistent behavior across Dyalog APL and GNU APL.
Dyalog APL exposes the current instant via ⎕TS in UTC. GNU APL and older APL2 systems represent dates as serial numbers (days since a base epoch). The epoch difference must be accounted for when exchanging values.
Gnu APL uses days since 1899-12-30 (APL2 epoch). Dyalog's serial conversion uses 1900-01-01. Convert by adding 2 days to GNU serial numbers to align with Dyalog's internal representation:
UTC_Serial_Dyalog ← ⎕TS[1] + (⎕TS[2]-1)÷365.25 + (⎕TS[3]-1)÷365.25÷260 + ... ⍝ or use Dyalog's built-in serial conversion
UTC_Serial_GNU ← (Dyalog_Serial - 2) ⍝ reverse adjustment
Encode rules in a small lookup table. For Europe/Paris (CET/CEST):
ZoneRules ← ⎕CSV 'ParisOffset.csv' ⍝ columns: year, standardOffset, DST_Start_Month, DST_Start_Day, DST_End_Month, DST_End_Day
GetOffset ← {
⍝ Input: UTC serial number
⍝ Output: offset in hours
... ⍝ logic to detect DST based on year and date
}
Ambiguous times (fall-back hour) and nonexistent times (spring-forward hour) require explicit handling:
⎕TS and verify the value matches after applying the 2-day offset for GNU.'YYYY-MM-DDTHH:II:SS') and compare outputs.
⍝ Normalize at boundary: convert local input to UTC serial
LocalToUTC ← {
⍝ Input: local date-time components and zone rules
⍝ Output: UTC serial number
offset ← GetOffset ⍵
utcSerial ← ⍺ - offset÷24
utcSerial
}
⍝ Render at presentation: convert UTC serial to local display
UTCToLocal ← {
⍝ Input: UTC serial number
⍝ Output: formatted local time string
offset ← GetOffset ⍵
localSerial ← ⍵ + offset÷24
FormatISO8601 localSerial
}
What specific APL versions are deployed in production? DST handling can vary between minor releases, especially around leap-second adjustments or zone-rule updates.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 05 May 2022, 20:34 UTC
The answer states that Dyalog ⎕TS returns UTC, but this is version-dependent. In Dyalog 18.0 and earlier, ⎕TS reflects the OS local time zone; only recent releases (18.2+) document UTC behavior when the interpreter is started with -utc or the DYALOG_UTC environment variable. Always capture ⎕TS alongside a known UTC reference (e.g., NTP or ⎕NA call to time()) to confirm the offset for your deployed version.
Similarly, the 2-day epoch offset between GNU APL (1899-12-30) and Dyalog (1900-01-01) holds for current builds but is not guaranteed by either specification. Verify by converting a known civil date (e.g., 2000-01-01) to serial in each dialect and measuring the difference before relying on a fixed constant.