[ python-Bugs-1647654 ] No obvious and correct way to get the time zone offset

SourceForge.net noreply at sourceforge.net
Mon Mar 5 11:03:49 CET 2007


Bugs item #1647654, was opened at 2007-01-30 13:48
Message generated for change (Comment added) made by jhenstridge
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1647654&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: James Henstridge (jhenstridge)
Assigned to: Nobody/Anonymous (nobody)
Summary: No obvious and correct way to get the time zone offset

Initial Comment:
It would be nice if the Python time module provided an obvious way to get the local time UTC offset for an arbitrary time stamp.  The existing constants included in the module are not sufficient to correctly determine this value.

As context, the Bazaar version control system (written in Python), the local time UTC offset is recorded in a commit.

The method used in releases prior to 0.14 made use of the "daylight", "timezone" and "altzone" constants from the time module like this:

    if time.localtime(t).tm_isdst and time.daylight:
        return -time.altzone
    else:
        return -time.timezone

This worked most of the time, but would occasionally give incorrect results.

On Linux, the local time system can handle different daylight saving rules for different spans of years.  For years where the rules change, these constants can provide incorrect data.  Furthermore, they may be incorrect for time stamps in the past.

I personally ran into this problem last December when Western Australia adopted daylight saving -- time.altzone gave an incorrect value until the start of 2007.

Having a function in the standard library to calculate this offset would solve the problem.  The implementation we ended up with for Bazaar was:

    offset = datetime.fromtimestamp(t) - datetime.utcfromtimestamp(t)
    return offset.days * 86400 + offset.seconds

Another alternative would be to expose tm_gmtoff on time tuples (perhaps using the above code to synthesise it on platforms that don't have the field).

----------------------------------------------------------------------

>Comment By: James Henstridge (jhenstridge)
Date: 2007-03-05 18:03

Message:
Logged In: YES 
user_id=146903
Originator: YES

In Western Australia, a 3 year daylight saving trial was introduced
starting on 3rd December 2006.  Prior to that, we had no daylight saving
shifts (the previous time we had daylight saving was 15 years ago in
another trial).

Since there was no daylight savings for 1st January 2006 and 1st July
2006, time.timezone and time.altzone were both equal to -28800 (UTC+8) for
Python interpreters run in 2006.

I am sure that I had the tzdata updates installed: my computer displayed
the correct time, and listed the UTC offset as +0900 in December.  Creating
a time tuple for a date in December 2006 had the tm_isdst flag set to 1.

If I was programming this in C, I'd use the tm_gmtoff field of "struct tm"
if it was available.  On platforms that don't provide tm_gmtoff, other
platform specific methods would be needed (e.g. using timezone/altzone).

The other alternative is to do date arithmetic on the results of
localtime() and gmtime(), as you say.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2007-03-02 23:48

Message:
Logged In: YES 
user_id=6380
Originator: NO

Hm.... I'm not sure I understand why the first bit of code didn't work. 
Can you give a concrete example?  (I.e. what was t, what was returned by
localtime(t), and what were the three time variables that day.)

I don't know the details of Western Australia's DST change.  But looking
at the source of timemodule.c, I notice that it simply samples the timezone
on Jan 1st and July 1st, and if they differ, decides which one is summer
time by which one is smaller.  Your remark that the problem righted itself
in January makes me wonder -- between what dates did you have DST?

Alternatively, it could be that your system simply didn't have the correct
DST change data loaded yet (this happens all the time when governments
change the rules).  Can you rule that out?  I really don't want to have to
change Python in order to correct for *that* problem.

Yet another question, if you were to code this in C, how would you write
it?

Regardless, I think that it would be useful to support tm_gmtoff and other
struct tm entries, the same way that we do this in struct stat.

You could probably also get the correct result (assuming your system's
timezone database is correct) by comparing localtime() and gmtime().  But
the reverse engineering is a bit painful; your trick using datetime
essentially does that.

----------------------------------------------------------------------

Comment By: James Henstridge (jhenstridge)
Date: 2007-03-01 18:09

Message:
Logged In: YES 
user_id=146903
Originator: YES

The localtime_tz() function sounds like it would probably fit the bill.

Another option would be to expose tm_gmtoff and tm_zone as non-sequence
fields of time.struct_time for systems that support them.  This would
provide the data without needing new APIs.

----------------------------------------------------------------------

Comment By: Paul Boddie (pboddie)
Date: 2007-02-24 08:31

Message:
Logged In: YES 
user_id=226443
Originator: NO

See patch #1667546 for a time module function returning extended time
tuples. The datetime-based solution you provide is quite a clever
workaround using "naive" datetime objects, but I'm inclined to think that
some more convenient way of getting "aware" datetime objects would be
nicer.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1647654&group_id=5470


More information about the Python-bugs-list mailing list