首页 > 解决方案 > 无法使用 datetime 创建具有空天槽的计时器

问题描述

我有一个程序应该保持做某事所花费的总时间。我存储了一个值,即从“000d 00h 00m 00s”开始,持续 0 天、小时、分钟和秒。但是,如果我尝试为其添加时间,我会收到“ValueError: time data '000d 00h 00m 00s' does not match format '%jd %Hh %Mm %Ss'”。

如果我将起始字符串更改为 '001d 00h 00m 00s' 它将添加时间没问题,但我将得到一个比准确值大 24 小时的值。如果我只是删除日计数器并将其设置为“00h 00m 00s”,它也会起作用,但是一旦达到 24,它仍然会重置小时。

能够从“000d 00h 00m 00s”开始会更好,但如果这不可能,那么让小时溢出(即“25h 00m 00s”)会起作用。

from datetime import *

EmptyTime = '000d 00h 00m 00s'
EmptyTimeThatWorks = '001d 00h 00m 00s'
ExampleTime = '174d 19h 07m 53s' # June 23 7:07 PM
FMT = "%jd %Hh %Mm %Ss"

def TaskEnded(RunningTotal, TimerStartTime):
    PresentTime = datetime.now().strftime(FMT) #PresnetTime is when the TaskEnded

    st = datetime.strptime(TimerStartTime, FMT)  #Brings things into the right format 
    pt = datetime.strptime(PresentTime, FMT)  #Brings things into the right format
    rt = datetime.strptime(RunningTotal, FMT)  #Brings things into the right format, but EmptyTime cant be
                                               # conveted to the right time because day '0' doenst exist
                                               # while hour, minute, and second 0 do

    NewTotal = rt + (pt - st)      #takes the running total and adds the timer value, which is the difference of start and end times
    NewTotal2 = datetime.strftime(NewTotal, FMT)  # Puts the Datetime value back into the right format FMT
    print(NewTotal2)
    return NewTotal2

TaskEnded(EmptyTimeThatWorks, ExampleTime)
TaskEnded(EmptyTime, ExampleTime)

标签: pythondatetimetime

解决方案


这就是我将经过的时间保存在 a 中timedelta并编写遵循 PEP 8 准则的代码的意思:

from datetime import *


def task_ended(running_total, timer_start_time, fmt="%B %d, %Y %I:%M %p"):
    """ Add time elapsed between timer_start_time and now to
        running_total timedelta and return it.
    """
    present_time = datetime.now()   # When task ended.
    # Convert timer_start_time string into a datetime using fmt string.
    start_time = datetime.strptime(timer_start_time, fmt)
    # Add time elapsed between present time and timer start time to running
    # total and return it.
    return running_total + (present_time - start_time)

def format_timedelta(td):
    """ Format timedelta into custom string representation. """
    days = td.days
    hours, remainder = divmod(td.seconds, 3600)
    mins, secs = divmod(remainder, 60)
    return '{:03}d {:02}h {:02}m {:02}s'.format(days, hours, mins, secs)


running_total = timedelta()
example_start_time = 'June 25, 2019 5:00 PM'
running_total = task_ended(running_total, example_start_time)
print('running total:', format_timedelta(running_total))
print()
running_total = timedelta()
example_start_time = 'June 23, 2019 7:07 PM'
running_total = task_ended(running_total, example_start_time)
print('running total:', format_timedelta(running_total))

这是一种将运行中的总字符串解析为 a 的方法timedelta(基于对问题如何timedelta从简单字符串构造对象的几个答案):

import re

regex = re.compile(r'^((?P<days>[\d]+?)d)? *'
                   r'((?P<hours>[\d]+?)h)? *'
                   r'((?P<minutes>[\d]+?)m)? *'
                   r'((?P<seconds>[\d]+?)s)?$')

def parse_timedelta(time_str):
    """
    Parse a time string e.g. (2h 13m) into a timedelta object.

    Modified from virhilo & Peter's answers at https://stackoverflow.com/a/4628148/355230

    :param time_str: A string identifying a duration.  (eg. 2h 13m)
    :return datetime.timedelta: A datetime.timedelta object
    """
    parts = regex.match(time_str)
    assert parts is not None, "Could not parse any time information from '{}'".format(time_str)
    time_params = {name: float(param) for name, param in parts.groupdict().items() if param}
    return timedelta(**time_params)


# Test string parser function.
test_str = '000d 21h 40m 53s'
td = parse_timedelta(test_str)
assert format_timedelta(td) == test_str

test_str = '002d 19h 33m 53s'
td = parse_timedelta(test_str)
assert format_timedelta(td) == test_str

推荐阅读