@@ -9,7 +9,7 @@ use strict;
99
1010use Config;
1111use POSIX;
12- use Test::More tests => 31 ;
12+ use Test::More tests => 40 ;
1313
1414# For the first go to UTC to avoid DST issues around the world when testing. SUS3 says that
1515# null should get you UTC, but some environments want the explicit names.
@@ -205,11 +205,14 @@ SKIP: {
205205 is(mktime(CORE::localtime ($time )), $time , " mktime()" );
206206 is(mktime(POSIX::localtime ($time )), $time , " mktime()" );
207207}
208+
209+ my $limited_strftime_formats = $^O eq " VMS"
210+ || $^O eq " MSWin32"
211+ || $^O eq " os390" ;
208212
209213SKIP: {
210- skip " '%s ' not implemented in strftime" , 1 if $^O eq " VMS"
211- || $^O eq " MSWin32"
212- || $^O eq " os390" ;
214+ skip " '%s ' not implemented in strftime" , 1 if $limited_strftime_formats ;
215+
213216 # Somewhat arbitrarily, put in 60 seconds of slack; if this fails, it
214217 # will likely be off by 1 hour
215218 ok(abs(POSIX::strftime(' %s' , localtime ) - time ) < 60,
@@ -226,3 +229,43 @@ SKIP: {
226229 is(strftime(undef , CORE::localtime ), ' ' , " strftime() works if format is undef" );
227230 like($warnings , qr / ^Use of uninitialized value in subroutine entry / , " strftime(undef, ...) produces expected warning" );
228231}
232+
233+ SKIP: { # GH #23878
234+ skip " No mktime()" , 9 if $Config {d_mktime } ne ' define' ;
235+ my $locale = " Europe/Paris" ;
236+ $ENV {TZ } = $locale ;
237+ my $t = 1761436800; # an hour before time should have changed
238+ my ($azone , $bzone ); # Timezone offset before and after dst change
239+
240+ # If this platform doesn't have this field, the offset will be zero
241+ if (! $Config {d_tm_tm_gmtoff }) {
242+ $azone = $bzone = " 0000" ;
243+ }
244+ else {
245+ $bzone = " 0200" ;
246+ $azone = " 0100" ;
247+ }
248+
249+ # The time in the first test case is such that UTC gives a different day.
250+ # If the locale above is unknown, libc is supposed to use UTC; so that's
251+ # how we check if the system knows about the rules for Paris; which on
252+ # some systems differ from plain CET-1CEST.
253+ skip " '$locale ' not understood" , 9 if
254+ POSIX::strftime(" %F %T%z " , localtime ($t - 1)) !~ / 2025-10-26/ ;
255+
256+ my @data = (
257+ [ -1, " 2025-10-26 01:59:59+$bzone " , " -1 second" ],
258+ [ 0, " 2025-10-26 02:00:00+$bzone " , " +0 seconds" ],
259+ [ 1, " 2025-10-26 02:00:01+$bzone " , " +1 second" ],
260+ [ 3599, " 2025-10-26 02:59:59+$bzone " , " +59 minutes 59 seconds" ],
261+ [ 3600, " 2025-10-26 02:00:00+$azone " , " +1 hour" ],
262+ [ 3601, " 2025-10-26 02:00:01+$azone " , " +1 hour 1 second" ],
263+ [ 7199, " 2025-10-26 02:59:59+$azone " , " +2 hours minus 1 sec" ],
264+ [ 7200, " 2025-10-26 03:00:00+$azone " , " +2 hours" ],
265+ [ 7201, " 2025-10-26 03:00:01+$azone " , " +2 hours 1 second" ],
266+ );
267+ for (my $i = 0; $i < @data ; $i ++) {
268+ is(POSIX::strftime(" %F %T%z " , localtime $t + $data [$i ][0]),
269+ $data [$i ][1], $data [$i ][2]);
270+ }
271+ }
0 commit comments