web-dev-qa-db-ja.com

Python形式のタイムデルタから文字列

私はPython初心者(2週間)で、datetime.timedeltaオブジェクトのフォーマットに問題があります。

私がやろうとしていることは次のとおりです。オブジェクトのリストがあり、オブジェクトのクラスのメンバーの1つは、イベントの継続時間を示すtimedeltaオブジェクトです。その期間を時間:分という形式で表示したいと思います。

これを行うためにさまざまな方法を試してみましたが、問題があります。私の現在のアプローチは、時間と分を返すオブジェクトのメソッドをクラスに追加することです。 timedelta.secondsを3600で割って丸めると、時間を取得できます。残りの秒を取得してそれを分に変換するのに問題があります。

ちなみに、プレゼンテーションにはGoogle AppEngineDjango Templatesを使用しています。

誰かがこれを解決するより良い方法を手伝うことができるか、知っているなら、私はとても幸せです。

おかげで、

226
mawcs

Str()を使用して、timedeltaを文字列に変換するだけです。次に例を示します。

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
185
Parand

ご存知のように、.seconds属性にアクセスすることで、timedeltaオブジェクトからtotal_secondsを取得できます。

Pythonは、以下を可能にする組み込み関数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
156
John Fouhy
>>> 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つの部分だけで元に戻すことができます。

55
joeforker
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)
38

彼はすでに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)

これは、時間差に日数や年数がある場合でも機能します。

27
Bill Kidd

私は個人的に 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は、人間が読めるはるかに大きな値をサポートしており、ローカライズされています。

Djangoのcontrib.humanizeモジュールに触発されているようです。したがって、Djangoを使用しているので、おそらくそれを使用する必要があります。

22
anarcat

これは古い答えの質問であることは知っていますが、これにはdatetime.utcfromtimestamp()を使用します。秒数を要し、他のdatetimeと同様にフォーマットできるdatetimeを返します。

duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime('%H:%M')

時間部分の有効範囲内にある限り、これは機能するはずです。つまり、時間は23以下なので1234:35を返しません。

16
sjngm

質問者は、一般的な形式よりも優れた形式を求めています

  >>> import datetime
  >>> datetime.timedelta(seconds=41000)
  datetime.timedelta(0, 41000)
  >>> str(datetime.timedelta(seconds=41000))
  '11:23:20'
  >>> str(datetime.timedelta(seconds=4102.33))
  '1:08:22.330000'
  >>> str(datetime.timedelta(seconds=413302.33))
  '4 days, 18:48:22.330000'

したがって、実際には2つの形式があります。1つは日が0で省略されている形式で、もう1つは「n days、h:m:s」というテキストがあります。ただし、秒には小数が含まれる場合があり、印刷出力に先行ゼロがないため、列が乱雑になります。

あなたがそれを好めば、ここに私のルーチンがあります:

def printNiceTimeDelta(stime, etime):
    delay = datetime.timedelta(seconds=(etime - stime))
    if (delay.days > 0):
        out = str(delay).replace(" days, ", ":")
    else:
        out = "0:" + str(delay)
    outAr = out.split(':')
    outAr = ["%02d" % (int(float(x))) for x in outAr]
    out   = ":".join(outAr)
    return out

これは、出力をdd:hh:mm:ss形式で返します。

00:00:00:15
00:00:00:19
02:01:31:40
02:01:32:22

私はこれに年を追加することを考えましたが、出力は1年以上で安全であるため、これは読者の課題として残されています。

>>> str(datetime.timedelta(seconds=99999999))
'1157 days, 9:46:39'
15
Kevin J. Rice

datetime.timedeltaオブジェクトが1日を超えました。そこで、さらに問題があります。上記の説明はすべて1日未満を想定しています。 timedeltaは、実際には日、秒、マイクロ秒のタプルです。上記の説明では、joeのようにtd.secondsを使用する必要がありますが、日数がある場合は、seconds値に含まれません。

2つの日付時刻と印刷日と時間の間の期間を取得しています。

span = currentdt - previousdt
print '%d,%d\n' % (span.days,span.seconds/3600)
13
user198910

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
12
MarredCheese

ここで、OccamのRazorアプローチを真剣に検討します。

td = str(timedelta).split('.')[0]

これは、マイクロ秒なしの文字列を返します

Datetime.timedeltaオブジェクトを再生成する場合は、次のようにします。

h,m,s = re.split(':', td)
new_delta = datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s))

2年後、私はこの言語が大好きです!

9
Pyrotherm

上記のJoeの値の例に従って、モジュラス算術演算子を使用します。

td = datetime.timedelta(hours=10.56)
td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)

Pythonの整数除算はデフォルトで切り捨てられることに注意してください。より明示的にしたい場合は、必要に応じてmath.floor()またはmath.ceil()を使用します。

7
UltraNurd

humanfriendly pythonライブラリを使用してこれを実行しましたが、非常にうまく機能します。

