英文:
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
<sup>[PyPi]</sup>。这将解析任意数量的数字,但… datetime
的分辨率为微秒,这意味着它不会存储六位数后的细节,因此它将忽略其余的数字:
>>> from dateutil import parser
>>> parser.isoparse('2022-11-11T06:19:32.776289776Z')
datetime.datetime(2022年11月11日, 6点19分32秒, 776289微秒, tzinfo=tzutc())
因此,…776
部分被省略。
英文:
You can use a more "permissive" parser with dateutil
. Indeed, you install that package python-dateutil
<sup>[PyPi]</sup>. This will parse with an arbitrary number of digits, but… 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:
>>> from dateutil import parser
>>> parser.isoparse('2022-11-11T06:19:32.776289776Z')
datetime.datetime(2022, 11, 11, 6, 19, 32, 776289, tzinfo=tzutc())
The <code>…776</code> part is thus omitted.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论