在Python中,如何将“ datetime”对象转换为秒?


226

为这个简单的问题表示歉意...我是Python的新手...我四处搜寻,似乎没有任何反应。

我有一堆datetime对象,我想计算每个对象过去某个固定时间以来的秒数(例如,自1970年1月1日起)。

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

这似乎只能区分具有不同日期的日期:

t.toordinal()

任何帮助深表感谢。



2
从时代开始,我可能会将它们都转换为S并从那里去: int(t.timestamp())
nerdwaller

对于相反的操作,请转到此处:将秒数转换为新的日期时间对象
Trevor Boyd Smith,

Answers:


233

在1970年1月1日这个特殊日期,有多种选择。

对于任何其他开始日期,您需要以秒为单位获取两个日期之间的差额。将两个日期相减得到一个timedelta对象,从Python 2.7开始,该对象具有total_seconds()功能。

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

通常以UTC指定开始日期,因此,要获得正确的结果,datetime您也应使用UTC输入该公式。如果您datetime尚未使用UTC,则需要先进行转换,再使用它,或附加tzinfo具有适当偏移量的类。

如评论中所述,如果您有tzinfo附件,datetime则在开始日期也需要一个附件,否则减法将会失败;对于上面的示例,tzinfo=pytz.utc如果使用Python 2或tzinfo=timezone.utcPython 3 ,我会添加。


1
Python现在警告我:“ TypeError:无法减去天真的偏移量和知道偏移量的日期时间”修复此问题的最佳解决方案是什么?
亚伦·阿什

2
@Charybdis,尝试datetime.datetime(1970,1,1,tzinfo=pytz.utc)
Mark Ransom

9
考虑使用:datetime.datetime.utcfromtimestamp(0) 我已经使用它来轻松获得“时代”。请注意,在所有系统上,纪元并不总是相同的。
2013年

3
请注意此处的时区。我在UTC + 2,这意味着输出time.time()datetime.now() - datetime(1970, 1, 1)通过7200秒不同。宁可使用(t - datetime.datetime.fromtimestamp(0)).total_seconds()。千万不能使用utcfromtimestamp(0),如果你想将时间值转换在您的本地时区。
卡尔

2
@DA:Python不支持非POSIX纪元。使用python的所有系统都使用相同的纪元:1970
jfs

130

要获取Unix时间(自1970年1月1日以来的秒数):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0

22
使用time.mktime它的明确的本地时间时一定要小心,它是依赖于平台的
师温溯

7
确实要小心。这让我对自己的屁股感到很开心
Arg

它假定这t是当地时间。本地时区的UTC偏移量过去可能有所不同,并且mktime()(C库)无法访问给定平台上的历史时区数据,否则可能会失败(这pytz是可访问tz数据库的可移植方式)。另外,本地时间可能是模棱两可的,例如在DST转换期间-您需要其他信息来消除歧义,例如,如果您知道日志文件中的连续日期/时间值应该增加
jfs 2015年

1
在几分之一秒的时间内使用此功能时要小心。time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())结果为1564819506.0,默默地降低了毫秒,但是datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(Andrzej Pronobis的答案)结果1564819506.912为预期结果。
亚历克斯

128

从Python 3.3开始,使用此datetime.timestamp()方法变得非常容易。当然,这仅在需要从1970-01-01 UTC开始的秒数时才有用。

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

返回值将是代表偶数秒的浮点数。如果datetime是时区朴素的(如上例所示),则将假定datetime对象代表本地时间,即,它是从您所在位置的当前时间到1970-01-01 UTC的秒数。


3
谁对此表示反对,请您解释一下原因?
Andrzej Pronobis 2015年

5
我认为,downvote是由于问题上的python-2.7标签(这只是一个猜测)。
jfs

3
这应该是接受的答案/接受的答案应该相应地更新。
DreamFlasher

11
我想是时候升级了;)
DreamFlasher

可以从另一个开始日期算起这个距离?(我的意思是更改1970-01-01的日期)
pellerossa pelles

29

也许离题:从日期时间获取UNIX / POSIX时间并将其转换回:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

请注意,不同的时区会影响结果,例如我当前的TZ / DST返回:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

因此,应该考虑使用功能的UTC版本将其标准化为UTC。

请注意,先前的结果可用于计算您当前时区的UTC偏移量。在此示例中,这是+1小时,即UTC + 0100。

参考文献:


mktime()可能会失败。通常,您需要pytz将本地时间转换为utc,以获得POSIX时间戳。
jfs

calendar.timegm()似​​乎是time.mktime()的utc版本
弗兰克斯

27

int (t.strftime("%s")) 也可以


1
在Python 2.7中对我有效,具有import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(由OP指定)。但实际上,我怀疑%s是最近添加的时间格式。
dan3'4

1
@ dan3:错了。%s不支持(如果t是表示本地时间的幼稚datetime对象,并且如果本地C库可以访问tz数据库,则它可能在某些平台上有效,否则结果可能是错误的)。不要使用它。
jfs 2015年

%s没有记录在任何地方。我将其播种在真实代码中,想知道这是什么,然后查看文档,就没有这样的东西%s。仅在几秒钟内就有大S。
VStoykov

13

从python文档:

timedelta.total_seconds()

返回持续时间中包含的总秒数。相当于

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

在启用真除法的情况下进行计算。

请注意,对于非常长的时间间隔(在大多数平台上大于270年),此方法将失去微秒的精度。

此功能是2.7版中的新增功能。


1
计算存在一个小问题,它必须是10 6而不是10 * 6 ... td.microseconds +(td.seconds + td.days * 24 * 3600)* 10 6)/ 10 ** 6
sdu

@sdu非常好-我的答案中有两个星号,但是stackoverflow占用了它,试图纠正仅使文本变粗。
迈克尔

2

要将代表UTC时间的datetime对象转换为POSIX时间戳

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

要将代表本地时区中时间的datetime对象转换为POSIX时间戳,请执行以下操作:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

请参阅如何在Python中将本地时间转换为UTC?如果tz数据库在给定平台上可用;仅有stdlib的解决方案可能有效

如果您需要<3.3Python版本的解决方案,请点击链接。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.