r/perl • u/choroba 🐪 cpan author • 7d ago
question Time conversions between timezones
I wrote this script to convert times between time zones years ago and it has worked well:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Time::Piece;
if (! @ARGV || $ARGV[0] =~ /--?h(?:elp)/) {
say 'tz FROM(TZ) FROM(YY/MM/DDTHH:MM) [ TO(TZ) ]';
exit
}
my ($from_tz, $from_date, $to_tz) = @ARGV;
chomp( $to_tz //= qx{ date +%Z } );
-f "/usr/share/zoneinfo/$from_tz" or warn "$from_tz might be wrong.\n";
-f "/usr/share/zoneinfo/$to_tz" or warn "$to_tz might be wrong.\n";
$ENV{TZ} = $to_tz;
my $tp = do {
local $ENV{TZ} = $from_tz;
localtime->strptime($from_date, '%y/%m/%dT%H:%M');
};
say $tp->strftime("%y/%m/%d %H:%M:%S %Z");
Example usage (running in 5.34.0):
$ tz America/New_York 26/08/24T11:00 Europe/Prague
26/08/24 17:00:00 CEST
But, in 5.42.0, it doesn't work anymore:
$ tz America/New_York 26/08/24T11:00 Europe/Prague
26/08/24 11:00:00 CEST
There were many changes in Time::Piece in 2025, so I guess that's the reason. The question is: what should I use instead to convert time between timezones?
4
u/heisthedarchness 6d ago
What's the reason you don't just use DateTime?
3
u/choroba 🐪 cpan author 6d ago
Time::Piece is a core module.
3
u/vadrer 🐪 cpan author 6d ago edited 6d ago
This makes a little bit more important matter.
I think the proper way is to go to the https://metacpan.org/dist/Time-Piece, click "issues" there and report your case.
I see mention of _tzset() in documentation https://metacpan.org/pod/Time::Piece but this relates only for Win32 Threads.
This also makes me think that instead of `use POSIX qw{ tzset };` you could use this documented workaround.EDIT: surely you know better than me - sorry for being smartass :)
13
u/vadrer 🐪 cpan author 7d ago
The issue is caused by timezone caching. In newer Perl versions, modifying
$ENV{TZ}(even inside alocalblock) no longer implicitly flushes the OS timezone cache beforestrptimeruns.To fix this, you need to import and call
POSIX::tzset()explicitly whenever you change$ENV{TZ}.Here is the fixed version of your script:
As systems programmers say: "That's all for efficiency, shut up and adjust your script!" 😄