import humanfriendly
from datetime import timedelta
delta = timedelta(seconds = 321)
humanfriendly.format_timespan(delta)

'5 minutes and 21 seconds'

https://pypi.org/project/humanfriendly/ で利用可能

5
Dhiraj Gupta
def seconds_to_time_left_string(total_seconds):
    s = int(total_seconds)
    years = s // 31104000
    if years > 1:
        return '%d years' % years
    s = s - (years * 31104000)
    months = s // 2592000
    if years == 1:
        r = 'one year'
        if months > 0:
            r += ' and %d months' % months
        return r
    if months > 1:
        return '%d months' % months
    s = s - (months * 2592000)
    days = s // 86400
    if months == 1:
        r = 'one month'
        if days > 0:
            r += ' and %d days' % days
        return r
    if days > 1:
        return '%d days' % days
    s = s - (days * 86400)
    hours = s // 3600
    if days == 1:
        r = 'one day'
        if hours > 0:
            r += ' and %d hours' % hours
        return r 
    s = s - (hours * 3600)
    minutes = s // 60
    seconds = s - (minutes * 60)
    if hours >= 6:
        return '%d hours' % hours
    if hours >= 1:
        r = '%d hours' % hours
        if hours == 1:
            r = 'one hour'
        if minutes > 0:
            r += ' and %d minutes' % minutes
        return r
    if minutes == 1:
        r = 'one minute'
        if seconds > 0:
            r += ' and %d seconds' % seconds
        return r
    if minutes == 0:
        return '%d seconds' % seconds
    if seconds == 0:
        return '%d minutes' % minutes
    return '%d minutes and %d seconds' % (minutes, seconds)

for i in range(10):
    print pow(8, i), seconds_to_time_left_string(pow(8, i))


Output:
1 1 seconds
8 8 seconds
64 one minute and 4 seconds
512 8 minutes and 32 seconds
4096 one hour and 8 minutes
32768 9 hours
262144 3 days
2097152 24 days
16777216 6 months
134217728 4 years
4
Veselin Penev

職場での残業計算の出力にも同様の問題がありました。値は、1日より長く、値が負になる場合でも、HH:MMに常に表示される必要があります。表示されているソリューションのいくつかを組み合わせたので、他の誰かがこのソリューションが役立つと思うかもしれません。 timedeltaの値が負の場合、divmodメソッドで示されているほとんどのソリューションはそのままでは機能しないことがわかりました。

def td2HHMMstr(td):
  '''Convert timedelta objects to a HH:MM string with (+/-) sign'''
  if td < datetime.timedelta(seconds=0):
    sign='-'
    td = -td
  else:
    sign = ''
  tdhours, rem = divmod(td.total_seconds(), 3600)
  tdminutes, rem = divmod(rem, 60)
  tdstr = '{}{:}:{:02d}'.format(sign, int(tdhours), int(tdminutes))
  return tdstr

timedeltaからHH:MM文字列へ:

td2HHMMstr(datetime.timedelta(hours=1, minutes=45))
'1:54'

td2HHMMstr(datetime.timedelta(days=2, hours=3, minutes=2))
'51:02'

td2HHMMstr(datetime.timedelta(hours=-3, minutes=-2))
'-3:02'

td2HHMMstr(datetime.timedelta(days=-35, hours=-3, minutes=-2))
'-843:02'
4
nealtz
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))
3
SleX
from Django.utils.translation import ngettext

def localize_timedelta(delta):
    ret = []
    num_years = int(delta.days / 365)
    if num_years > 0:
        delta -= timedelta(days=num_years * 365)
        ret.append(ngettext('%d year', '%d years', num_years) % num_years)

    if delta.days > 0:
        ret.append(ngettext('%d day', '%d days', delta.days) % delta.days)

    num_hours = int(delta.seconds / 3600)
    if num_hours > 0:
        delta -= timedelta(hours=num_hours)
        ret.append(ngettext('%d hour', '%d hours', num_hours) % num_hours)

    num_minutes = int(delta.seconds / 60)
    if num_minutes > 0:
        ret.append(ngettext('%d minute', '%d minutes', num_minutes) % num_minutes)

    return ' '.join(ret)

これにより、以下が生成されます。

>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'
2
Artem Vasilev

この関数を確認してください-timedeltaオブジェクトを文字列「HH:MM:SS」に変換します

def format_timedelta(td):
    hours, remainder = divmod(td.total_seconds(), 3600)
    minutes, seconds = divmod(remainder, 60)
    hours, minutes, seconds = int(hours), int(minutes), int(seconds)
    if hours < 10:
        hours = '0%s' % int(hours)
    if minutes < 10:
        minutes = '0%s' % minutes
    if seconds < 10:
        seconds = '0%s' % seconds
    return '%s:%s:%s' % (hours, minutes, seconds)
1
MobilePro.pl