将具有9位数字的字符串日期时间转换为Python中的ISO格式日期时间对象。

huangapple go评论75阅读模式
英文:

Convert string datetime with 9 digits in last to ISO format datetime object in python

问题

我有一个字符串日期时间(例如:"2022-11-11T06:19:32.776289776Z")。我想将其转换为ISO格式。

我尝试了下面的方法:

datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289776Z")

但它会报错。
ValueError: Invalid isoformat string: '2022-11-11T06:19:32.776289776Z'

如果我只在最后提供6位数字而没有Z,它可以正常工作。

以下示例对我有效,但对于以9位数字和Z结尾的字符串则无效:

datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289")

datetime.datetime(2022, 11, 11, 6, 19, 32, 776289)
英文:

I have string datetime (eg: "2022-11-11T06:19:32.776289776Z"). I want to convert the same in ISO format.

I tried below

>>> datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289776Z")

But it is throwing error.
>ValueError: Invalid isoformat string: '2022-11-11T06:19:32.776289776Z

It is working if I give only 6 digits in the last without Z.

Below example is working for me, however not working for the strings with 9 digits and z in the end:

>>> datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289")

datetime.datetime(2022, 11, 11, 6, 19, 32, 776289)

答案1

得分: 3

如果 Python 3.11 可用

如果您可以升级到 Python 3.11,则可以使用 fromisoformat 处理这个问题:

# 仅适用于 Python 3.11 及以上版本
dt = datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289776Z")
print(dt)

将输出:

2022-11-11 06:19:32.776289+00:00

Python 的早期版本

如果您受限于较早版本的 Python,那么可以按照评论中 @SalmanA 的建议,通过以下步骤获得有效的时间戳:(1) 使用 re.sub 将微秒部分截断为 6 位数字,(2) 将 Z 替换为 +00:00(可以使用 str.replace 完成)。

这假定时间戳在其他方面是有效格式的(例如,字符串中没有字母 Z)。

例如:

import datetime
import re

def clean_str(ts):
    return re.sub("(\d{6})(\d+)", r"", ts).replace("Z", "+00:00")

tests = ["2022-11-11T06:19:32.776289776Z",
         "2022-11-11T06:19:32.776289Z",
         "2022-11-11T06:19:32.7762897+03:00",
         "2022-11-11T06:19:32.776Z"]

for i, ts in enumerate(tests, 1):
    clean = clean_str(ts)
    dt = datetime.datetime.fromisoformat(clean)
    print(f"({i}): {ts} -> {clean} -> {dt}")

将输出:

(1): 2022-11-11T06:19:32.776289776Z -> 2022-11-11T06:19:32.776289+00:00 -> 2022-11-11 06:19:32.776289+00:00
(2): 2022-11-11T06:19:32.776289Z -> 2022-11-11T06:19:32.776289+00:00 -> 2022-11-11 06:19:32.776289+00:00
(3): 2022-11-11T06:19:32.7762897+03:00 -> 2022-11-11T06:19:32.776289+03:00 -> 2022-11-11 06:19:32.776289+03:00
(4): 2022-11-11T06:19:32.776Z -> 2022-11-11T06:19:32.776+00:00 -> 2022-11-11 06:19:32.776000+00:00

请注意,正如示例(1)和(3)所示,微秒部分被截断,而不是四舍五入,即 32.776289776 变为 32.776289 而不是 32.776290。(对于原生 Python 3.11 解决方案也是如此。)如果您想要真正的四舍五入,则需要进一步解析字符串。

英文:

If Python 3.11 is available

If you can upgrade to Python 3.11, then fromisoformat can handle this:

# Python 3.11 and above only
dt = datetime.datetime.fromisoformat("2022-11-11T06:19:32.776289776Z")
print(dt)

giving

2022-11-11 06:19:32.776289+00:00

Earlier versions of Python

If you're restricted to earlier versions of Python, then as @SalmanA said in the comments, you can get to a valid timestamp by (1) trimming the microseconds down to 6 digits, using re.sub, and (2) replacing Z with +00:00 (str.replace will do that).

This assumes the timestamp is otherwise validly formatted (e.g. no letter Z anywhere else in the string).

For example:

import datetime
import re

def clean_str(ts):
    return re.sub("(\d{6})(\d+)", r"", ts).replace("Z", "+00:00")

tests = ["2022-11-11T06:19:32.776289776Z",
         "2022-11-11T06:19:32.776289Z",
         "2022-11-11T06:19:32.7762897+03:00",
         "2022-11-11T06:19:32.776Z"]

for i, ts in enumerate(tests, 1):
    clean = clean_str(ts)
    dt = datetime.datetime.fromisoformat(clean)
    print(f"({i}): {ts} -> {clean} -> {dt}")

giving:

(1): 2022-11-11T06:19:32.776289776Z -> 2022-11-11T06:19:32.776289+00:00 -> 2022-11-11 06:19:32.776289+00:00
(2): 2022-11-11T06:19:32.776289Z -> 2022-11-11T06:19:32.776289+00:00 -> 2022-11-11 06:19:32.776289+00:00
(3): 2022-11-11T06:19:32.7762897+03:00 -> 2022-11-11T06:19:32.776289+03:00 -> 2022-11-11 06:19:32.776289+03:00
(4): 2022-11-11T06:19:32.776Z -> 2022-11-11T06:19:32.776+00:00 -> 2022-11-11 06:19:32.776000+00:00

Note that as (1) and (3) show, the microseconds are truncated, not rounded, i.e. 32.776289776 goes to 32.776289 not 32.776290. (And the same goes for the native Python 3.11 solution.) If you wanted true rounding then you would need to parse the string further.

答案2

得分: 1

你可以使用dateutil的更宽松解析器。确实,您可以安装该包python-dateutil&nbsp;<sup>[PyPi]</sup>。这将解析任意数量的数字,&hellip; datetime分辨率为微秒,这意味着它不会存储六位数后的细节,因此它将忽略其余的数字:

&gt;&gt;&gt; from dateutil import parser
&gt;&gt;&gt; parser.isoparse(&#39;2022-11-11T06:19:32.776289776Z&#39;)
datetime.datetime(2022年11月11日, 6点19分32秒, 776289微秒, tzinfo=tzutc())

因此,&hellip;776 部分被省略。

英文:

You can use a more "permissive" parser with dateutil. Indeed, you install that package python-dateutil&nbsp;<sup>[PyPi]</sup>. This will parse with an arbitrary number of digits, but&hellip; datetime has a resolution of a microsecond, this means that it will not store the details after six digits, so it will just ignore the rest of the digits:

&gt;&gt;&gt; from dateutil import parser
&gt;&gt;&gt; parser.isoparse(&#39;2022-11-11T06:19:32.776289776Z&#39;)
datetime.datetime(2022, 11, 11, 6, 19, 32, 776289, tzinfo=tzutc())

The <code>&hellip;776</code> part is thus omitted.

huangapple
  • 本文由 发表于 2023年6月22日 19:19:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76531347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定