ENV{TZ} and strftime in perl not working

Bug #347303 reported by jsteel
2
Affects Status Importance Assigned to Milestone
perl (Fedora)
Fix Released
Medium
perl (Ubuntu)
New
Undecided
Unassigned
Hardy
Won't Fix
Medium
Unassigned

Bug Description

If you run the following:

perl -e 'use POSIX;
$ENV{TZ} = "UTC";
my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
print "$time\n";
$ENV{TZ} = "US/Eastern";
my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
print "$time\n";'

You should get two different times.

2009-03-23 14:15:13 UTC
2009-03-23 10:15:13 EDT

 But in Ubuntu 8.04 server (lsb_release -rd =>Description: Ubuntu 8.04.2, Release: 8.04) you instead get

2009-03-23 14:15:40 UTC
2009-03-23 14:15:40 EDT

It does the same thing for almost any timezone you give it. It give UTC time but labels it as the proper time zone.

This happens on my 8.04 desktop version as well, but not on any 8.10 machines.

Revision history for this message
In , Jason (jason-redhat-bugs) wrote :
Download full text (3.8 KiB)

Description of problem:

This program should print out 2 different timestamps :
---
#!/usr/bin/perl
use POSIX ;
$t = time();
$ENV{'TZ'}="US/Eastern";
$east = scalar( localtime( $t ));
$ENV{'TZ'}="US/Western";
$west = scalar( localtime( $t ));
print $east,"\n", $west,"\n";
---

But it does not:
$ ./tz.pl
Thu Nov 3 13:54:04 2005
Thu Nov 3 13:54:04 2005

This is because when PERL is compiled with multi-threading enabled, it uses
localtime_r, which does not call 'tzset', contrary to the documentation
of localtime(3), which does call 'tzset'.

