方便的python时间字符串解析

时间:2019-02-27 12:09:32

标签: python parsing elasticsearch

我需要计算从特定日期到现在的持续时间,以进行Elasticsearch索引清除。 我的工作将在python中运行。 我有一个配置文件:

    <html>
      <body>
        <canvas id="test" style="width: 300px; height: 300px"></canvas>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
        <script src="https://cdn.jsdelivr.net/gh/emn178/chartjs-plugin-labels/src/chartjs-plugin-labels.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.5.0"></script>
      </body>

    </html>

如何将字符串“ 1d”或“ 2m”解析为有效时间间隔,以便从liveLength字段中计算特定日期的持续时间?

3 个答案:

答案 0 :(得分:0)

我在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))

很好example

答案 1 :(得分:0)

您可以使用正则表达式提取数字/时间单位的部分,然后在字典中查找乘数。这样,它比your手动解析和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而不是{{ 1}})。另外,我认为通过使用更多的声明式和更少的命令式样式可以更容易理解,但这肯定是口味和喜好问题。

答案 2 :(得分:0)

这是我的解决方案;我使用了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)