[英]How to construct a timedelta object from a simple string
I'm writing a function that needs to parse string to a timedelta<\/code> .
我正在编写一个需要将字符串解析为
timedelta<\/code>的函数。
The user must enter something like
"32m"<\/code> or
"2h32m"<\/code> , or even
"4:13"<\/code> or
"5hr34m56s"<\/code> ... Is there a library or something that has this sort of thing already implemented?
用户必须输入类似
"32m"<\/code>或
"2h32m"<\/code> ,甚至是
"4:13"<\/code>或
"5hr34m56s"<\/code> ... 是否有图书馆或已经实现了这类东西的东西?
"
To me the most elegant solution, without having to resort to external libraries such as dateutil or manually parsing the input, is to use datetime's powerful strptime
string parsing method.对我来说,最优雅的解决方案是使用datetime强大的
strptime
字符串解析方法,而无需求助于dateutil等外部库或手动解析输入。
from datetime import datetime, timedelta
# we specify the input and the format...
t = datetime.strptime("05:20:25","%H:%M:%S")
# ...and use datetime's hour, min and sec properties to build a timedelta
delta = timedelta(hours=t.hour, minutes=t.minute, seconds=t.second)
After this you can use your timedelta object as normally, convert it to seconds to make sure we did the correct thing etc.在此之后,您可以像往常一样使用您的 timedelta 对象,将其转换为秒以确保我们做了正确的事情等。
print(delta)
assert(5*60*60+20*60+25 == delta.total_seconds())
I had a bit of time on my hands yesterday, so I developed @virhilo<\/a> 's answer<\/a> into a Python module, adding a few more time expression formats, including all those requested by @priestc<\/a> .昨天我有一点时间,所以我将
@virhilo<\/a>的答案<\/a>开发成一个Python 模块,添加了更多时间表达式格式,包括@priestc<\/a>要求的所有格式。
Source code is on github<\/a> (MIT License) for anybody that wants it.任何想要它的人都
可以在 github(MIT 许可证)上找到源代码<\/a>。 It's also on PyPI:
它也在 PyPI 上:
pip install pytimeparse
For the first format ( 5hr34m56s<\/code> ), you should parse using regular expressions
对于第一种格式(
5hr34m56s<\/code> ),您应该使用正则表达式进行解析
Here is re-based solution:这是基于重新的解决方案:
import re
from datetime import timedelta
regex = re.compile(r'((?P<hours>\d+?)hr)?((?P<minutes>\d+?)m)?((?P<seconds>\d+?)s)?')
def parse_time(time_str):
parts = regex.match(time_str)
if not parts:
return
parts = parts.groupdict()
time_params = {}
for name, param in parts.items():
if param:
time_params[name] = int(param)
return timedelta(**time_params)
>>> from parse_time import parse_time
>>> parse_time('12hr')
datetime.timedelta(0, 43200)
>>> parse_time('12hr5m10s')
datetime.timedelta(0, 43510)
>>> parse_time('12hr10s')
datetime.timedelta(0, 43210)
>>> parse_time('10s')
datetime.timedelta(0, 10)
>>>
I wanted to input just a time and then add it to various dates so this worked for me:我只想输入一个时间,然后将其添加到不同的日期,所以这对我有用:
from datetime import datetime as dtt
time_only = dtt.strptime('15:30', "%H:%M") - dtt.strptime("00:00", "%H:%M")
I've modified virhilo's nice answer with a few upgrades:我通过一些升级修改了 virhilo 的好答案:
3m0.25s
is 3 minutes, 0.25 seconds)3m0.25s
是 3 分 0.25 秒) . .
import re
from datetime import timedelta
regex = re.compile(r'^((?P<days>[\.\d]+?)d)?((?P<hours>[\.\d]+?)h)?((?P<minutes>[\.\d]+?)m)?((?P<seconds>[\.\d]+?)s)?$')
def parse_time(time_str):
"""
Parse a time string e.g. (2h13m) into a timedelta object.
Modified from virhilo's answer at https://stackoverflow.com/a/4628148/851699
:param time_str: A string identifying a duration. (eg. 2h13m)
:return datetime.timedelta: A datetime.timedelta object
"""
parts = regex.match(time_str)
assert parts is not None, "Could not parse any time information from '{}'. Examples of valid strings: '8h', '2d8h5m20s', '2m4s'".format(time_str)
time_params = {name: float(param) for name, param in parts.groupdict().items() if param}
return timedelta(**time_params)
Django comes with the utility function parse_duration()
. Django 带有实用函数
parse_duration()
。 From the documentation :从文档中:
Parses a string and returns a
datetime.timedelta
.解析一个字符串并返回一个
datetime.timedelta
。Expects data in the format
"DD HH:MM:SS.uuuuuu"
or as specified by ISO 8601 (egP4DT1H15M20S
which is equivalent to4 1:15:20
) or PostgreSQL's day-time interval format (eg3 days 04:05:06
).期望格式为
"DD HH:MM:SS.uuuuuu"
或由 ISO 8601 指定的数据(例如P4DT1H15M20S
相当于4 1:15:20
)或 PostgreSQL 的日间间隔格式(例如3 days 04:05:06
)。
if you want to use : as separator, I use this function:如果你想使用 : 作为分隔符,我使用这个函数:
import re
from datetime import timedelta
def timedelta_parse(value):
"""
convert input string to timedelta
"""
value = re.sub(r"[^0-9:]", "", value)
if not value:
return
return timedelta(**{key:float(val)
for val, key in zip(value.split(":")[::-1],
("seconds", "minutes", "hours", "days"))
})
Use isodate library to parse ISO 8601 duration string.使用isodate库解析 ISO 8601 持续时间字符串。 For example:
例如:
isodate.parse_duration('PT1H5M26S')
Also see Is there an easy way to convert ISO 8601 duration to timedelta?另请参阅是否有一种简单的方法可以将 ISO 8601 持续时间转换为 timedelta?
If Pandas is already in your dependencies, it does this pretty well:如果 Pandas 已经在您的依赖项中,它会做得很好:
>>> import pandas as pd
>>> pd.Timedelta('5hr34m56s')
Timedelta('0 days 05:34:56')
>>> pd.Timedelta('2h32m')
Timedelta('0 days 02:32:00')
>>> pd.Timedelta('5hr34m56s')
Timedelta('0 days 05:34:56')
>>> # It is pretty forgiving:
>>> pd.Timedelta('2 days 24:30:00 10 sec')
Timedelta('3 days 00:30:10')
To convert to datetime.timedelta
if you prefer that type:如果您喜欢这种类型,要转换为
datetime.timedelta
:
>>> pd.Timedelta('1 days').to_pytimedelta()
datetime.timedelta(1)
Unfortunately this does not work though:不幸的是,这不起作用:
>>> pd.Timedelta('4:13')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pandas\_libs\tslibs\timedeltas.pyx", line 1217, in
pandas._libs.tslibs.timedeltas.Timedelta.__new__
File "pandas\_libs\tslibs\timedeltas.pyx", line 454, in
pandas._libs.tslibs.timedeltas.parse_timedelta_string
ValueError: expected hh:mm:ss format
Pandas actually has pretty extensive date and time tools even though that is not its main purpose. Pandas 实际上有相当广泛的日期和时间工具,尽管这不是它的主要用途。
To install Pandas:要安装熊猫:
# If you use pip
pip install pandas
# If you use conda
conda install pandas
If you use Python 3 then here's updated version for Hari Shankar's solution, which I used:如果您使用 Python 3,那么这里是 Hari Shankar 解决方案的更新版本,我使用的是:
from datetime import timedelta
import re
regex = re.compile(r'(?P<hours>\d+?)/'
r'(?P<minutes>\d+?)/'
r'(?P<seconds>\d+?)$')
def parse_time(time_str):
parts = regex.match(time_str)
if not parts:
return
parts = parts.groupdict()
print(parts)
time_params = {}
for name, param in parts.items():
if param:
time_params[name] = int(param)
return timedelta(**time_params)
Consider trying tempora.parse_timedelta<\/a> .考虑尝试
tempora.parse_timedelta<\/a> 。
$ pip-run 'tempora>=4.1.1'
Collecting tempora>=4.1.1
Downloading tempora-4.1.1-py3-none-any.whl (15 kB)
Collecting jaraco.functools>=1.20
Using cached jaraco.functools-3.3.0-py3-none-any.whl (6.8 kB)
Collecting pytz
Using cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Collecting more-itertools
Using cached more_itertools-8.8.0-py3-none-any.whl (48 kB)
Installing collected packages: more-itertools, pytz, jaraco.functools, tempora
Successfully installed jaraco.functools-3.3.0 more-itertools-8.8.0 pytz-2021.1 tempora-4.1.1
Python 3.9.2 (v3.9.2:1a79785e3e, Feb 19 2021, 09:06:10)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from tempora import parse_timedelta
>>> parse_timedelta("32m")
datetime.timedelta(seconds=1920)
>>> parse_timedelta("2h32m")
datetime.timedelta(seconds=9120)
>>> parse_timedelta("4:13")
datetime.timedelta(seconds=15180)
>>> parse_timedelta("5hr34m56s")
datetime.timedelta(seconds=20096)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.