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
精彩评论