Lua os library and host C time functions: handling ambiguous local times during DST transitions
0 reputation · 30 Oct 2022, 17:55 UTC
0 reputation · 30 Oct 2022, 17:55 UTC
When constructing a time table for os.time, the isdst flag can be set to true, false, or omitted to indicate daylight‑saving status for the given local time.
The Lua reference manual does not define what happens when the supplied local time is ambiguous (e.g., 1:30 am during a “fall back” transition) or skipped (e.g., 2:30 am during a “spring forward” jump), leaving the normalization to the underlying C library’s mktime.
Because mktime’s behavior varies across platforms—glibc, macOS libc, Windows CRT—the same os.time call may produce different timestamps, affecting any code that relies on exact UTC conversion or protocol timestamps.
What does os.time return when isdst is explicitly set for an ambiguous or skipped local time? Does the result differ between major C library implementations? Is there a portable way, using only the Lua standard library, to detect or resolve such ambiguity?
33275 reputation · 31 Oct 2022, 00:26 UTC
os.time forwards the supplied table to the host C library’s mktime. For an ambiguous local time—one that occurs twice during a fall-back DST transition—mktime uses the isdst flag to choose the instance: true selects the later occurrence, false selects the earlier one, and omitting the flag leaves the decision to the C library, which commonly picks the earlier instance. For a skipped local time—one that does not exist during a spring-forward jump—most C libraries normalize the value forward to the first valid clock time after the gap, regardless of isdst. Because these rules live in the platform C library, the epoch returned by os.time is not guaranteed to match across glibc, macOS libc, and the Windows CRT.
The confirmed fact is that Lua adds no normalization of its own; it relies entirely on mktime. The practical variance is that glibc generally applies the isdst selection rule consistently, while the Windows CRT has historically ignored isdst and normalized to the earlier instance, though newer CRT versions may honor isdst=true for ambiguous times. macOS libc usually follows the glibc pattern, but some versions may adjust ambiguous results by an hour. Treat every cross-platform epoch value as provisional until verified on the actual target system.
Lua’s standard library does not expose timezone or DST metadata. The only portable test is to call os.time twice with the same wall-clock fields but different isdst values and compare the results.
local t1 = {year=2026, month=10, day=29, hour=1, min=30, isdst=false}
local t2 = {year=2026, month=10, day=29, hour=1, min=30, isdst=true}
local e1, e2 = os.time(t1), os.time(t2)
if e1 ~= e2 then
-- ambiguous on this platform; e2 is the later instance
-- when the library honors isdst
end
If the two epoch values are equal, the time is either unambiguous or the platform ignores isdst for that transition.
isdst explicitly when you need a specific side of an ambiguous hour.If your target is a specific operating system and Lua version, share those details so the expected normalization can be narrowed further.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.