จัดรูปแบบ timedelta เป็นสตริง


275

ฉันมีปัญหาในการจัดรูปแบบdatetime.timedeltaวัตถุ

นี่คือสิ่งที่ฉันพยายามทำ: ฉันมีรายการของวัตถุและหนึ่งในสมาชิกของคลาสของวัตถุคือวัตถุ timedelta ที่แสดงระยะเวลาของเหตุการณ์ ฉันต้องการแสดงช่วงเวลานั้นในรูปแบบชั่วโมง: นาที

ฉันได้ลองวิธีการมากมายในการทำสิ่งนี้และฉันมีปัญหา วิธีการปัจจุบันของฉันคือการเพิ่มวิธีการเรียนสำหรับวัตถุของฉันที่ส่งกลับชั่วโมงและนาที ฉันสามารถรับชั่วโมงโดยการหาร timedelta.seconds โดย 3600 และปัดเศษมัน ฉันมีปัญหากับการได้รับส่วนที่เหลือวินาทีและแปลงเป็นนาที

ยังไงก็ตามฉันใช้ Google AppEngine กับ Django Templates เพื่อนำเสนอ


44
จะดีถ้า timedelta มีวิธี strftime () ที่เทียบเท่า
JS

@JS datetime.utcfromtimestamp()ดีที่คุณสามารถค่อนข้างถ้าคุณใช้ ดูคำตอบของฉันด้านล่าง
sjngm

@JS - เห็นด้วย 100% จากนั้น__str__ของtimedeltaจะดีมากเมื่อเทียบกับ__repr__(นั่นคือ - สำหรับมนุษย์) ตัวอย่างเช่น: datetime.timedelta(minutes=6, seconds=41) * 2618 / 48ให้datetime.timedelta(seconds=21871, microseconds=208333)แต่str(datetime.timedelta(minutes=6, seconds=41) * 2618 / 48)ให้'6:04:31.208333'ซึ่งค่อนข้างเป็นธรรมในการอ่าน
Tomasz Gandor

คำตอบ:


213

คุณสามารถแปลง timedelta เป็นสตริงด้วย 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

13
เหมือนการเรียกใช้เมธอด str () ที่มี timedelta เป็นอาร์กิวเมนต์
joeforker

12
คุณไม่จำเป็นต้องใช้สายที่นั่นมันจะถูกพิมพ์โดยอัตโนมัติ
Zitrax

5
@Zitrax แต่จำเป็นถ้าคุณจะต่อเดลต้ากับสตริงอื่น ตัวอย่างเช่นprint 'some thing ' + str(delta)
Plinio.Santos

13
และจำเป็นเมื่อประเภทข้อมูลถูกกำหนดเป็น 'datetime.timedelta' และคุณใช้มันเช่นนี้ConvertDuration=datetime.timedelta(milliseconds=int(254459))จากนั้นคุณก็ใช้ split เพื่อรับไมโครวินาทีจากการเล่น จาก0: 03: 43.765000ฉันจะได้รับ0:03:43เพียงแค่วิ่งTotalDuration=str(ConvertDuration).split('.', 2)[0]
DarkXDroid

16
นี่อาจพิมพ์เดลตาเป็นสตริง แต่ไม่ได้จัดรูปแบบตามที่ OP ร้องขอ
Dannid

187

อย่างที่คุณทราบคุณจะได้รับผลรวมจากวินาทีเป็นวัตถุ timedelta โดยเข้าถึง.secondsแอตทริบิวต์

Python มีฟังก์ชัน builtin 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

5
สำหรับ timedeltas abs(s)เชิงลบที่คุณควรจะทำอย่างไรในการประเมินเข้าสู่ระบบก่อนแล้วจึงทำ
mbarkhau

27
โปรดทราบว่าคุณอาจต้องการใช้'%d:%02d:%02d'เพื่อให้มีศูนย์นำหน้าในสตริงเอาต์พุต
ShinNoNoir

12
สำหรับ python 2.7 และสูงกว่าใช้. total_seconds () วิธีการ
sk8asd123

27
อย่าใช้.secondsหากความแตกต่างอาจเป็นค่าลบหรือนานกว่า 24 ชั่วโมง ( .secondsแอตทริบิวต์จะละเว้น.days) ใช้.total_seconds()หรืออะนาล็อกแทน
jfs

สำหรับความแตกต่างในเชิงบวกฉันได้นำสิ่งนี้กลับมาใช้ใหม่เป็นครั้งคราว ขอบคุณสำหรับการเพียงแค่มีการค้นหาครั้งนี้ :)
หมาป่า

59
>>> 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 ส่วนแรกเท่านั้น


