problems with changing process.env.TZ at runtime

2,890 views
Skip to first unread message

SethP

unread,
May 15, 2012, 6:44:45 PM5/15/12
to nod...@googlegroups.com
Hi all,

Before I raised this as an issue on Node, I wanted to sanity-check it here. Basically, I'm having an issue where the Date constructor/localizer lags behind a change to process.env.TZ. Here's a script to reproduce what I'm seeing:

var assert = require('assert');

// if either of these three lines is commented out, the problem goes away
process.env.TZ = 'America/Los_Angeles';
console.log(new Date().toString());
process.env.TZ = "America/New_York";

// uncomment this and the problem goes away
//console.log(new Date().toString());

// create a date by parsing a string
var d = new Date('2012-1-12 02:00 PM');

// can also create the date this way
//var d = new Date(2012, 0, 12, 14);

// print the date value and locale string
console.log(d.getTime() + " " + d.toLocaleString());

// should create an identical date
var copy = new Date(d);

// print the copy's value and locale string
// the values are the same, but the **strings are different**
console.log(copy.getTime() + " " + copy.toLocaleString());

// here we see the date has been given the wrong value to begin with
assert.equal(d.getTime(), 1326394800000);


Hopefully this makes the problem clear - the script prints two dates with identical ms values but differing toString() values. Admittedly, it seems harsh to be jerking the TZ around like this, but I suspect there's a bug here.

Thanks,
Seth

Ben Noordhuis

unread,
May 15, 2012, 7:38:37 PM5/15/12
to nod...@googlegroups.com
It's not really a bug but a result of how the standard timezone
functions work on UNIX systems.

The date handling code in V8 implicitly calls tzset(3)[1] when you
first convert a string to a date or vice versa.

tzset() parses and caches the TZ environment variable. That means that
you can set TZ just once, further changes won't get picked up. Even
that may not work if Node's boot scripts did some date munging - which
they almost never do, fortunately.

[1] http://linux.die.net/man/3/tzset

SethP

unread,
May 15, 2012, 10:44:53 PM5/15/12
to nod...@googlegroups.com
Thanks, Ben - I figured you'd be the one to pick this up. (btw - how do you pronounce your name?)

The reason I think it may be a bug is that the output of the test script (sans assertion) is as follows:

Tue May 15 2012 19:21:53 GMT-0700 (PDT)
1326405600000 Thu Jan 12 2012 14:00:00 GMT-0500 (EST)
1326405600000 Thu Jan 12 2012 17:00:00 GMT-0500 (EST)

Two dates have identical getTime() values but different hours with the *same* tzinfo (EST). Regardless of which TZ is the current one, that should never happen, correct? It's a matter of internal consistency; one of those lines has got to be wrong. (The bottom line is correct; the date appears to be parsed as though the TZ is still America/LA)

Seth

Ben Noordhuis

unread,
May 16, 2012, 9:06:12 AM5/16/12
to nod...@googlegroups.com
On Wed, May 16, 2012 at 4:44 AM, SethP <kaio...@gmail.com> wrote:
> Thanks, Ben - I figured you'd be the one to pick this up. (btw - how do you
> pronounce your name?)

'North house' is a close enough approximation. :-)

> The reason I think it may be a bug is that the output of the test script
> (sans assertion) is as follows:
>
> Tue May 15 2012 19:21:53 GMT-0700 (PDT)
> 1326405600000 Thu Jan 12 2012 14:00:00 GMT-0500 (EST)
> 1326405600000 Thu Jan 12 2012 17:00:00 GMT-0500 (EST)
>
> Two dates have identical getTime() values but different hours with the
> *same* tzinfo (EST). Regardless of which TZ is the current one, that should
> never happen, correct? It's a matter of internal consistency; one of those
> lines has got to be wrong. (The bottom line is correct; the date appears to
> be parsed as though the TZ is still America/LA)

Yes, that's a V8 bug. It's mostly* fixed in master.

Your example still won't work quite right (the assertion will fail)
unless you `export TZ="America/New_York"` before running the script.
That can't really be helped, I'm afraid.

* There is still a bug in timezone handling on Solaris.

SethP

unread,
May 16, 2012, 5:15:49 PM5/16/12
to nod...@googlegroups.com


On Wednesday, May 16, 2012 9:06:12 AM UTC-4, Ben Noordhuis wrote:
> Thanks, Ben - I figured you'd be the one to pick this up. (btw - how do you
> pronounce your name?)

'North house' is a close enough approximation. :-)

Thanks for clearing that up for everyone. Maybe that can go in the group FAQ? :o)
 

> The reason I think it may be a bug is that the output of the test script
> (sans assertion) is as follows:
>
> Tue May 15 2012 19:21:53 GMT-0700 (PDT)
> 1326405600000 Thu Jan 12 2012 14:00:00 GMT-0500 (EST)
> 1326405600000 Thu Jan 12 2012 17:00:00 GMT-0500 (EST)
>
> Two dates have identical getTime() values but different hours with the
> *same* tzinfo (EST). Regardless of which TZ is the current one, that should
> never happen, correct? It's a matter of internal consistency; one of those
> lines has got to be wrong. (The bottom line is correct; the date appears to
> be parsed as though the TZ is still America/LA)

