2012-03-28 29 views
6

我使用datetime.fromtimestamp将epoch时间转换成本地时间。我发现datetime.fromtimestamp在某个特定的时间点会做一小时的离散跳跃,我完全不知道为什么会这样做。Python的`fromtimestamp`做了离散跳转

(我也是用time.mktime为datetime对象转换为划时代的时间,as suggested by Raymond Hettinger。我不知道这是否是对这个问题的相关信息,所以我说这只是以防万一。)

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import time, datetime 
>>> def datetime_to_epoch_time(datetime_): 
...  return time.mktime(datetime_.timetuple()) + datetime_.microsecond/1e6 
... 

挑选一个特定历元时间:

>>> x = datetime_to_epoch_time(datetime.datetime(2012, 3, 30, 3, 0)) 

它转换为一个日期时间使用fromtimestamp

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 

我们得到凌晨3点的时间。

现在让我们转换之前,这正是一秒钟时间:

>>> datetime.datetime.fromtimestamp(x-1) 
datetime.datetime(2012, 3, 30, 1, 59, 59) 

我们突然得到凌晨1:59!

发生了什么事?我知道这样的事情发生在闰日附近,但是从3月30日什么时候开始闰日呢?

我应该注意到,我只在Linux上发生过这种情况,而不是在Windows上。我认为不同的Linux计算机(在不同的时区)有不同的时间点,其中fromtimestamp跳跃。

回答

4

简单。 3月30日大概是您所在时区的夏令时开关。

所以在这一天,时间确实从一点59分59秒到3:00:00

+0

我明白了。所以'fromtimestamp'知道我所在的时区,并知道要跳过哪几个小时。但是'datetime'对象不知道这个跳转:如果我从凌晨2点减去'datetime'对象,那么我会得到一个小时的'timedelta',我应该得到零。 – 2012-03-28 20:36:26

+0

那么,如何让'datetime'对象知道我的时区,并使它们使用* exact *某个时区作为'fromtimestamp',因此它们将完全同步? – 2012-03-28 20:37:13

+0

@RamRachum构造时间戳时传递'tzinfo'标志。 'pytz'库可能对此有所帮助。 – Amber 2012-03-28 20:46:26

7

fromtimestamp使用当前用户的“本地环境”,由POSIX C库定义(见man (3) tzset,和time模块的文档)。

如果您确实想要获得当前用户环境的本地时间的pytz表示,则datetime-tz程序包具有用于自动检测它的功能。

然而,常见的智慧是始终与UTC一起工作,并避免所有DST问题(仅使用本地时区进行最终显示)。使用datetime.fromtimestamp(x, tz=pytz.UTC),或者,如果你没有pytz

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 
>>> datetime.datetime.utcfromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
>>> datetime.datetime.utcfromtimestamp(x-1) 
datetime.datetime(2012, 3, 29, 23, 59, 59) 

附:您也可以将您的进程的语言环境设置为UTC(但这可能不适用于非POSIX操作系统):

>>> import os,time 
>>> os.environ["TZ"] = "UTC" 
>>> time.tzset() 
>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
+0

+1伟大的建议。 – 2012-03-30 11:35:15