开发者

What is the fastest way to detect when two timestamps produce the same local time in Python?

The UNIX timestamps 1289106000 and 1289109600 both represent 2010-11-07T01:00:00 in the US-East EST/EDT timezone, as a result of daylight savings time. I'm creating a dictionary-like object, keyed on timestamp, that needs to map any such pairs to the same value.

Additionally, as much as we want to avoid premature optimization, I happen to know that this operation 开发者_开发知识库is performed in an extremely tight loop. Any solution must be faster than using fromtimestamp to obtain the local time for each timestamp.

Is there a way to structure my object's back-end storage, or build some sort of lookup table in advance, that makes this possible?


You could build a table, stretching as far into the past or future as you wish, with the overlapping hour for each year. It's easy to convert the timestamp to an approximate year with a simple division. Look up the tuple (start_leap_hour,end_leap_hour) from the year; if the timestamp is between them, subtract an hour.


Regarding how one might generate a table of DST critical times:

This generates the datetimes when Daylight Savings Time "fall back" occurs:

import datetime as dt
import time
import itertools

def fall_dst_boundaries(date=None):
    '''
    Generates the datetimes when Daylight Savings Time "fall back" occurs after date.
    '''
    if date is None:
        date=dt.datetime.now()
    timestamp=time.mktime(date.timetuple())//3600 * 3600
    previous_date=dt.datetime.fromtimestamp(timestamp)
    while True:
        timestamp+=3600
        date=dt.datetime.fromtimestamp(timestamp)
        if date==previous_date:
            yield date
        previous_date=date

for date in itertools.islice(fall_dst_boundaries(dt.datetime(1980,1,1)),15):
    print(date)

yields:

1980-10-26 01:00:00
1981-10-25 01:00:00
1982-10-31 01:00:00
1983-10-30 01:00:00
1984-10-28 01:00:00
1985-10-27 01:00:00
1986-10-26 01:00:00
1987-10-25 01:00:00
1988-10-30 01:00:00
1989-10-29 01:00:00
1990-10-28 01:00:00
1991-10-27 01:00:00
1992-10-25 01:00:00
1993-10-31 01:00:00
1994-10-30 01:00:00

PS. DST ends at 2am, but the hour the gets repeated is 1am.


To generate both the "fall back" and "spring forward" datetimes, you could use something like this:

def DST_boundaries(date=None):
    '''
    Generates the datetimes when Daylight Savings Time "fall back" or "spring
    forward" occurs after date.
    '''
    if date is None:
        date=dt.datetime.now()
    timestamp=time.mktime(date.timetuple())//3600 * 3600 + 3599
    previous_date=dt.datetime.fromtimestamp(timestamp)
    while True:
        timestamp+=3600
        date=dt.datetime.fromtimestamp(timestamp)
        if date==previous_date or date.hour-previous_date.hour>1:
            yield previous_date
        previous_date=date
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