在Python中使用高精度时间戳

6

嘿,我正在使用Python和datetime工作,我想知道解析这个时间戳的最佳方法。

时间戳是ISO标准的,这里有一个例子:"2010-06-19T08:17:14.078685237Z"

到目前为止,我已经使用了

time = datetime.datetime.strptime(timestamp.split(".")[0], "%Y-%m-%dT%H:%M:%S")
precisetime = time + datetime.timedelta(0,float("." + timestamp[:-1].split(".")[0]))

这种方法是可行的,但我觉得应该有更简单的方法(我很新手,对Python不是很熟悉)。而且,我的时间戳中有纳秒,但我的日期时间对象中只有微秒,是否有更好的模块可用?我需要能够执行操作,例如减去时间并将其放入调度程序中。
有没有更好的解决方法?

1
抱歉我发了一个无用的评论,但是“我很新手Python,我肯定做得很糟糕” -> 您,先生,让我大声笑了。我们都曾经历过这个阶段。 - salezica
我仍然写“烂代码”。 - tMC
5个回答

8

1
现在似乎引发了“DeprecationWarning”。 - Newskooler
从[文档](https://numpy.org/devdocs/reference/arrays.datetime.html)中:“自版本1.11.0起已弃用:NumPy不存储时区信息。”另外,从[源代码](https://github.com/numpy/numpy/blob/0e9b464df4720028ef8739bf75ce5a44137a0bb7/numpy/core/tests/test_deprecations.py#L240-L246)中:“在我们删除它之前需要很长一段时间,因为至少有很多现有的代码使用'Z'修饰符...”但是您应该只删除Z并使用np.datetime64(“2010-06-19T08:17:14.078685237”) - oittaa

6

datetime 只精确到微秒级别,即 10e-6

因此

14.078685237

将被截断为

14.078685

如果您想要做上面的操作。

最好只是将次秒单独保持在一个 float 中,并进行一些浮点模数运算以跟踪它们。

我发现 datetime 不这样做很荒谬。

对于那些认为时钟不够准确的人来说,这并不是唯一的用例。当您需要在时间和距离之间进行转换时(乘以光速)。 1微秒等于300米。 300米是3个足球场的长度。这对于精度来说完全是胡说八道。


2

你的方法本质上没有问题,但是你可以尝试使用pyiso8601或者dateutil


2
pyiso8601dateutil都返回仅具有微秒精度的datetime对象。 OP需要纳秒精度,例如由numpy.datetime64提供的精度。 - jfs

1

你的代码看起来很好。我不知道有更好的方法,但我不是一个datetime专家。个人而言,我会将其封装在一个函数中,并且每行做更少的工作,但这只是我的风格:

def parse_iso_timestamp(timestamp)
    ts, partial_seconds = timestamp[:-1].split('.')
    partial_seconds = float("." + partial_seconds)
    time = datetime.datetime.strptime(ts, "%Y-%m-%dT%H:%M:%S")
    precisedatetime = time + datetime.timedelta(seconds=partial_seconds)
    return precisedatetime

编辑:我同意Rob Cowie的答案。没有必要重新发明轮子。


2
顺便提一下:在Python中,尽可能地在一行中完成尽量多的工作已成为一种潮流。我不确定我是否喜欢这种方式。我更倾向于使用变量名来记录较小的代码块。 - Steven Rumbalski

0

这里有一种使用正则表达式的替代方法,你可能会觉得更加简洁(或者不会):

import re

timestamp = "2010-06-19T08:17:14.078685237Z"
ts_regex = re.compile(r"(\d{4})-(\d{1,2})-(\d{1,2})T(\d{2}):(\d{2}):(\d{2})\.(\d{6})")
precisetime = datetime.datetime(*map(int, ts_regex.match(timestamp).groups()))

这里将其分为几个步骤,以提供更清晰的解释:
>>> ts_regex.match(timestamp).groups()
('2010', '06', '19', '08', '17', '14', '078685')
>>> map(int, ts_regex.match(timestamp).groups())
[2010, 6, 19, 8, 17, 14, 78685]

我们可以使用参数扩展符*将此列表直接传递到datetime对象的初始化中,因为参数顺序正确。

1
不需要使用那么复杂的正则表达式。以下内容可以帮你得到你所需要的结果:re.findall('\d+', timestamp)。通过这个你可以缩减到一行代码:precisetime = datetime.datetime(*map(int, re.findall('\d+', timestamp)),比之前的代码还要短。 ;) - Steven Rumbalski
这种情况下,一行代码将无法运作,因为它会匹配小数点后的9个字符并试图将其放入“微秒”中。如果您确定正在处理有效的时间戳,则可以使用Steven方法的变体来节省一些代码。 - Andrew Clark

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