This is an upstream perl bug :
26136: localtime(3) calls tzset(3), but localtime_r(3) may not.
      ( http://rt.perl.org/rt3/Ticket/Display.html?id=26136 )

-- Additional comment from <email address hidden> on 2005-06-22 05:22 EST --
From User-Agent: XML-RPC

Analyzed the problem and tracked down its cause and also got a workaround.
(Thanks go to Bill Nottingham and Jakub Jelinek for help on this). To get
the original (pre-perl-5.8), you should declare "use POSIX qw(tzset);" at
the start of your script (with other use clauses) and instead of calling
"localtime" call "tzset; localtime" or after each $ENV{TZ} = assignment
call tzset; this should make the script behave as expected. We'll try and
consult perl upstream about this behaviour in the meantime and if the
proposed workaround is not good enough, we'll see if this can be corrected
in the perl package itself.

--- Additional comment from Issue Tracker (<email address hidden>) on 2005-06-22 05:22 EST

Actually, Pete Rockai found the solution; basically, glibc caches

the timezone. Given their example script, what they need to do is

do an explicit tzset() after setting the environment variable.

i.e.:
/usr/bin/perl -e 'use POSIX qw(tzset); my $t = time; print "$t ", scalar
localtime($t), "\n"; $ENV{TZ} = "Japan"; tzset; my $t = time; print
"$t ", scalar localtime($t), "\n";'

The reason this changed between perl-5.6.x and perl-5.8 is
probably because perl switched to using localtime_r (the thread-safe
version), which doesn't reset the timezone automatically.

What we'd recommend is that they fix their code to explicitly
set the timezone; we can see about having upstream perl change
its behavior to automatically do the tzset on calls to localtime(),
but we don't want to break compatibility with upstream by either
doing it ourselves, or switching perl back to using localtime
instead of localtime_r.

Bill

-- Additional comment from <email address hidden> on 2005-11-02 22:50 EST --
A fix for this issue has been developed, and appended as a patch to the
upstream perl bug that was raised on this issue :
26136: localtime(3) calls tzset(3), but localtime_r(3) may not.
      ( http://rt.perl.org/rt3/Ticket/Display.html?id=26136 )

If the upstream PERL developers agree to accept this patch, then I will
submit it to our PERL distribution.

The patch detects this problem during the Configure phase, and if it was
detected, and perl is being built multi-threaded (localtime_r is used),
will insert a tzset call before any localtime_r call .

The downside of this fix is that glibc uses mutex locking in the tzset call,
so there would be a performance hit and multi-threaded perl progra...

Read more...

Revision history for this message
In , Jason (jason-redhat-bugs) wrote :

This bug is fixed in perl-5.8.7-0.7.fc5 .

Revision history for this message
In , Robin (robin-redhat-bugs) wrote :

assigning to <email address hidden>

Revision history for this message
jsteel (jon-steel) wrote :

The following works:

use POSIX;
$ENV{TZ} = "UTC";
#my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
my $time = `date`;
print "$time\n";
$ENV{TZ} = "US/Eastern";
my $time = `date`;
#my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
print "$time\n";

And I ran the code that doesn't work with a source install of perl-5.10.0 and it worked as well. So it looks like its perls POSIX library that is installed by Ubuntu.

Revision history for this message
jsteel (jon-steel) wrote :

So it looks like its a bug with perl.

perl -v
This is perl, v5.8.8 built for i486-linux-gnu-thread-multi

When you call localtime for the first time it picks up the ENV{TZ} value and remembers it. Every time you call localtime after, it will use that old value for the TZ. The only way to change it would be to do something like the following:

sub mylocaltime
{
my $t = shift;
return split / /, `perl -le 'print join(" ",localtime($t))'`
}
my $time = time;
print "time = $time\n";

print "TZ = $ENV{TZ}\n";
print "$_ " for mylocaltime($time);

$ENV{TZ}='US/Central';
print "TZ = $ENV{TZ}\n";
print "$_ " for mylocaltime($time);

I guess I'll just install a newer version of perl :)

Changed in perl (Ubuntu Hardy):
milestone: none → ubuntu-8.04.3
importance: Undecided → Medium
status: New → Confirmed
Revision history for this message
Steve Peters (steve-fisharerojo) wrote : Re: [Bug 347303] [NEW] ENV{TZ} and strftime in perl not working

On Wed, Mar 25, 2009 at 4:13 PM, Launchpad Bug Tracker
<email address hidden> wrote:
> You have been subscribed to a public bug:
>
> If you run the following:
>
> perl -e 'use POSIX;
> $ENV{TZ} = "UTC";
> my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
> print "$time\n";
> $ENV{TZ} = "US/Eastern";
> my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
> print "$time\n";'
>
> You should get two different times.
>
> 2009-03-23 14:15:13 UTC
> 2009-03-23 10:15:13 EDT
>
>  But in Ubuntu 8.04 server (lsb_release -rd =>Description:      Ubuntu
> 8.04.2, Release: 8.04) you instead get
>
> 2009-03-23 14:15:40 UTC
> 2009-03-23 14:15:40 EDT
>
> It does the same thing for almost any timezone you give it. It give UTC
> time but labels it as the proper time zone.
>
> This happens on my 8.04 desktop version as well, but not on any 8.10
> machines.
>
> ** Affects: perl (Ubuntu)
>     Importance: Undecided
>         Status: New
>
> --
> ENV{TZ} and strftime in perl not working
> https://bugs.edge.launchpad.net/bugs/347303
> You received this bug notification because you are subscribed to perl in ubuntu.
>

I can confirm that the Perl distributed with Ubuntu 8.04 has problems.
 This problem, however, appears to be a bug in the Debian/Ubuntu perl.
 I just built the original Perl 5.8.8 and everything worked fine.
This problem is caused by some Debian/Ubuntu applied patch.

Steve Peters
<email address hidden>

Revision history for this message
Niko Tyni (ntyni) wrote :

On Thu, Mar 26, 2009 at 12:04:31PM -0000, Steve Peters wrote:
> On Wed, Mar 25, 2009 at 4:13 PM, Launchpad Bug Tracker
> <email address hidden> wrote:

> > perl -e 'use POSIX;
> > $ENV{TZ} = "UTC";
> > my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
> > print "$time\n";
> > $ENV{TZ} = "US/Eastern";
> > my $time = strftime("%Y-%m-%d %H:%M:%S %Z", localtime(time));
> > print "$time\n";'
> >
> > You should get two different times.
> >
> > 2009-03-23 14:15:13 UTC
> > 2009-03-23 10:15:13 EDT

> I can confirm that the Perl distributed with Ubuntu 8.04 has problems.
> This problem, however, appears to be a bug in the Debian/Ubuntu perl.
> I just built the original Perl 5.8.8 and everything worked fine.
> This problem is caused by some Debian/Ubuntu applied patch.

Did you build a threaded version?

This seems to be

 https://bugzilla.redhat.com/show_bug.cgi?id=172396
 http://rt.perl.org/rt3//Public/Bug/Display.html?id=26136

fixed with

 http://perl5.git.perl.org/perl.git/commitdiff/8572b25d

in 5.8.9 and 5.10.0.
--
Niko Tyni <email address hidden>

Changed in perl:
status: Unknown → Fix Released
Revision history for this message
Rolf Leggewie (r0lf) wrote :

Hardy has seen the end of its life and is no longer receiving any updates. Marking the Hardy task for this ticket as "Won't Fix".

Changed in perl (Ubuntu Hardy):
status: Confirmed → Won't Fix
Changed in perl (Fedora):
importance: Unknown → Medium
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.