Reputation: 1934
As you can see from the snippet below, there's a one hour difference between the two method. What is the reason ?
from datetime import datetime
from pytz import timezone
import time
def timestamp2date(timestamp):
# function converts a UTC timestamp into Europe/Zurich Gregorian date
DATE_TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
utcTimeStamp = datetime.fromtimestamp(int(timestamp)).replace(tzinfo=timezone('UTC'))
return utcTimeStamp.astimezone(timezone('Europe/Zurich')).strftime(DATE_TIME_FORMAT)
timeStampUTC_1 = time.mktime(datetime.utcnow().timetuple())
print(timeStampUTC_1)
print(timestamp2date(timeStampUTC_1))
timeStampUTC_2 = time.mktime(datetime.now(timezone('UTC')).timetuple())
print(timeStampUTC_2)
print(timestamp2date(timeStampUTC_2))
print(timeStampUTC_2 - timeStampUTC_1)
# 1504385450.0
# 2017-09-03 00:50:50 this the right time
# 1504389050.0
# 2017-09-03 01:50:50
# 3600.0
Upvotes: 0
Views: 1017
Reputation: 1934
Here's the result of my further exploration of the timezone concept associated with the daylight saving time flag. The code is pretty straightforward.
To summarize the results, there's a right way to handle date/time information:
code:
from datetime import datetime
from pytz import timezone
import time
print("---- Winter time (CET=Central European Time) ----")
dateStr = "2014-02-28 22:28:15"
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S")
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8]))
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized)
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8]))
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print("\n---- Summer time (CEST=Central European Summer Time) ----")
dateStr = "2014-06-28 22:28:15"
datetimeObjUnlocalized = datetime.strptime(dateStr, "%Y-%m-%d %H:%M:%S")
print('UNL: ' + datetimeObjUnlocalized.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjUnlocalized-->tm_isdst=' + str(datetimeObjUnlocalized.timetuple()[8]))
datetimeObjZH = timezone('Europe/Zurich').localize(datetimeObjUnlocalized)
print('ZH: ' + datetimeObjZH.strftime("%Y-%m-%d %H:%M:%S %Z%z"))
print(' datetimeObjZH-->tm_isdst=' + str(datetimeObjZH.timetuple()[8]))
print("UTC: " + datetimeObjZH.astimezone(timezone('UTC')).strftime("%Y-%m-%d %H:%M:%S %Z%z"))
Upvotes: 0
Reputation: 30258
The reason is that datetime.timetuple()
sets dst=-1
if the datetime
is not offset aware and dst=0 or 1
when it is offset aware.
From the documentation:
The
tm_isdst
flag of the result is set according to thedst()
method:tzinfo
isNone
ordst()
returnsNone
,tm_isdst
is set to-1
; else ifdst()
returns a non-zero value,tm_isdst
is set to1
; elsetm_isdst
is set to0
.
In []:
datetime.utcnow()
Out[]:
datetime.datetime(2017, 9, 2, 23, 9, 12, 715042)
In []:
print(datetime.utcnow().dst())
Out[]:
None
In []:
datetime.now(timezone('UTC'))
Out[]:
datetime.datetime(2017, 9, 2, 23, 9, 15, 856983, tzinfo=<UTC>)
In []:
datetime.now(timezone('UTC')).dst()
Out[]
datetime.timedelta(0)
In []:
datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple()
Out[]:
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9,
tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=-1)
^^
In []:
datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple()
Out[]:
time.struct_time(tm_year=2017, tm_mon=9, tm_mday=2, tm_hour=23, tm_min=9,
tm_sec=15, tm_wday=5, tm_yday=245, tm_isdst=0)
^
This changes the timestamp
that time.mktime()
generates because mktime
treats -1
unknown and uses localtime, so may calculate dst=1
and hence they could be an 1 hour different (3600s
):
In []:
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983).timetuple())
Out[]:
1504411755.0
In []:
time.mktime(datetime(2017, 9, 2, 23, 9, 15, 856983, timezone('UTC')).timetuple())
Out[]:
1504415355.0
Upvotes: 1