Convert string that was originally a `timedelta` back into a `timedelta` object in Python

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

Convert string that was originally a `timedelta` back into a `timedelta` object in Python

问题

我有一些最初是从timedelta对象生成的字符串,像这样:print(f'{my_delta}')

我有许多这些语句被记录下来(例如,“12:21:00”,“1 day, 0:53:00”,“2 days, 9:28:00”),我只是想解析这些记录下来的语句,将它们转换回timedelta对象。是否可以使用datetime库实现这个目标?

这些字符串实际上是从打印timedelta对象生成的,但我似乎无法通过timedelta(my_string)来转换回去。想知道是否有一种标准的方法可以做到这一点,我是否遗漏了什么。

英文:

I have strings which were originally produced from timedelta objects like so: print(f'{my_delta}').

I have many of these statements logged (e.g. "12:21:00", "1 day, 0:53:00", "2 days, 9:28:00") and I simply want to parse these logged statements to convert back to timedelta objects. Is this possible with the datetime library?

The strings were literally produced from just printing timedelta objects, but I cannot seem to convert back by using timedelta(my_string). Wondering if there is a standard way of doing this that I am missing.

答案1

得分: 0

以下是您提供的代码的翻译部分:

这部分应该适用于正则表达式因为它似乎非常规律它可能在开头指定天数或者在结尾指定微秒但它非常... 规律

import re

pattern = r'''
    ((?P<days>-?\d{1,})\ days?,\ )?  # maybe there will be day(s)
    (?P<hours>\d{1,2})  # hours will be one or 2 digits
    :(?P<minutes>\d{2})  # separated by a colon, minutes will be 2 digits
    :(?P<seconds>\d{2})  # separated by a colon, seconds will be 2 digits
    (\.(?P<microseconds>\d{6}))?  # maybe, separated by a period, microseconds will be 6 digits
'''

parse_timedelta_regex = re.compile(pattern, flags=re.VERBOSE)

请注意,使用re.VERBOSE标志时要注意空格,除非您对它们进行转义,否则在特定情况之外,它们会被忽略。但我认为这样更可读。

以下是如何使用它的示例:

>> parse_timedelta_regex.search("1000 days, 0:00:00").groupdict()
{'days': '1000', 'hours': '0', 'minutes': '00', 'seconds': '00', 'microseconds': None}
>>> parse_timedelta_regex.search("1 day, 11:00:13.000130").groupdict()
{'days': '1', 'hours': '11', 'minutes': '00', 'seconds': '13', 'microseconds': '000130'}

您还可以编写将字符串转换为时间间隔对象的函数,如下所示:

>>> def string_to_timedelta(s):
...     groups = parse_timedelta_regex.search(s).groupdict()
...     args = {k:int(v) for k,v in groups.items() if v}
...     return datetime.timedelta(**args)
...
>>> string_to_timedelta(str(datetime.timedelta(seconds=1337)))
datetime.timedelta(seconds=1337)

以下是一个更严格的测试(仍然不是非常严格):

>>> def test_parse(n):
...     for _ in range(n):
...         seconds = random.random()*100_000_000
...         td = datetime.timedelta(seconds=seconds)
...         parsed = string_to_timedelta(str(td))
...         assert td == parsed
...
>>> test_parse(1000)
>>> test_parse(10_000)
>>> test_parse(100_000)

希望这有助于您理解代码的翻译。如果您需要进一步的帮助,请随时提出。

英文:

This should be amenable to regex, since it seems very regular. It may have days specified at the beginning, or microseconds at the end. But its very... regular:

import re

pattern = r&#39;&#39;&#39;
    ((?P&lt;days&gt;-?\d{1,})\ days?,\ )?  # maybe there will be day(s)
    (?P&lt;hours&gt;\d{1,2})  # hours will be one or 2 digits
    :(?P&lt;minutes&gt;\d{2})  # separated by a colon, minutes will be 2 digits
    :(?P&lt;seconds&gt;\d{2})  # separated by a colon, seconds will be 2 digits
    (\.(?P&lt;microseconds&gt;\d{6}))?  # maybe, separated by a period, microseconds will be 6 digits
&#39;&#39;&#39;

