Reputation: 4366
I wrote such a code to get timezone based on DST for an specific epoch time:
def getTimeZoneFromEpoch(epoch)
if time.daylight and time.gmtime(epoch).tm_isdst==1:
return -time.altzone/3600.0
else:
return -time.timezone/3600.0
But i'm not sure its correct, in fact at the moment i mistakes by 1 hour. Maybe i should swap altzone and timezone in this code, but its not what i understood from python's help (time module):
timezone -- difference in seconds between UTC and local standard time
altzone -- difference in seconds between UTC and local DST time
tm_isdst
1 if summer time is in effect, 0 if not, and -1 if unknown
Have i misundestood something?
Upvotes: 2
Views: 3017
Reputation: 4366
Thanks for the help, besides the two methods that you suggested, I also found a more flexible (and maybe more compatible) version that can also take timezone object (or just use local zone) and return UTC offset
There was just this AmbiguousTimeError part that confused me, but I did something about it to make it (kind of) working in all cases.
from datetime import datetime
import pytz
from tzlocal import get_localzone
def getUtcOffsetByEpoch(epoch, tz=None):
if not tz:
tz = get_localzone()
delta = 0
while True:
try:
return tz.utcoffset(datetime.fromtimestamp(epoch + delta)).total_seconds()
except pytz.exceptions.AmbiguousTimeError:## FIXME
#d = datetime.fromtimestamp(epoch+3600)
#print('AmbiguousTimeError', d.year, d.month, d.day, d.hour, d.minute, d.second)
delta += 3600
print('delta = %s'%delta)
except (
ValueError,
OverflowError,
):
return tz._utcoffset.total_seconds()
Upvotes: 1
Reputation: 27565
In short, use time.localtime()
instead of time.gmtime()
.
The problem is that you use gmtime()
, as the result of the following program shows.
from time import *
def getTimeZoneFromEpoch(epoch):
if daylight and gmtime(epoch).tm_isdst==1:
return -altzone/3600.0
else:
return -timezone/3600.0
print " tm_isdst of tm_isdst of time zone's\n" + \
' epoch gmtime(epoch) localtime(epoch) offset'
for d in ('13/03/2011', # DST start date in USA
'14/03/2011',
'',
'06/11/2011', # DST end date in USA
'07/11/2011',
'',
'27/03/2011', # DST start date in Europe
'28/03/2011',
'',
'30/10/2011', # DST end date in Europe
'31/10/2011'):
if d:
ds = strptime(d,'%d/%m/%Y')
epoch = mktime(ds)
lt = localtime(epoch)
gt = gmtime(epoch)
print '%s %s %12s %11s %7s %17s' % (d,ds.tm_isdst,epoch,gt.tm_isdst,lt.tm_isdst,getTimeZoneFromEpoch(epoch))
else:
print
With my clock set to the "UTC-07:00 Rocky Mountains" time zone, where the DST starts on March 13th 2011 and ends on November 06th 2011 , the result is:
tm_isdst of tm_isdst of time zone's
epoch gmtime(epoch) localtime(epoch) offset
13/03/2011 -1 1299999600.0 0 0 -7.0
14/03/2011 -1 1300082400.0 0 1 -7.0
06/11/2011 -1 1320559200.0 0 1 -7.0
07/11/2011 -1 1320649200.0 0 0 -7.0
27/03/2011 -1 1301205600.0 0 1 -7.0
28/03/2011 -1 1301292000.0 0 1 -7.0
30/10/2011 -1 1319954400.0 0 1 -7.0
31/10/2011 -1 1320040800.0 0 1 -7.0
With my clock set to the "UTC+01:00 West Continental Europe" time zone, where the DST starts on March 27th 2011 and ends on October 30th 2011 , the result is:
tm_isdst of tm_isdst of time zone's
epoch gmtime(epoch) localtime(epoch) offset
13/03/2011 -1 1299970800.0 0 0 1.0
14/03/2011 -1 1300057200.0 0 0 1.0
06/11/2011 -1 1320534000.0 0 0 1.0
07/11/2011 -1 1320620400.0 0 0 1.0
27/03/2011 -1 1301180400.0 0 0 1.0
28/03/2011 -1 1301263200.0 0 1 1.0
30/10/2011 -1 1319925600.0 0 1 1.0
31/10/2011 -1 1320015600.0 0 0 1.0
Upvotes: 4
Reputation: 19317
I've tested this code to obtain the VM's locale UTC offset. Which, by the way, is only really valid at the moment it is measured. I'm not sure whether your code is equivalent or not.
def local_ephemeral_UTC_offset(epoch_time=None):
u"Returns a datetime.timedelta object representing the local time offset from UTC at the moment"
if epoch_time == None:
epoch_time = time()
return datetime.fromtimestamp(epoch_time) - datetime.utcfromtimestamp(epoch_time)
Upvotes: 4