Time::Piece::strftime and time zone issue
https://rt.cpan.org/Ticket/Display.html?id=75046 This entry is just thinking note.
use strict; use warnings; use utf8; use Time::Piece; $ENV{TZ} = 'JST-9'; print gmtime(1363791599)->strftime('%Y-%m-%dT%H:%M:%S%z'), "\n"; print localtime(1363791599)->strftime('%Y-%m-%dT%H:%M:%S%z'), "\n";
↓
2013-03-20T14:59:59+0900 2013-03-20T23:59:59+0900
OMG!!!!
Why?
sub strftime { my $time = shift; my $tzname = $time->[c_islocal] ? '%Z' : 'UTC'; my $format = @_ ? shift(@_) : "%a, %d %b %Y %H:%M:%S $tzname"; if (!defined $time->[c_wday]) { if ($time->[c_islocal]) { return _strftime($format, CORE::localtime($time->epoch)); } else { return _strftime($format, CORE::gmtime($time->epoch)); } } return _strftime($format, (@$time)[c_sec..c_isdst]); }
And, _strftime() is a wrapper of strftime(3). strftime(3) converts "%z" and "%Z" to system time zone.
Solution
Replace %Z and %z
Very ad-hoc, but may works.
Here is a pretty monkey patch.
{ my $orig = Time::Piece->can('strftime'); no warnings 'redefine'; *Time::Piece::strftime = sub { my ($time, $format) = @_; if (!$time->[Time::Piece::c_islocal]) { $format =~ s/(?<!%)%Z/UTC/; $format =~ s/(?<!%)%z/+0000/; warn $format; } $orig->($time, $format); }; }
Use tm.tm_zone
OSX, GNU linux, and other systems support tm.tm_zone. I think, if T::Piece::_strftime call a gmtime, and it set to tm.tm_zone, it works well.
(But, it does not work well on win32, mattn says.)
Use Time::Piece own strftime
Implement yet another srtrftime() implementation.
Is good? But it breaks your code on some operating system, that extended?