use strict;
use warnings;
# GH#10 / RT#80649: Wrong timezone abbreviation during DST fall-back
#
# format_Z was calling timelocal() to reconstruct the original epoch from
# broken-down time. During the "fall-back" hour, the broken-down time is
# ambiguous (1:xx AM occurs twice: once in PDT and once in PST). timelocal()
# resolves the ambiguity to the first occurrence (PDT), returning the PDT
# epoch (offset -25200). tz_name(-25200, dst=0) then finds -25200 in %zoneOff
# as "mst" (Mountain Standard), yielding MST instead of PST.
#
# Fix: use the original epoch stored in $_[0]->[9] instead of timelocal().
#
# The TZ is set in a BEGIN block so the C library timezone is initialised
# before any module loads and before any localtime/tzset calls happen.
# Using a runtime $ENV{TZ} assignment after `use` statements is unreliable
# because `use` executes at compile time, and on some platforms restoring a
# `local $ENV{TZ}` automatically resets the C library timezone, which a later
# POSIX::tzset() call may not fully undo.
BEGIN {
$ENV{TZ} = 'America/Los_Angeles';
require POSIX;
eval { POSIX::tzset() };
}
use POSIX qw();
use Test::More;
use Date::Format qw(time2str);
# Skip the whole file if the platform does not support IANA timezone names.
# Use epoch 1352019262 (2012-11-04 01:04:22 PDT): DST=1 in America/Los_Angeles
# but DST=0 in UTC, so this check actually distinguishes the two and won't
# produce a false-positive on a UTC-only system.
my $has_la_tz = eval {
my @lt = localtime(1352019262); # 2012-11-04 01:04:22 PDT (before fall-back)
$lt[8] == 1; # Expect DST flag = 1 in PDT
};
plan( skip_all => "system does not support America/Los_Angeles timezone" )
unless $has_la_tz;
plan tests => 3;
# 2012-11-04 01:25:05 PST — the second occurrence of 01:xx AM after fall-back
# This is the timestamp from the original bug report that returned MST.
is( time2str("%Z", 1352021105), "PST",
"GH#10/RT#80649: repeated hour after fall-back formats as PST, not MST" );
# 2012-11-04 01:54:22 PDT — before the fall-back (first occurrence of 01:xx AM)
is( time2str("%Z", 1352019262), "PDT",
"GH#10/RT#80649: pre-fall-back timestamp formats as PDT" );
# 2012-11-04 02:25:05 PST — after the repeated hour, clearly PST
is( time2str("%Z", 1352024705), "PST",
"GH#10/RT#80649: post-repeated-hour timestamp formats as PST" );