[英]Convenient time string parsing in python
我需要計算從特定日期到現在的持續時間,以進行Elasticsearch索引清除。 我的工作將在python中運行。 我有一個配置文件:
indices:
- name: test
template: raw*
liveLength: 1d
如何將字符串“ 1d”或“ 2m”解析為有效時間間隔,以便從liveLength字段計算從特定日期開始的持續時間?
我在GitHub上找到了代碼:
from decimal import Decimal
from datetime import timedelta
def duration(duration_string): #example: '5d3h2m1s'
duration_string = duration_string.lower()
total_seconds = Decimal('0')
prev_num = []
for character in duration_string:
if character.isalpha():
if prev_num:
num = Decimal(''.join(prev_num))
if character == 'd':
total_seconds += num * 60 * 60 * 24
elif character == 'h':
total_seconds += num * 60 * 60
elif character == 'm':
total_seconds += num * 60
elif character == 's':
total_seconds += num
prev_num = []
elif character.isnumeric() or character == '.':
prev_num.append(character)
return timedelta(seconds=float(total_seconds))
很好的例子
您可以使用正則表達式提取數字/時間單位的部分,然后在字典中查找乘數。 這樣一來,這是一個有點短,可能是一大堆比更可讀的手動檢查和if/elif
鏈。
>>> mult = {"s": 1, "m": 60, "h": 60*60, "d": 60*60*24}
>>> s = "2d 4h 13m 5.2s"
>>> re.findall(r"(\d+(?:\.\d)?)([smhd])", s)
[('2', 'd'), ('4', 'h'), ('3', 'm'), ('5.2', 's')]
>>> sum(float(x) * mult[m] for x, m in _)
187385.2
作為功能:
def duration(string):
mult = {"s": 1, "m": 60, "h": 60*60, "d": 60*60*24}
parts = re.findall(r"(\d+(?:\.\d)?)([smhd])", string)
total_seconds = sum(float(x) * mult[m] for x, m in parts)
return timedelta(seconds=total_seconds)
print(duration("2d 4h 13m 5.2s"))
# 2 days, 4:03:05.200000
這還將確保數字部分實際上是有效數字(而不僅僅是數字和點的任何序列)。 此外,如果使用了非允許的時間單位,則會引發異常。
通過使用函數外部的re.compile
預編譯正則表達式,可以進一步優化該函數。 當我使用IPython的%timeit
測試它時,我的顯示速度要快一些(對於您來說,是2.1µs對2.8µs,既沒有創建timedelta
,也只有float
而不是Decimal
)。 另外,我認為這具有更聲明性和更少命令性的風格,因此更具可讀性,但這當然是口味和喜好問題。
這是我的解決方案; 我使用了python datetime
庫,它是timedelta
:
import datetime
intervals = {
"w": datetime.timedelta(weeks=1),
"d": datetime.timedelta(days=1),
"h": datetime.timedelta(hours=1),
"m": datetime.timedelta(minutes=1),
"s": datetime.timedelta(seconds=1)
}
def parse_live_length(string):
time_interval_start_index = 0
for char in string:
if char.isnumeric():
time_interval_start_index += 1
else:
return int(string[0:time_interval_start_index]), string[time_interval_start_index:]
return False
# "2w" used as an example
live_length = "2w"
time_scalar, ll_interval = parse_live_length(live_length)
for interval in intervals:
if interval == ll_interval:
new_delta = time_scalar * intervals[interval]
break
# Example of how it could be used
current = datetime.datetime.now()
new_time = new_delta + current
print(new_time.day, new_time.month, new_time.year)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.