parse_timedelta_regex = re.compile(pattern, flags=re.VERBOSE)

Note, take care using the re.VERBOSE flag with spaces, they are ignored outside of specific cases unless you escape them. But I do think it is more readable this way.

Examples of how to use this:

&gt;&gt; parse_timedelta_regex.search(&quot;1000 days, 0:00:00&quot;).groupdict()
{&#39;days&#39;: &#39;1000&#39;, &#39;hours&#39;: &#39;0&#39;, &#39;minutes&#39;: &#39;00&#39;, &#39;seconds&#39;: &#39;00&#39;, &#39;microseconds&#39;: None}
&gt;&gt;&gt; parse_timedelta_regex.search(&quot;1 day, 11:00:13.000130&quot;).groupdict()
{&#39;days&#39;: &#39;1&#39;, &#39;hours&#39;: &#39;11&#39;, &#39;minutes&#39;: &#39;00&#39;, &#39;seconds&#39;: &#39;13&#39;, &#39;microseconds&#39;: &#39;000130&#39;}

You could also just write the function to convert the string to timedelta object like so:

&gt;&gt;&gt; def string_to_timedelta(s):
...     groups = parse_timedelta_regex.search(s).groupdict()
...     args = {k:int(v) for k,v in groups.items() if v}
...     return datetime.timedelta(**args)
...
&gt;&gt;&gt; string_to_timedelta(str(datetime.timedelta(seconds=1337)))
datetime.timedelta(seconds=1337)

Here's a more rigorous test (still not very rigorous):

&gt;&gt; def test_parse(n):
...     for _ in range(n):
...         seconds = random.random()*100_000_000
...         td = datetime.timedelta(seconds=seconds)
...         parsed = string_to_timedelta(str(td))
...         assert td == parsed
...
&gt;&gt;&gt; test_parse(1000)
&gt;&gt;&gt; test_parse(10_000)
&gt;&gt;&gt; test_parse(100_000)

答案2

得分: 0

其他人已经强调过,`datetime`库似乎不支持这个功能

以下是使用正则表达式的一行代码

```python
&gt;&gt;&gt; from datetime import timedelta
&gt;&gt;&gt; import re
&gt;&gt;&gt; 
&gt;&gt;&gt; str_to_dlt = lambda t: timedelta(days=int((m:=re.match(r'((\d+)\sdays?,\s*)?(\d{1,2}):(\d{2}):(\d{2})', t))[2] or 0), hours=int(m[3]), minutes=int(m[4]), seconds=int(m[5]))

打印timedelta会返回它接收到的原始字符串:

&gt;&gt;&gt; print(str_to_dlt('5:11:13'))
5:11:13
&gt;&gt;&gt; 
&gt;&gt;&gt; print(str_to_dlt('1 day, 5:11:13'))
1 day, 5:11:13
&gt;&gt;&gt; 
&gt;&gt;&gt; print(str_to_dlt('2 days, 5:11:13'))
2 days, 5:11:13
英文:

As others have noted emphatically, the datetime library does not seem to support this functionality.

Here's a one-liner that uses regex:

&gt;&gt;&gt; from datetime import timedelta
&gt;&gt;&gt; import re
&gt;&gt;&gt; 
&gt;&gt;&gt; str_to_dlt = lambda t: timedelta(days=int((m:=re.match(r&#39;((\d+)\sdays?,\s*)?(\d{1,2}):(\d{2}):(\d{2})&#39;, t))[2] or 0), hours=int(m[3]), minutes=int(m[4]), seconds=int(m[5]))

Printing the timedelta returns the original string it was supplied:

&gt;&gt;&gt; print(str_to_dlt(&#39;5:11:13&#39;))
5:11:13
&gt;&gt;&gt; 
&gt;&gt;&gt; print(str_to_dlt(&#39;1 day, 5:11:13&#39;))
1 day, 5:11:13
&gt;&gt;&gt; 
&gt;&gt;&gt; print(str_to_dlt(&#39;2 days, 5:11:13&#39;))
2 days, 5:11:13

huangapple
  • 本文由 发表于 2023年5月18日 03:17:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76275525.html
匿名

发表评论

匿名网友

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

确定