英文:
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'''
((?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)
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:
>> 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'}
You could also just write the function to convert the string to timedelta object like so:
>>> 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)
Here's a more rigorous test (still not very rigorous):
>> 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)
答案2
得分: 0
其他人已经强调过,`datetime`库似乎不支持这个功能。
以下是使用正则表达式的一行代码:
```python
>>> from datetime import timedelta
>>> import re
>>>
>>> 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
会返回它接收到的原始字符串:
>>> print(str_to_dlt('5:11:13'))
5:11:13
>>>
>>> print(str_to_dlt('1 day, 5:11:13'))
1 day, 5:11:13
>>>
>>> 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:
>>> from datetime import timedelta
>>> import re
>>>
>>> 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]))
Printing the timedelta returns the original string it was supplied:
>>> print(str_to_dlt('5:11:13'))
5:11:13
>>>
>>> print(str_to_dlt('1 day, 5:11:13'))
1 day, 5:11:13
>>>
>>> print(str_to_dlt('2 days, 5:11:13'))
2 days, 5:11:13
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论