Time::Piece and Time::TimeZone compatibility boundary when replacing system TZ with explicit regional offsets
0 reputation · 01 Feb 2023, 22:09 UTC
0 reputation · 01 Feb 2023, 22:09 UTC
When converting Unix epoch timestamps to regional wall-clock times, Time::Piece delegates localtime to the underlying C library and the process TZ environment variable, making output dependent on the host operating system's time zone database. Time::TimeZone offers explicit regional offset lookups that do not rely on the OS locale, but combining the two approaches raises unresolved questions about daylight saving time consistency. Because Time::Piece is a thin wrapper over C functions, its behavior can differ between POSIX-compliant systems and Windows, and manually applying an offset from Time::TimeZone to a Time::Piece object may not account for the same DST transition rules that the C library would apply. Altering the TZ variable at runtime to influence Time::Piece is also documented as unsafe in threaded Perl applications.
Which documented behavior should govern the boundary when a script replaces system TZ lookups with explicit Time::TimeZone offsets: the C library's transition table or the CPAN module's offset table? How can a multi-threaded Perl program avoid race conditions if it must temporarily adjust the process TZ environment while still using Time::Piece for formatting? Are there version-specific guarantees for Time::Piece and Time::TimeZone that ensure identical DST boundary results across differing OS-level TZ database versions?
32775 reputation · 02 Feb 2023, 01:05 UTC
When you replace the system TZ lookup with an explicit offset from Time::TimeZone, the boundary that determines daylight‑saving transitions is governed by the CPAN module’s offset table, not the C library’s transition table. Time::Piece itself only follows the C library (localtime/gmtime) and the process TZ environment variable; if you bypass it by adding an offset manually, you are relying entirely on the data supplied by Time::TimeZone.
Modifying $ENV{TZ} at runtime is unsafe in threaded Perl because the environment block is process‑wide and shared by all threads. To avoid race conditions:
Time::TimeZone->offset($epoch, $zone).Time::Piece object: my $tp = Time::Piece->gmtime($epoch);$tp += $offset;Time::Piece as needed.This approach never touches %ENV, so it is safe across threads.
There is no documented guarantee that Time::Piece (which uses the host’s tzdata) and Time::TimeZone (which ships its own zoneinfo copy) will produce identical DST boundaries across different OS tzdata versions. Consistency is only assured when both components are built from the same version of the zoneinfo database. If you need strict parity, verify that the system’s tzdata package and the version of Time::TimeZone you are using were derived from the same release.
If you observe a mismatch between the two methods, please confirm the exact versions of the system tzdata (e.g., zdump -V /etc/localtime | head -1) and the Time::TimeZone module (perl -MTime::TimeZone -e 'print $Time::TimeZone::VERSION'). This information determines whether a version skew explains the discrepancy.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.