Sunday, December 10, 2006

小心时区陷阱(二)

测试用例
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece qw//;
use Date::Simple qw//;
use POSIX qw//;

sub show_info {
my $msg = shift;
my $hour = (localtime)[2];
printf "tz=$ENV{TZ}, tzname=%s:%s, hour=%2d # $msg\n", POSIX::tzname, $hour;
}

$ENV{TZ} = 'JST-9';
print "Date::Simple version is $Date::Simple::VERSION\n";
show_info('start');
my $date = Date::Simple->new;
show_info('after new');
$date->strftime("%Y-%m-%d\n");
show_info('after strftime');
POSIX::tzset;
show_info('after tzset');


输出结果
tz=JST-9, tzname=JST:JST, hour= 8 # start
tz=JST-9, tzname=JST:JST, hour= 8 # after new
tz=JST-9, tzname=UTC:UTC, hour=23 # after strftime
tz=JST-9, tzname=JST:JST, hour= 8 # after tzset


另外,关于 $ENV{TZ},提醒一下。
假设机器的时区设置为 UTC+9,不考虑非法的时区设置,那么根据值的不同,分别会是这样的结果
1.  not exists $ENV{TZ}        UTC+9
2.1 if ( $ENV{TZ} ) {...} UTC+0
2.2 else {...} UTC+9


Patch for Date::Simple 3.02
$ diff -r Date-Simple-3.02.orig Date-Simple-3.02
diff -r Date-Simple-3.02.orig/lib/Date/Simple.pm Date-Simple-3.02/lib/Date/Simple.pm
158a159
>
160,161c161,174
< local $ENV{TZ} = 'UTC+0';
< return POSIX::strftime ($format, _gmtime ($self));
---
> my $exists_env_tz = exists $ENV{TZ};
> my $tz = $ENV{TZ} if $exists_env_tz;
>
> $ENV{TZ} = 'UTC+0';
> my $result = POSIX::strftime ($format, _gmtime ($self));
>
> if ( $exists_env_tz ) {
> $ENV{TZ} = $tz;
> } else {
> delete $ENV{TZ};
> }
> POSIX::tzset();
>
> return $result;

参考链接
rt#23875

No comments: