I recently learned how to change the timezone returned by localtime
in Perl.
use POSIX qw(tzset);
print localtime . "\n";
$ENV{TZ} = 'America/Los_Angeles';
print localtime . "\n";
tzset;
print localtime . "\n";
Outputs
Wed Apr 15 15:58:10 2009
Wed Apr 15 15:58:10 2009
Wed Apr 15 12:58:10 2009
Notice how the hour only changes after calling tzset
.
This is perl, v5.8.8 built for x86_64-linux-thread-multi
However, on my systems I'm getting,
Fri Jul 8 19:00:51 2016
Fri Jul 8 16:00:51 2016
Fri Jul 8 16:00:51 2016
Notice how on my system, the hour changes without calling tzset
. This holds true on recent versions of Perl in Ubuntu and Illumos, as well as Perl v5.8.8
on Solaris 10.
So if all my tests indicate that tzset
has no effect, why / what other systems require tzset
to be called explicitly? Do I still need to call tzset
to remain compatible with certain environments, or is it now a thing of the past?
TL;DR: Starting with Perl v5.8.9 (released in 2011) calling tzset
when changing $ENV{TZ}
isn't needed anymore.
Perl's localtime
calls localtime_r(3)
internally, which isn't required to call tzset(3)
. The Linux manpage advises:
According to POSIX.1-2004, localtime() is required to behave as though tzset(3) was called, while localtime_r() does not have this requirement. For portable code tzset(3) should be called before localtime_r().
In older non-multithreaded Perls, or if localtime_r(3)
wasn't available during build, localtime(3)
is used instead. In that case, a call to tzset
would have been unnecessary, per POSIX:
Local timezone information is used as though localtime() calls tzset()
although there seem to have been times where glibc didn't adhere to that:
As for any code which doesn't call tzset all the time: this definitly won't change. It's far too expensive. And for what? The 0.000001% of the people who take the laptops on a world tour and expect, e.g., syslog messages with dates according to the native timezone. This is not justification enough. Just restart your machine.
This did change though and glibc now does act as if tztime(3)
was called, but only for non-reentrant localtime
which might not be what your Perl was compiled to use.
There have been two Perl bug reports regarding this: #26136 and #41591.
As a fix, Perl now decides at configuration time whether an implicit tzset(3)
needs to be done, which makes specifying it in user code superfluous.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With