Yes, that's a V8 bug. It's mostly* fixed in master.

Your example still won't work quite right (the assertion will fail)
unless you `export TZ="America/New_York"` before running the script.
That can't really be helped, I'm afraid.

* There is still a bug in timezone handling on Solaris.

Good to know. I've abandoned my dumb approach and am now using node-time (which appears to have some oddities of its own lurking in the corner cases).

I figured something must be caching the TZinfo; here's a script that shows some perplexing behavior on OS X:

var d;

console.log(new Date().toString());

process.env.TZ = 'America/Los_Angeles';

d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

process.env.TZ = "America/New_York";
d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

process.env.TZ = 'America/Los_Angeles';

d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

process.env.TZ = 'America/Chicago';

d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

process.env.TZ = 'Hongkong';

d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

process.env.TZ = "America/New_York";
d = new Date('2012-1-12 02:00 PM');
console.log(new Date().toString());

When run with $TZ == undefined, I *usually* get:

Wed May 16 2012 17:06:22 GMT-0400 (EDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)
Wed May 16 2012 14:06:22 GMT-0700 (PDT)

But every now and then I get:

Wed May 16 2012 17:10:14 GMT-0400 (EDT)
Wed May 16 2012 14:10:14 GMT-0700 (PDT)
Wed May 16 2012 17:10:14 GMT-0400 (EDT)
Wed May 16 2012 17:10:14 GMT-0400 (EDT)
Wed May 16 2012 17:10:14 GMT-0400 (EDT)
Wed May 16 2012 17:10:14 GMT-0400 (EDT)
Wed May 16 2012 17:10:14 GMT-0400 (EDT)

And on rare times I get:

Wed May 16 2012 17:09:25 GMT-0400 (EDT)
Wed May 16 2012 14:09:25 GMT-0700 (PDT)
Wed May 16 2012 14:09:25 GMT-0700 (PDT)
Wed May 16 2012 14:09:25 GMT-0700 (PDT)
Wed May 16 2012 16:09:25 GMT-0500 (CDT)
Thu May 17 2012 05:09:25 GMT+0800 (HKT)
Wed May 16 2012 17:09:25 GMT-0400 (EDT)

Which I'd normally think was a race condition somewhere, but it's not apparent to me where there'd be a race. For added fun you can export TZ=GMT or something to spice it up; it's just stochastic as hell.

Nathan Rajlich

unread,
May 16, 2012, 6:24:05 PM5/16/12
to nod...@googlegroups.com
Let me know what kind of edge-cases you run into with node-time!

--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Ben Noordhuis

unread,
May 17, 2012, 12:01:28 AM5/17/12
to nod...@googlegroups.com
I see what you mean, it happens on Linux too. Does this patch[1] fix
it? It's against master but it probably applies to v0.6 as well:

[1] https://gist.github.com/71255d724b46f40693a1

SethP

unread,
May 17, 2012, 11:50:23 AM5/17/12
to nod...@googlegroups.com
Thanks, Ben. The patch applied fine to my v0.6.17-release branch, but doesn't appear to have fixed the issue.

(Also, 'make clean' doesn't seem to drop the /out dir - which doesn't seem very clean to me; I dropped it manually.)

Ben Noordhuis

unread,
May 17, 2012, 4:48:16 PM5/17/12
to nod...@googlegroups.com
Try `make distclean` :-)

It seems this issue needs some further investigation. If you open a
bug report, we'll look into it.

SethP

unread,
May 19, 2012, 11:21:12 AM5/19/12
to nod...@googlegroups.com
Ok, opened issue: https://github.com/joyent/node/issues/3286

Thanks!

Alan Gutierrez

unread,
Jun 5, 2012, 1:33:09 AM6/5/12
to nod...@googlegroups.com
On 5/15/12 10:44 PM, SethP wrote:
> Thanks, Ben - I figured you'd be the one to pick this up. (btw - how do
> you pronounce your name?)
>
> The reason I think it may be a bug is that the output of the test script
> (sans assertion) is as follows:
>
> Tue May 15 2012 19:21:53 GMT-0700 (PDT)
> 1326405600000 Thu Jan 12 2012 14:00:00 GMT-0500 (EST)
> 1326405600000 Thu Jan 12 2012 17:00:00 GMT-0500 (EST)
>
> Two dates have identical getTime() values but different hours with the
> *same* tzinfo (EST). Regardless of which TZ is the current one, that
> should never happen, correct? It's a matter of internal consistency; one
> of those lines has got to be wrong. (The bottom line is correct; the
> date appears to be parsed as though the TZ is still America/LA)

An old issue, but I thought I'd suggest...

https://github.com/bigeasy/timezone

..if you're still working with timezones and having trouble with this.

Timezone will address problems like one you mention above. It will
generate the correct time for any timezone string since the dawn of
standard time and into the future.

--
Alan Gutierrez - @bigeasy
Reply all
Reply to author
Forward
0 new messages