ขอบคุณสำหรับคำตอบของคุณ joeforker แต่ฉันไม่แน่ใจว่าฉันเข้าใจคำตอบของคุณ ฉันได้รับเดลต้าเวลาตามวันที่และเวลา - วันที่และเวลา ฉันไม่รู้ชั่วโมง นอกจากนี้ดูเหมือนว่าตัวอย่างของคุณจะรวมวินาทีฉันจะลบออกได้อย่างไร
mawcs

1
ไม่สำคัญว่าคุณจะได้รับวัตถุ timedelta จากที่ใดมันจะจัดรูปแบบเหมือนเดิม
joeforker

9
ถ้ามันยาวกว่าหนึ่งวันมันจะจัดรูปแบบเช่น "4 วัน 8:00" หลังจากการแยก / เข้าร่วมการประมวลผล
joeforker

4
str(my_timedelta)ทำงานได้ไม่ดีสำหรับตัวเลขติดลบ
Catskul

2
แสดงวันเช่นกันเมื่อ> 24 ชั่วโมงเช่น '4 วัน 18: 48: 22.330000' วิธีการมากมายที่แนะนำในที่นี้ทำไม่ได้
Alexei Martianov

47
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)

3
ดีจริงๆผมจะขอแนะนำให้เปลี่ยนif seconds > period_seconds:ไปif seconds >= period_seconds:อย่างไร
CBenni

1
ส่งคืนสตริงว่างสำหรับ timedeltas เชิงลบ แต่ไม่แน่ใจว่ามีจุดประสงค์นี้หรือไม่
เดิร์ค

31

ฉันเองใช้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โมดูลของ Django ดังนั้นเมื่อคุณใช้ Django คุณควรใช้มัน


2
ดี, +1 แม้ว่า: humanize.naturaldelta (pd.Timedelta ('- 10sec')) -> '10 วินาที ': S ...
ntg

2
ดีที่มันเป็น 10 สองเดลต้า :) คุณต้องการเวลา , naturaltimeคือสิ่งที่คุณต้องการที่จะใช้
anarcat

28

เขามีอ็อบเจกต์ 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)

สิ่งนี้จะทำงานโดยไม่คำนึงว่าเวลาเดลต้ามีเท่าหรือหลายปี


23

นี่คือฟังก์ชั่นวัตถุประสงค์ทั่วไปสำหรับการแปลง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

ดีมากสะอาดรหัส! ฉันสงสัยว่ารหัสนี้สามารถขยายได้เพื่อจัดการกับเศษส่วนที่เหลือเพียงไม่กี่วินาทีในการจัดรูปแบบ ...
kfmfe04

17

ฉันรู้ว่านี่เป็นคำถามที่ตอบแล้ว แต่ฉันใช้datetime.utcfromtimestamp()สำหรับสิ่งนี้ ใช้เวลาไม่กี่วินาทีและส่งกลับค่าdatetimeที่สามารถจัดรูปแบบเหมือนdatetimeกัน

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

ตราบใดที่คุณยังอยู่ในช่วงของกฏหมายสำหรับเวลาส่วนนี้ก็จะได้ผลเช่นนั้นจะไม่ส่งคืน 1234: 35 เนื่องจากชั่วโมงคือ <= 23


2
คุณควรใช้print timedelta(seconds=end - begin)แทน
jfs

@JFSebastian จากนั้นคุณจะต้องเพิ่มจำนวนชั่วโมงด้วยตนเองด้วยศูนย์นำหน้า
sjngm

ฉันไม่เห็นอะไรเกี่ยวกับช่องว่างภายในคำถาม ใช้.zfill(8)ถ้าคุณต้องการ
jfs

1
ต้องการการเรียกใช้. Total_seconds (): >>> datetime.utcfromtimestamp ((t2-t1) .total_seconds ()) strftime ("% H:% M:% S") <<< >>> '00: 00: 05 '
cagney

2
ฉันชอบโซลูชันนี้มากช่วยให้คุณสามารถควบคุมการจัดรูปแบบได้ หมายเหตุคุณยังสามารถใช้ตัวจัดรูปแบบ str โดยตรงเช่นนี้: "{0:% H}: {0:% M}" รูปแบบ (ระยะเวลา)
toes

15

ผู้ถามต้องการรูปแบบที่ดีกว่าแบบทั่วไป:

  >>> 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'

ดังนั้นจริงๆแล้วมีสองรูปแบบหนึ่งรูปแบบที่วันคือ 0 และเหลืออีกรูปแบบหนึ่งและอีกรูปแบบหนึ่งที่มีข้อความ "n วัน, 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

ฉันจะพิจารณาแนวทางมีดโกนของ Occam อย่างจริงจังที่นี่:

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 ปีในฉันรักภาษานี้!


5
สิ่งนี้ไม่ครอบคลุมวัน
Waschbaer

13

datetime.timedeltaวัตถุของฉันมากกว่าหนึ่งวัน ดังนั้นนี่คือปัญหาเพิ่มเติม การอภิปรายทั้งหมดข้างต้นถือว่าน้อยกว่าหนึ่งวัน timedeltaเป็นจริง tuple ของวัน, วินาทีและ microseconds การสนทนาข้างต้นควรใช้td.secondsอย่างที่โจทำได้ แต่ถ้าคุณมีวันมันจะไม่รวมอยู่ในค่าวินาที

ฉันได้รับช่วงเวลาระหว่าง 2 ชุดข้อมูลและการพิมพ์วันและเวลา

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

นี่เป็นวิธีแก้ปัญหาในอนาคต
Jibin

11

ฉันใช้humanfriendlyห้องสมุดหลามเพื่อทำสิ่งนี้มันทำงานได้ดีมาก

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

'5 minutes and 21 seconds'

มีให้ที่https://pypi.org/project/humanfriendly/


7

ตามค่าตัวอย่างของโจด้านบนฉันจะใช้ตัวดำเนินการทางคณิตศาสตร์ของโมดูลัสดังนี้:

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

โปรดทราบว่าการแบ่งจำนวนเต็มใน Python จะปัดเศษลงตามค่าเริ่มต้น หากคุณต้องการให้ชัดเจนยิ่งขึ้นให้ใช้ math.floor () หรือ math.ceil () ตามความเหมาะสม


timedelta รู้วิธีจัดรูปแบบตัวเองแล้วเช่นเดียวกับใน 'print some_timedelta'
joeforker

ใช่ แต่ไม่สามารถยอมรับสตริงรูปแบบที่กำหนดเองซึ่งเป็นสิ่งที่ไมเคิลถาม แม้ว่าตอนนี้ฉันคิดว่ามันเป็น 3600 ตัวหาร mod ทำให้สมมติฐานชั่วโมงซึ่งทำให้เกิดปัญหาที่ก้าวกระโดดวินาที
UltraNurd

ใช่ แต่เขาไม่ต้องการสตริงรูปแบบที่กำหนดเองเขาต้องการพฤติกรรมเริ่มต้นเกือบทั้งหมด
joeforker

2
อย่าลืม // เพื่อตัดทอนส่วนใน Python 3000
joeforker

3
+1 แต่ทำไมคุณไม่แก้ไขคำตอบที่จะใช้ // ฉันขอแนะนำให้ใช้td.total_seconds()แทน.secondsเพื่อให้ทำงานได้เป็นระยะ> 1 วัน
Antony Hatchkins

4
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

คุณเขียนอันนี้หรือไม่? คุณทดสอบมันมากแค่ไหน?
โทมัส Ahle

ฉันกำลังใช้รหัสนี้ในโครงการของฉันเรียกว่าdatahaven.net มันใช้งานได้ดี คุณเห็นข้อผิดพลาดหรือไม่?
Veselin Penev

เป็นเรื่องที่ดีถ้าคุณให้ข้อมูลเล็กน้อยกับคำตอบที่หนักหน่วง :) เช่นตัวอย่างของการทำงานจุดแข็งและจุดอ่อนที่เป็นไปได้
โทมัส Ahle

1
โอ้ แน่นอนว่า !. เพิ่มตัวอย่างให้คุณแล้ว :-)
Veselin Penev

ซูเปอร์ :) นอกจากนี้ยังแจ้งให้ทราบว่าtimedeltaวัตถุที่มีเขตข้อมูลdays, secondsและmicrosecondsโดยเอกสาร
โทมัส Ahle

4

ฉันมีปัญหาคล้ายกันกับผลลัพธ์ของการคำนวณค่าล่วงเวลาในที่ทำงาน ค่าควรแสดงเป็น 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
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))

2
ใน 3.7 ฉันได้รับ AttributeError: วัตถุ 'datetime.timedelta' ไม่มีแอตทริบิวต์ 'strftime'
qubodup

4

ตัวกรองแม่แบบส่งตรงสำหรับปัญหานี้ ฟังก์ชันในตัว int () ไม่เคยปัดเศษขึ้น F-Strings (เช่น f '') ต้องการ python 3.6

@app_template_filter()
def diffTime(end, start):
    diff = (end - start).total_seconds()
    d = int(diff / 86400)
    h = int((diff - (d * 86400)) / 3600)
    m = int((diff - (d * 86400 + h * 3600)) / 60)
    s = int((diff - (d * 86400 + h * 3600 + m *60)))
    if d > 0:
        fdiff = f'{d}d {h}h {m}m {s}s'
    elif h > 0:
        fdiff = f'{h}h {m}m {s}s'
    elif m > 0:
        fdiff = f'{m}m {s}s'
    else:
        fdiff = f'{s}s'
    return fdiff

