当我更改$ ENV {TZ}时,为什么Windows 7上的ActivePerl中的localtime不正确?

时间:2015-03-18 16:08:02

标签: perl datetime timezone

我在使用Perl的DateTime模块的IIS服务器上使用Bugzilla。不幸的是,时间显示不正确。 gmtime显示GMT中的正确时间,但localtime在更改$ENV{TZ}时没有给出正确的时间。

以下是一些用于演示此问题的代码:

#C:\Perl64\bin/perl -w
$ENV{TZ} = 'America/New_York';
my $now = scalar localtime;
$TZone =  $ENV{'TZ'}; 
print "It is now $now $TZone\n";

$ENV{TZ} = 'America/Los_Angeles';
my $now = scalar localtime;
$TZone =  $ENV{'TZ'}; 
print "It is now $now $TZone\n";

my $GMTime = scalar gmtime;
print "It is now $GMTime GMT\n";

打印:

It is now Wed Mar 18 17:02:46 2015 America/New_York
It is now Wed Mar 18 17:02:46 2015 America/Los_Angeles
It is now Wed Mar 18 16:02:46 2015 GMT

以下是预期结果:

It is now Wed Mar 18 12:02:46 2015 America/New_York
It is now Wed Mar 18 9:02:46 2015 America/Los_Angeles
It is now Wed Mar 18 16:02:46 2015 GMT

这是我的perl版本信息:

This is perl 5, version 20, subversion 1 (v5.20.1) built for MSWin32-x64-multi-thread
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2014, Larry Wall

Binary build 2000 [298557] provided by ActiveState http://www.ActiveState.com
Built Oct 15 2014 14:56:57

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

我看到posts表示你必须运行

POSIX::tzset();

更改$ENV{TZ}后,但是当我尝试时,我收到错误:

POSIX::tzset not implemented on this architecture.

以下是IIS的服务器日志。时间是UTC并且是正确的。

#Software: Microsoft Internet Information Services 7.5
#Version: 1.0
#Date: 2015-03-18 20:15:34
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken
2015-03-18 20:17:52 127.0.0.1 GET /bugzilla/skins/standard/show_bug.css - 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/42.0.2311.39+Safari/537.36 304 0 0 1
2015-03-18 20:17:52 127.0.0.1 GET /bugzilla/js/comments.js - 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/42.0.2311.39+Safari/537.36 304 0 0 24
2015-03-18 20:18:06 127.0.0.1 POST /bugzilla/process_bug.cgi - 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/42.0.2311.39+Safari/537.36 200 0 0 9498
2015-03-18 20:18:23 127.0.0.1 GET /bugzilla/show_bug.cgi id=1 80 - 127.0.0.1 Mozilla/5.0+(Windows+NT+6.1;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/42.0.2311.39+Safari/537.36 200 0 0 1164

我该如何解决这个问题?

我们的解决方案是将Bugzilla迁移到VM上的Linux Guest OS。这解决了这个问题。

3 个答案:

答案 0 :(得分:1)

更改POSIX::tzset()后,您需要致电$ENV{TZ}

答案 1 :(得分:1)

您发布的代码未使用DateTime

perl -MDateTime -E" say DateTime->now(time_zone => 'local'); 
                    say DateTime->now(time_zone => 'America/New_York');
                    say DateTime->now(time_zone => 'America/Los_Angeles');
                    say DateTime->now(time_zone => 'GMT');

                    my $now = DateTime->now(time_zone => 'local');
                    say 'before conversion: ', $now;
                    $now->set_time_zone('America/New_York');
                    say 'after conversion: ', $now;
                  "

输出(来自CST):

2015-03-18T11:47:10
2015-03-18T12:47:10
2015-03-18T09:47:10
2015-03-18T16:47:10
before conversion: 2015-03-18T11:47:10
after conversion: 2015-03-18T12:47:10

答案 2 :(得分:1)

_tzset的文档解释了$ENV{TZ}的可接受格式:

  

设置TZ = tzn [+ | - ] hh [:mm [:ss]] [dzn]

     

tzn:三个字母的时区名称,例如PST。您必须指定从本地时间到UTC的正确偏移量。

     

hh: UTC与当地时间之间的小时差异。为正值签名(+)可选。

     

mm:分钟。与冒号(:)分开。

     

ss:秒。用冒号(:)与mm分开。

     

dzn:三个字母的夏令时区,如PDT。如果夏令时在本地区永远不会生效,set TZ没有dzn的值。 C运行时库假设美国'实施夏令时(DST)计算的规则。

所以,以下工作:

 C:\> perl -E "$ENV{TZ}='PST-8:00PDT';say scalar localtime"
Wed Mar 18 15:44:57 2015

但是,你会发现一些其他的价值观和工作#34;同样,即使他们没有记录:

C:\> set TZ='-08:00'

C:\> perl -E "say scalar localtime"
Wed Mar 18 12:27:33 2015
C:\> set TZ=

C:\> perl -E "say scalar localtime"
Wed Mar 18 15:28:03 2015
C:\> perl -E "$ENV{TZ}=q{'-08:00'};say scalar localtime"
Wed Mar 18 15:34:41 2015
C:\> perl -E "$ENV{TZ}=q{'America/Los_Angeles'};say scalar localtime"
Wed Mar 18 15:35:09 2015