2017-09-02 72 views
0

正如你可以从下面的代码片段看到的,两种方法之间有一个小时的差异。是什么原因 ?为什么datetime.utcnow()和datetime.now(timezone('UTC'))之间有区别?

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 
+0

我没有在我的Windows 10笔记本电脑QPython NND我的Android智能手机,其执行的Python 3.2解释器中运行的python 3.6的代码,我获得同样的区别。我当地的时区是欧洲/苏黎世。 –

+0

...但即使以美国/太平洋作为时区,差异也是如此。 –

回答

1

的原因是,datetime.timetuple()dst=-1如果datetime没有偏移量感知和dst=0 or 1当偏移量感知。

从文档:

结果的tm_isdst标志根据dst()方法设置:tzinfoNonedst()返回Nonetm_isdst设为-1;否则,如果dst()返回非零值,则tm_isdst设置为1;否则tm_isdst设置为0

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) 
                  ^

这改变了timestamptime.mktime()生成因为mktime对待-1未知,并且使用本地时间,所以可以计算dst=1,因此,它们可以是一个1小时不同(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 
+0

从文档:在调用mktime()时,夏令时有效时tm_isdst可能设置为1,如果不是,则为0。值为-1表示这是未知的,并且通常会导致填充正确的状态。 –

+0

@ Jean-PierreSchnyder mktime的文档状态为:“它的参数是struct_time或完整的9元组(自dst标志是必需的;如果它是未知的,则使用-1作为dst标志)表示当地时间的时间**,而不是UTC **。所以,如果你给它'-1',但你已经通过'UTC'时间,它会纠正'localtime',所以你得到的差异。 – AChampion

0

这里的这是我进一步探索与夏令时标志相关的时区概念的结果。代码非常简单。

总结的结果,有处理日期/时间信息的正确方法:

  1. 日期/时间对象必须本地化
  2. 如果正确本地化,日期/时间对象是否显示正确的夏令时信息
  3. 将您的本地化日期/时间对象转换为根据定义的UTC日期/时间对象时会反映这一点DST不可知
  4. 当您访问股票或货币历史记录时,所有这些考虑事项尤其相关CAL分钟费率API

代码:

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")) 

Console output

相关问题