Jeff Gay
Jeff Gay

Reputation: 1

Why is localtime in ActivePerl on windows 7 not correct when I change $ENV{TZ}?

I'm using Bugzilla on an IIS server which uses Perl's DateTime module. Unfortunately the time is showing incorrectly. gmtime shows the correct time in GMT but localtime does not give the correct time when I change $ENV{TZ}.

Here is some code to demonstrate the issue:

#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";

This prints:

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

Here are the expected results:

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

Here is my perl version information:

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.

I have seen posts that say you have to run

POSIX::tzset();

after changing $ENV{TZ}, but when I try that, I get an error:

POSIX::tzset not implemented on this architecture.

Here are the server logs for IIS. The times are in UTC and are correct.

#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

How can I fix this?

Our Solution was to move Bugzilla to a Linux Guest OS on a VM. This solved the problem.

Upvotes: 0

Views: 721

Answers (3)

Sinan Ünür
Sinan Ünür

Reputation: 118156

The documentation for _tzset explains the acceptable format for $ENV{TZ}:

set TZ=tzn[+ | –]hh[:mm[:ss] ][dzn]

tzn: Three-letter time-zone name, such as PST. You must specify the correct offset from local time to UTC.

hh: Difference in hours between UTC and local time. Sign (+) optional for positive values.

mm: Minutes. Separated from hh by a colon (:).

ss: Seconds. Separated from mm by a colon (:).

dzn: Three-letter daylight-saving-time zone such as PDT. If daylight saving time is never in effect in the locality, set TZ without a value for dzn. The C run-time library assumes the United States' rules for implementing the calculation of daylight saving time (DST).

So, the following works:

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

But, you'll find that some other values "work" as well, even though they are not documented:

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

Upvotes: 1

Oesor
Oesor

Reputation: 6642

The code you posted is not using 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;
                  "

Output (from 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

Upvotes: 1

ikegami
ikegami

Reputation: 386501

You need to call POSIX::tzset() after changing $ENV{TZ}.

Upvotes: 1

Related Questions