3
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'

สิ่งที่ดีที่สุดในความคิดของฉันในแง่ของความยาวและความครอบคลุม
Dici

1

กรุณาตรวจสอบฟังก์ชั่นนี้ - มันจะแปลงวัตถุ 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

หนึ่งในสายการบิน. เนื่องจาก timedeltas ไม่มี strftime ของ datetime ให้นำ timedelta กลับไปที่ datetime และใช้ stftime

สิ่งนี้ไม่เพียงสามารถบรรลุรูปแบบที่ร้องขอของ OP ได้เวลา: นาทีตอนนี้คุณสามารถใช้พลังการจัดรูปแบบเต็มรูปแบบของ strftime ของ datetime ได้หากความต้องการของคุณเปลี่ยนไปเป็นการนำเสนออื่น

import datetime
td = datetime.timedelta(hours=2, minutes=10, seconds=5)
print(td)
print(datetime.datetime.strftime(datetime.datetime.strptime(str(td), "%H:%M:%S"), "%H:%M"))

Output:
2:10:05
02:10

สิ่งนี้ยังช่วยแก้ไขความรำคาญที่ timedeltas ถูกจัดรูปแบบเป็นสตริงเช่น H: MM: SS มากกว่า HH: MM: SS ซึ่งทำให้ฉันมีปัญหานี้และวิธีแก้ไขที่ฉันแบ่งปัน


0

หากคุณมี obed timedelta แล้วเพียงแค่แปลง obj นั้นเป็นสตริง ลบอักขระ 3 ตัวสุดท้ายของสตริงและพิมพ์ สิ่งนี้จะตัดทอนส่วนวินาทีและพิมพ์ส่วนที่เหลือในรูปแบบชั่วโมง: นาที

t = str(timedeltaobj) 

print t[:-3]

-3 ไม่ทำงานใช้ดีกว่าprint t.split('.')[0]
EvgenyKolyakov

0

หากคุณมีIPythonอยู่ในแพ็คเกจของคุณ (คุณควร) มันมี (จนถึงตอนนี้) ตัวจัดรูปแบบที่ดีมากสำหรับระยะเวลา (ในหน่วยวินาที) ที่ใช้ในสถานที่ต่าง ๆ เช่น%%timeเซลล์เวทมนตร์ ฉันชอบรูปแบบที่สร้างขึ้นในระยะเวลาสั้น ๆ :

>>> from IPython.core.magics.execution import _format_time
>>> 
>>> for v in range(-9, 10, 2):
...     dt = 1.25 * 10**v
...     print(_format_time(dt))

1.25 ns
125 ns
12.5 µs
1.25 ms
125 ms
12.5 s
20min 50s
1d 10h 43min 20s
144d 16h 13min 20s
14467d 14h 13min 20s

-3
t1 = datetime.datetime.strptime(StartTime, "%H:%M:%S %d-%m-%y")

t2 = datetime.datetime.strptime(EndTime, "%H:%M:%S %d-%m-%y")

return str(t2-t1)

ดังนั้นสำหรับ:

StartTime = '15:28:53 21-07-13'
EndTime = '15:32:40 21-07-13'

ผลตอบแทน:

'0:03:47'

-10

ขอบคุณทุกคนสำหรับความช่วยเหลือของคุณ ฉันได้นำความคิดของคุณมารวมกันและทำให้พวกเขารู้ว่าคุณคิดอย่างไร

ฉันเพิ่มสองวิธีในชั้นเรียนเช่นนี้

def hours(self):
    retval = ""
    if self.totalTime:
        hoursfloat = self.totalTime.seconds / 3600
        retval = round(hoursfloat)
    return retval

def minutes(self):
    retval = ""
    if self.totalTime:
        minutesfloat = self.totalTime.seconds / 60
        hoursAsMinutes = self.hours() * 60
        retval = round(minutesfloat - hoursAsMinutes)
    return retval

ใน django ของฉันฉันใช้สิ่งนี้ (ผลรวมคือวัตถุและอยู่ในพจนานุกรม):

<td>{{ sum.0 }}</td>    
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>

มันค่อนข้างยาว ฉันจะแนะนำ: def hhmm (ตัวเอง): return ':'. เข้าร่วม (str (td) .split (':') [: 2]) <td> {{sum.1.hhmm}} </td>
joeforker

1
เพียงใช้ divmod () ตามที่แสดงในตัวอย่าง "ความแตกต่างของวันที่สอง" ที่docs.python.org/release/2.5.2/lib/datetime-timedelta.html
Tom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.