POSIX::Strftime Output Change In Perl V5.40 To V5.42
Hey everyone,
There's been a reported issue regarding a change in the behavior of POSIX::strftime between Perl versions v5.40 and v5.42. This article dives into the details of this change, the steps to reproduce it, the expected behavior, and the commit that introduced the difference. Let's get started!
Module: POSIX
This issue specifically affects the POSIX module in Perl.
Description
It was reported on IRC by user sphex that there's an inconsistent output from POSIX::strftime when comparing Perl v5.40 and v5.42. The command that triggered this observation is:
TZ=Europe/Paris perl -E 'use POSIX "strftime"; say strftime("%FT%T%z", localtime 1761436800);'
The core of the issue is that the time zone offset generated by strftime differs between these two Perl versions for the same input time and time zone.
Steps to Reproduce
To reproduce this issue, you can run the following commands in your terminal. Make sure you have both Perl v5.40 and v5.42 installed to compare the outputs.
Perl 5.42:
perl -E 'BEGIN {$ENV{TZ}="Europe/Paris"} use POSIX "strftime"; say strftime("%FT%T%z", localtime 1761436800);'
This command outputs:
2025-10-26T02:00:00+0100
Perl 5.40:
perl -E 'BEGIN {$ENV{TZ}="Europe/Paris"} use POSIX "strftime"; say strftime("%FT%T%z", localtime 1761436800);'
This command outputs:
2025-10-26T02:00:00+0200
As you can see, the time zone offset differs: +0100 in v5.42 and +0200 in v5.40.
Expected Behavior
It's believed that the output from Perl v5.40, which is 2025-10-26T02:00:00+0200, is the correct output. This expectation is based on the understanding of how time zones and daylight saving time should be applied for the given timestamp and time zone.
To confirm this, a bisecting process was performed using the following command:
Porting/bisect.pl --start v5.40.0 --end v5.42.0 -e ' BEGIN {$ENV{TZ}="Europe/Paris"} use POSIX "strftime"; die "Wrong time" unless "2025-10-26T02:00:00+0200" eq strftime("%FT%T%z", localtime 1761436800);'
This command automates the process of checking out different commits between v5.40.0 and v5.42.0 and running the provided Perl code. It identifies the commit where the output deviates from the expected 2025-10-26T02:00:00+0200.
Culprit Commit
The bisecting process pinpointed the following commit as the culprit:
86a9c18b6fab1949a26de790418b8b897a71e4ac
This commit is the one that introduced the change in behavior. Further investigation into this commit's changes would be necessary to understand the root cause of the issue.
Perl Configuration
To provide a comprehensive understanding of the environment where this issue was observed, the Perl configuration is included below. This information can be crucial for debugging and identifying potential environmental factors that might influence the behavior.
Summary of my perl5 (revision 5 version 42 subversion 0) configuration:
Platform:
osname=linux
osvers=6.12.22+bpo-amd64
archname=x86_64-linux
uname='linux simcop2387.info 6.12.22+bpo-amd64 #1 smp preempt_dynamic debian 6.12.22-1~bpo12+1 (2025-04-25) x86_64 gnulinux '
config_args='-Dprefix=/home/perlbot/perl5/custom/5.42.0 -de -Dusedevel -Duseshrplib -Dusemymalloc=y -Accflags=-fpie -fPIC -mtune=native -fstack-protector-all -pie -D_FORTIFY_SOURCE=2 -ggdb -DPERL_EMERGENCY_SBRK -Aldflags=-Wl,-z,now -Wl,-zrelro -Wl,-z,noexecstack -A'eval:scriptdir=/home/perlbot/perl5/custom/5.42.0/bin''
hint=recommended
useposix=true
d_sigaction=define
useithreads=undef
usemultiplicity=undef
use64bitint=define
use64bitall=define
uselongdouble=undef
usemymalloc=y
default_inc_excludes_dot=define
Compiler:
cc='cc'
ccflags ='-fpie -fPIC -mtune=native -fstack-protector-all -pie -D_FORTIFY_SOURCE=2 -ggdb -DPERL_EMERGENCY_SBRK -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
optimize='-O2'
cppflags='-fpie -fPIC -mtune=native -fstack-protector-all -pie -D_FORTIFY_SOURCE=2 -ggdb -DPERL_EMERGENCY_SBRK -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
ccversion=''
gccversion='12.2.0'
gccosandvers=''
intsize=4
longsize=8
ptrsize=8
doublesize=8
byteorder=12345678
doublekind=3
d_longlong=define
longlongsize=8
d_longdbl=define
longdblsize=16
longdblkind=3
ivtype='long'
ivsize=8
nvtype='double'
nvsize=8
Off_t='off_t'
lseeksize=8
alignbytes=8
prototype=define
Linker and Libraries:
ld='cc'
ldflags =' -Wl,-z,now -Wl,-zrelro -Wl,-z,noexecstack -fstack-protector-strong -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib/x86_64-linux-gnu /usr/lib /usr/lib64
libs=-lpthread -ldl -lm -lcrypt -lutil -lc
perllibs=-lpthread -ldl -lm -lcrypt -lutil -lc
libc=/lib/x86_64-linux-gnu/libc.so.6
so=so
useshrplib=true
libperl=libperl.so
gnulibc_version='2.36'
Dynamic Linking:
dlsrc=dl_dlopen.xs
dlext=so
d_dlsymun=undef
ccdlflags='-Wl,-E -Wl,-rpath,/home/perlbot/perl5/custom/5.42.0/lib/5.42.0/x86_64-linux/CORE'
cccdlflags='-fPIC'
lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'
Characteristics of this binary (from libperl):
Compile-time options:
HAS_LONG_DOUBLE
HAS_STRTOLD
HAS_TIMES
MYMALLOC
PERLIO_LAYERS
PERL_COPY_ON_WRITE
PERL_DONT_CREATE_GVSV
PERL_HASH_FUNC_SIPHASH13
PERL_HASH_USE_SBOX32
PERL_MALLOC_WRAP
PERL_OP_PARENT
PERL_PRESERVE_IVUV
PERL_USE_DEVEL
PERL_USE_SAFE_PUTENV
USE_64_BIT_ALL
USE_64_BIT_INT
USE_LARGE_FILES
USE_LOCALE
USE_LOCALE_COLLATE
USE_LOCALE_CTYPE
USE_LOCALE_NUMERIC
USE_LOCALE_TIME
USE_PERLIO
USE_PERL_ATOF
Built under linux
Compiled at Jul 3 2025 21:14:07
%ENV:
PERLBREW_HOME="/home/perlbot/.perlbrew"
PERLBREW_MANPATH="/home/perlbot/perl5/perlbrew/perls/perlbot-main/man"
PERLBREW_PATH="/home/perlbot/perl5/perlbrew/bin:/home/perlbot/perl5/perlbrew/perls/perlbot-main/bin"
PERLBREW_PERL="perlbot-main"
PERLBREW_ROOT="/home/perlbot/perl5/perlbrew"
PERLBREW_SHELLRC_VERSION="0.86"
PERLBREW_VERSION="0.86"
@INC:
/home/perlbot/perl5/custom/5.42.0/lib/site_perl/5.42.0/x86_64-linux
/home/perlbot/perl5/custom/5.42.0/lib/site_perl/5.42.0
/home/perlbot/perl5/custom/5.42.0/lib/5.42.0/x86_64-linux
/home/perlbot/perl5/custom/5.42.0/lib/5.42.0
The Perl configuration details provide insights into the environment in which the issue was reproduced. Key aspects include the operating system (Linux), Perl version (5.42.0), compiler (gcc 12.2.0), and various compile-time options. This information is crucial for anyone attempting to debug or fix the issue, as it helps to ensure that the problem can be reproduced in a similar environment.
Summary and Next Steps
In summary, a change in the output of POSIX::strftime has been observed between Perl v5.40 and v5.42 when formatting a specific time with the Europe/Paris time zone. The commit 86a9c18b6fab1949a26de790418b8b897a71e4ac has been identified as the cause of this change.
Next steps would involve:
- Deep Dive into the Culprit Commit: Analyzing the changes introduced by commit
86a9c18b6fab1949a26de790418b8b897a71e4acto understand how it affected thePOSIX::strftimefunction. - Identify the Root Cause: Determining why the changes in the commit led to the incorrect time zone offset.
- Develop a Fix: Implementing a solution that restores the correct behavior of
strftimewithout introducing new issues. - Testing: Thoroughly testing the fix to ensure it resolves the problem and doesn't negatively impact other functionality.
This issue highlights the importance of careful change management and thorough testing when updating software, especially in areas that deal with time and date manipulations, which can be complex and prone to subtle errors.
If you're experiencing this issue or have insights into the cause, feel free to share your thoughts and findings. Let's work together to get this resolved!