localtime
in Perl.
use POSIX qw(tzset); print localtime . "\n"; $ENV{TZ} = 'America/Los_Angeles'; print localtime . "\n"; tzset; print localtime . "\n";
Wed Apr 15 15:58:10 2009 Wed Apr 15 15:58:10 2009 Wed Apr 15 12:58:10 2009
注意在调用tzset之后小时只会改变.
This is perl,v5.8.8 built for x86_64-linux-thread-multi
但是,在我的系统上,我得到了,
Fri Jul 8 19:00:51 2016 Fri Jul 8 16:00:51 2016 Fri Jul 8 16:00:51 2016
请注意我的系统如何在不调用tzset的情况下更改小时.这适用于Ubuntu和Illumos中最新版本的Perl,以及Solaris 10上的Perl v5.8.8.
因此,如果我的所有测试都表明tzset没有效果,为什么/其他系统需要显式调用tzset?我还需要调用tzset以保持与某些环境的兼容性,还是现在已成为过去?
解决方法
Perl的本地时间调用localtime_r(3)
internally,不需要调用tzset(3). Linux manpage建议:
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().
在较旧的非多线程Perls中,或者如果在构建期间localtime_r(3)不可用,则使用localtime(3).在这种情况下,调用tzset是不必要的,per POSIX:
Local timezone information is used as though localtime() calls tzset()
虽然似乎有时间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.
虽然这确实发生了变化,但glibc现在确实就像调用tztime(3)一样,但仅适用于非重入本地时间,这可能不是你的Perl编译使用的.
有关于此的两个Perl错误报告:#26136和#41591.
作为修复,Perl现在decides at configuration time是否需要完成隐式tzset(3),这使得在用户代码中指定它是多余的.