将ISO 8601日期时间转换为Python中的秒数

33

我想将两个时间相加。 ISO 8601时间戳为'1984-06-02T19:05:00.000Z',我想将其转换为秒。 我尝试使用Python模块iso8601,但它只是一个解析器。

有什么建议吗?


1
什么秒数?自纪元以来的秒数? - Robby Cornelissen
我想是的。这是我第一次处理日期。 - Zaynaib Giwa
3个回答

37
如果您想获取自纪元以来的秒数,可以使用 python-dateutil 将其转换为 datetime 对象,然后使用 strftime 方法将其转换为秒。代码如下:
>>> import dateutil.parser as dp
>>> t = '1984-06-02T19:05:00.000Z'
>>> parsed_t = dp.parse(t)
>>> t_in_seconds = parsed_t.timestamp()
>>> t_in_seconds
'455051100'

所以你已经完成了一半的工作 :)

1
看看这个链接:https://docs.python.org/2/library/datetime.html。`datetime.isoformat()`应该是你要找的。所以你需要先使用`strptime`将字符串转换回`datetime`对象,然后在该对象上调用`isoformat`。 - chunpoon
2
parsed_t.strftime('%s') 是错误的。parsed_t.tzinfo == tzutc(),但是.strftime('%s')即使可用本地时区,它仍然会使用本地时区(在您的情况下可能会有所不同)。正确答案是 455051100,而不是 455047500(请检查 datetime.utcfromtimestamp(455051100))。 - jfs
如此简单、优雅的解决方案! - Blairg23
3
从Python 3.3版本开始,你可以使用parsed_t.timestamp()来获取正确的时间。 - user1609012
1
警告:如果 parsed_t 不是时区感知的话,那么 timestamp() 可能会产生错误的结果。它将天然日期时间解释为本地时间,可能与所需的时区(如 UTC)不同。 - jfs
显示剩余5条评论

28

你的日期是使用RFC 3339格式的协调世界时(UTC)时间,您可以仅使用标准库来解析它:

from datetime import datetime

utc_dt = datetime.strptime('1984-06-02T19:05:00.000Z', '%Y-%m-%dT%H:%M:%S.%fZ')

# Convert UTC datetime to seconds since the Epoch
timestamp = (utc_dt - datetime(1970, 1, 1)).total_seconds()
# -> 455051100.0

参见在Python中将datetime.date转换为UTC时间戳

如何将其转换回ISO 8601格式?

要将POSIX时间戳转换回ISO 8601格式,请从中创建一个UTC datetime对象,并使用.strftime()方法进行格式化:

from datetime import datetime, timedelta

utc_dt = datetime(1970, 1, 1) + timedelta(seconds=timestamp)
print(utc_dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ'))
# -> 1984-06-02T19:05:00.000000Z

注意:它会打印小数点后六位数字(微秒)。要获得三位数字,请参见将微秒格式化为2位小数(实际上是将微秒转换为十分之一微秒)


你是否知道如何将其转换回ISO 8601格式?到目前为止,另一个时间是datetime.datetime.fromtimestamp(时间戳).isoformat(),但它会格式化为.000Z。有什么建议吗?我尝试了多种方法,但都出现错误。 - Zaynaib Giwa
@user3426338:我已经更新了答案,展示了如何将时间戳(数字)转换回ISO 8601格式的字符串。 - jfs
1
这只解析 Z 后缀,不处理 ±hh:mm 时区。 %f 令人恼火地拒绝解析超过6个小数位(在 ISO 8601 和 RFC 3339 中都很少见但合法),例如由 date --iso-8601=ns 打印的格式。 - Beni Cherniavsky-Paskin
@BeniCherniavsky-Paskin 是的,它是正确的(此外,在Python 3中,%z只能理解hhmm的UTC偏移量 - 没有冒号 :)。即使是rfc 3339(rfc 8601的一个配置文件),也没有办法仅使用标准库进行解析(请参见我上面提到的问题)。虽然有时候,在问题的示例中,解析Z就足够了。 - jfs

0

这是Python 3的解决方案:

$ date +%s
1428030452
$ TZ=US/Pacific date -d @1428030452 '+%Y%m%d %H:%M:%S %z'
20150402 20:07:32 -0700
$ TZ=US/Eastern date -d @1428030452 '+%Y%m%d %H:%M:%S %z'
20150402 23:07:32 -0400
$ python3
>>> from datetime import datetime,timezone
>>> def iso2epoch(ts):
...     return int(datetime.strptime(ts[:-6],"%Y%m%d %H:%M:%S").replace(tzinfo=timezone.utc).timestamp()) - (int(ts[-2:])*60 + 60 * 60 * int(ts[-4:-2]) * int(ts[-5:-4]+'1'))
...
>>> iso2epoch("20150402 20:07:32 -0700")
1428030452
>>> iso2epoch("20150402 23:07:32 -0400")
1428030452
>>>

1
令人印象深刻的短小纯stdlib时区感知解析!但遗憾的是,它不是ISO 8601格式(请参见问题中的示例或运行date --iso-8601=ns)。ISO标准允许大量格式,因此strptime无法胜任,但仅解析±hh:mmZ时区格式(RFC3339子集)在许多情况下已经足够好了。 - Beni Cherniavsky-Paskin
似乎过于复杂:(int(ts[-2:])*60 + 60 * 60 * int(ts[-4:-2]) * int(ts[-5:-4]+'1') - Ian Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接