[python] timedelta를 문자열로 형식화

datetime.timedelta개체를 포맷하는 데 문제가 있습니다.

여기에 내가하려는 일이 있습니다. 객체 목록이 있고 객체 클래스의 멤버 중 하나가 이벤트 기간을 나타내는 timedelta 객체입니다. 해당 지속 시간을시 : 분 형식으로 표시하고 싶습니다.

나는 이것을하기 위해 다양한 방법을 시도했지만 어려움을 겪고있다. 현재 접근 방식은 시간과 분을 반환하는 객체의 클래스에 메소드를 추가하는 것입니다. timedelta.seconds를 3600으로 나누고 반올림하여 시간을 얻을 수 있습니다. 나머지 초를 가져 와서 몇 분으로 변환하는 데 문제가 있습니다.

그건 그렇고, 나는 장고 템플릿과 함께 Google AppEngine을 사용하여 프레젠테이션하고 있습니다.



답변

시간 델타를 str ()을 사용하여 문자열로 변환 할 수 있습니다. 예를 들면 다음과 같습니다.

import datetime
start = datetime.datetime(2009,2,10,14,00)
end   = datetime.datetime(2009,2,10,16,00)
delta = end-start
print(str(delta))
# prints 2:00:00


답변

아시다시피, .seconds속성 에 액세스하여 timedelta 객체에서 total_seconds를 가져올 수 있습니다 .

파이썬은 내장 함수 divmod()를 제공합니다 .

s = 13420
hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60)
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40

또는 모듈로와 빼기를 조합하여 시간과 나머지로 변환 할 수 있습니다.

# arbitrary number of seconds
s = 13420
# hours
hours = s // 3600
# remaining seconds
s = s - (hours * 3600)
# minutes
minutes = s // 60
# remaining seconds
seconds = s - (minutes * 60)
# total time
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40


답변

>>> str(datetime.timedelta(hours=10.56))
10:33:36

>>> td = datetime.timedelta(hours=10.505) # any timedelta object
>>> ':'.join(str(td).split(':')[:2])
10:30

timedelta객체를 str()함수에 전달하면 단순히 입력하면 사용되는 것과 동일한 서식 코드가 호출됩니다 print td. 초를 원하지 않기 때문에 문자열을 콜론 (3 부분)으로 나누고 처음 2 부분 만 다시 묶을 수 있습니다.


답변

def td_format(td_object):
    seconds = int(td_object.total_seconds())
    periods = [
        ('year',        60*60*24*365),
        ('month',       60*60*24*30),
        ('day',         60*60*24),
        ('hour',        60*60),
        ('minute',      60),
        ('second',      1)
    ]

    strings=[]
    for period_name, period_seconds in periods:
        if seconds > period_seconds:
            period_value , seconds = divmod(seconds, period_seconds)
            has_s = 's' if period_value > 1 else ''
            strings.append("%s %s%s" % (period_value, period_name, has_s))

    return ", ".join(strings)


답변

개인적으로 humanize라이브러리를 사용합니다 .

>>> import datetime
>>> humanize.naturalday(datetime.datetime.now())
'today'
>>> humanize.naturalday(datetime.datetime.now() - datetime.timedelta(days=1))
'yesterday'
>>> humanize.naturalday(datetime.date(2007, 6, 5))
'Jun 05'
>>> humanize.naturaldate(datetime.date(2007, 6, 5))
'Jun 05 2007'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1))
'a second ago'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600))
'an hour ago'

물론, 그것은 당신이 찾고있는 정확한 대답을 제공하지는 않습니다 (실제로 str(timeA - timeB)몇 시간이 지나면 디스플레이를 빠르게 읽을 수 없음 humanize을 알았습니다 . 사람이 읽을 수 있고 잘 현지화되어 있습니다.

장고의 contrib.humanize모듈 에서 영감을 얻은 것 같습니다. 장고를 사용하고 있기 때문에 아마도 그것을 사용해야합니다.


답변

그는 이미 timedelta 객체를 가지고 있으므로 내장 메소드 total_seconds ()를 사용하여 초로 변환 한 다음 divmod ()를 사용하여 시간과 분을 얻으십시오.

hours, remainder = divmod(myTimeDelta.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)

# Formatted only for hours and minutes as requested
print '%s:%s' % (hours, minutes)

이것은 시간 델타가 며칠 또는 몇 년인지에 관계없이 작동합니다.


답변

다음은 timedelta객체 또는 일반 숫자 (초 또는 분 등의 형식)를 멋진 형식의 문자열 로 변환하는 범용 함수입니다 . 나는 중복 질문에 대한 mpounsett의 환상적인 대답취하여 조금 더 유연하고 가독성을 높이고 문서를 추가했습니다.

다음을 수행 할 수 있기 때문에 지금까지 가장 유연한 답변임을 알 수 있습니다.

  1. 하드 코딩되는 대신 문자열 형식을 즉석에서 사용자 지정할 수 있습니다.
  2. 문제없이 일정한 시간 간격을 두십시오 (아래 예 참조).

함수:

from string import Formatter
from datetime import timedelta

def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02}s', inputtype='timedelta'):
    """Convert a datetime.timedelta object or a regular number to a custom-
    formatted string, just like the stftime() method does for datetime.datetime
    objects.

    The fmt argument allows custom formatting to be specified.  Fields can
    include seconds, minutes, hours, days, and weeks.  Each field is optional.

    Some examples:
        '{D:02}d {H:02}h {M:02}m {S:02}s' --> '05d 08h 04m 02s' (default)
        '{W}w {D}d {H}:{M:02}:{S:02}'     --> '4w 5d 8:04:02'
        '{D:2}d {H:2}:{M:02}:{S:02}'      --> ' 5d  8:04:02'
        '{H}h {S}s'                       --> '72h 800s'

    The inputtype argument allows tdelta to be a regular number instead of the
    default, which is a datetime.timedelta object.  Valid inputtype strings:
        's', 'seconds',
        'm', 'minutes',
        'h', 'hours',
        'd', 'days',
        'w', 'weeks'
    """

    # Convert tdelta to integer seconds.
    if inputtype == 'timedelta':
        remainder = int(tdelta.total_seconds())
    elif inputtype in ['s', 'seconds']:
        remainder = int(tdelta)
    elif inputtype in ['m', 'minutes']:
        remainder = int(tdelta)*60
    elif inputtype in ['h', 'hours']:
        remainder = int(tdelta)*3600
    elif inputtype in ['d', 'days']:
        remainder = int(tdelta)*86400
    elif inputtype in ['w', 'weeks']:
        remainder = int(tdelta)*604800

    f = Formatter()
    desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)]
    possible_fields = ('W', 'D', 'H', 'M', 'S')
    constants = {'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
    values = {}
    for field in possible_fields:
        if field in desired_fields and field in constants:
            values[field], remainder = divmod(remainder, constants[field])
    return f.format(fmt, **values)

데모:

>>> td = timedelta(days=2, hours=3, minutes=5, seconds=8, microseconds=340)

>>> print strfdelta(td)
02d 03h 05m 08s

>>> print strfdelta(td, '{D}d {H}:{M:02}:{S:02}')
2d 3:05:08

>>> print strfdelta(td, '{D:2}d {H:2}:{M:02}:{S:02}')
 2d  3:05:08

>>> print strfdelta(td, '{H}h {S}s')
51h 308s

>>> print strfdelta(12304, inputtype='s')
00d 03h 25m 04s

>>> print strfdelta(620, '{H}:{M:02}', 'm')
10:20

>>> print strfdelta(49, '{D}d {H}h', 'h')
2d 1h