使用strftime将python datetime转换为纪元


209

我在UTC有一个时间,我想要从纪元开始经过的秒数。

我正在使用strftime将其转换为秒数。以2012年4月1日为例。

>>>datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

从纪元开始的UTC时间为2012年4月1日,但以上返回1333234800,相差1小时。

因此,看来strftime正在考虑我的系统时间,并在某处应用了时区偏移。我以为日期时间纯粹是天真的?

我该如何解决?如果可能,除非标准,否则避免导入其他库。(我有可移植性问题)。



11
我是唯一注意到您在数字中使用八进制文字的人吗?
Fish Monitor


3
较新的Python 3.3+具有datetime.datetime.timestamp(datetime.datetime.utcnow())
MarkHu '18

Answers:


389

如果要将python日期时间转换为自纪元以来的秒数,则可以明确地执行以下操作:

>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

在Python 3.3+中,您可以timestamp()改用:

>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

为什么不应该使用 datetime.strftime('%s')

Python实际上并不支持%s作为strftime的参数(如果您不在http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior中查看,则不在列表中),唯一之所以起作用,是因为Python会将信息传递到使用本地时区的系统的strftime中。

>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

7
我一直在疯狂地试图弄清为什么我经常看到strftime(“%s”),但是它不在文档中。谢谢你!
乔纳森·瓦纳斯科

54
不要使用.strftime("%s"):不支持它,它不是可移植的,它可能会为已知的datetime对象默默地产生错误的结果,如果输入使用UTC(如在问题中),但是失败,但是本地时区不是UTC,它将失败
jfs

2
@earthmeLon您的括号是错误的。Timedelta(通过减去两个日期时间得出)具有total_seconds,但datetimes没有。
jleahy

2
这对我不起作用:AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
Michael

3
@Michael该函数是python 2.7中的新功能,您必须使用旧版本。对于2.7之前的版本,您可以执行td.seconds + td.days*24*3600。这将丢弃微秒部分。
jleahy 2014年

100

我在时区等方面遇到了严重问题。Python处理所有事情的方式(对我而言)非常令人困惑。事情似乎使用日历模块(参见链接被精细工作1234)。

>>> import datetime
>>> import calendar
>>> aprilFirst=datetime.datetime(2012, 04, 01, 0, 0)
>>> calendar.timegm(aprilFirst.timetuple())
1333238400

7
+1,因为它是唯一适用于问题输入的答案。
jfs

这是便携式的吗?
benjaminz

1
这应该标记为正确答案,因为这可以回答所关注的问题。vnice kudos
Leo Prince

2
这是“有效的”,但请注意以下问题:“我有UTC时间”此方法将始终使用系统的本地时区。无法指定时区。如果aprilFirst在此示例中是“感知”实例,并且使用的时区与系统的时区不同,则结果将不正确(时区在timetuple()呼叫中丢失)。为了获得正确的日期时间答案,您可以awaredt.timestamp()在最近的Python 3上使用。一种方法是使用arrow库。arrow.get(awaredt).timestamp会正确的。
亚当·威廉姆森

1
很好,@ AdamWilliamson,但是示例中的代码未对datetime对象进行本地化,因此我假设“我有时间在UTC中”意味着OP具有一个不知道的datetime对象,该对象被认为是他想要的UTC中的对象得到一个epoch(如果datetime碰巧是TZ感知的,那的确可能会改变事情)。另外,请记住,这个答案已有8年历史了,自从arrow发布(例如,2013年发布)以来,发生了很多事情
BorrajaX

35
import time
from datetime import datetime
now = datetime.now()

time.mktime(now.timetuple())

1
这是一种错误的写入方式time.time()mktime()在DST转换过程中可能会time.time()继续工作而失败)。除非本地时区是UTC(问题的输入是UTC),否则它不会回答问题。即使输入代表本地时间mktime(),如果不使用tz数据库,并且本地时区在过去几年中的UTC偏移量也不同,例如欧洲/莫斯科在2010-2015年间,则过去/将来的日期也可能会失败- -使用UTC时间(如在问题中所示)或时区感知的datetime对象。
jfs

我这里还有更多的问题与本地时间(例如,通过返回转换.now())至历元时间戳记(由返回mktime()。如果您阅读了;您了解为什么(在问题中使用的)UTC输入比表示本地时间的朴素的datetime对象更(更)优选
jfs 2015年

14
import time
from datetime import datetime
now = datetime.now()

# same as above except keeps microseconds
time.mktime(now.timetuple()) + now.microsecond * 1e-6

(对不起,它不会让我对现有答案发表评论)


那是因为time.mktime没有考虑微秒部分,对吗?
爱德华多

1
正确。时间元组结构(基于C strut)没有微秒的空间,因此我们需要从datetime对象获取信息并将其添加到末尾。
Charles Plager 2014年


在我的机器上,即使我的时区是ET,也可以正常工作。
查尔斯·普拉格

1
这将根据系统的本地时间为不同的系统提供不同的时间戳。
Yousaf

6

如果您只需要使用unix / epoch时间的时间戳,则此行可以工作:

created_timestamp = int((datetime.datetime.now() - datetime.datetime(1970,1,1)).total_seconds())
>>> created_timestamp
1522942073L

并且仅取决于datetime python2和python3中的作品


2

这适用于Python 2和3:

>>> import time
>>> import calendar
>>> calendar.timegm(time.gmtime())
1504917998

仅遵循官方文档... https://docs.python.org/2/library/time.html#module-time


1)假设您要立即转换,而不是随机的datetime对象。2)您不需要日历。time.mktime(randomDateTime.timetuple())+ randomDateTime.microsecond * 1e-6
Charles Plager

@CharlesPlager time.mktime不正确;它在本地时区解释参数,而OP希望以UTC解释时间(就像calendar.timegm一样)。
stewbasic

如果您希望将时间转换为格林尼治标准时间,并且希望在转换为纪元时间戳时保持这种方式,这对我来说是最准确的答案。
Yousaf

紧跟您的答案,calendar.timegm(datetime.strptime(“ 2019-05-03T05:40:09.770494 + 00:00” [:16],'%Y-%m-%dT%H:%M')。 timetuple())我在utc中有时间戳记,无论您在哪个系统上运行都可以给我正确的时间戳记,技巧是使用strptime.timetumple
Yousaf

2

对于明确的时区独立解决方案,请使用pytz库。

import datetime
import pytz

pytz.utc.localize(datetime.datetime(2012,4,1,0,0), is_dst=False).timestamp()

输出(浮动):1333238400.0


stackoverflow.com/a/21145908/4355695上看到了类似的答案,但是作为单行代码,这对于我的用例非常有用,因为传入的数据在UTC中,而只是.timestamp()假定它在本地时间中。
Nikhil VJ

这确实适用于小于1970年的日期。谢谢。接受的答案不适用于小于1970年的日期。(Python 3.7.3 64位Anaconda3)
canbax

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.