Bagaimana cara mengonversi detik ke jam, menit, dan detik?

472

Saya memiliki fungsi yang mengembalikan informasi dalam hitungan detik, tetapi saya perlu menyimpan informasi itu dalam jam: menit: detik.

Apakah ada cara mudah untuk mengkonversi detik ke format ini dengan Python?

Specto
sumber
20
Kebalikan dari masalah ini dapat ditemukan di Bagaimana mengkonversi string waktu H: MM: SS ke detik dalam Python?
hughes

Jawaban:

764

Anda dapat menggunakan datetime.timedeltafungsi:

>>> import datetime
>>> str(datetime.timedelta(seconds=666))
'0:11:06'
SilentGhost
sumber
9
Ini adalah cara terbaik, IMHO, karena Anda dapat menggunakan aritmatika pada timedelta dan objek datetime apa pun.
Matthew Schinckel
13
Ini berfungsi selama beberapa hari: str(datetime.timedelta(seconds=60*60*24+1))='1 day, 0:00:01'
hyprnick
3
str(datetime.timedelta(seconds=round(666666.55)))membuat hari dengan benar; menekan detik desimal.
CPBL
1
timedeltatidak overflow aman dan tidak dapat melakukan operasi matematika dengan benar, misalnya str(timedelta(hours=8) - timedelta(hours=10))hasilnya '-1 day, 22:00:00'dan solusi berbasis integer tepat untuk situasi di mana Anda butuhkan '-02:00:00'.
cprn
1
+1. Jawaban ini dapat dimodifikasi dengan sangat mudah. Misalnya, jika Anda ingin menghilangkan bidang saat mencetak, gunakan ini: stackoverflow.com/questions/7999935/…
eric_kernfeld
616

Dengan menggunakan divmod()fungsi, yang hanya melakukan satu divisi untuk menghasilkan hasil bagi dan sisanya, Anda dapat memiliki hasilnya dengan sangat cepat dengan hanya dua operasi matematika:

m, s = divmod(seconds, 60)
h, m = divmod(m, 60)

Dan kemudian gunakan pemformatan string untuk mengubah hasil menjadi output yang Anda inginkan:

print('{:d}:{:02d}:{:02d}'.format(h, m, s)) # Python 3
print(f'{h:d}:{m:02d}:{s:02d}') # Python 3.6+
Brandon Rhodes
sumber
2
Jika Anda lebih suka operator daripada fungsi, gunakan modulo; misalnya (hanya beberapa menit / detik):'%d:%02dmn' % (seconds / 60, seconds % 60)
bufh
18
Dan Anda dapat memperpanjang untuk hari: d, h = divmod(h, 24).
Mark Ransom
14
@ Markarkom: dan kemudian ke bulan m, d = divmod(m, 31). Aduh, tidak, kamu tidak bisa. Lebih buruk lagi, kode Anda akan salah jika lompatan detik masuk ke dalam permainan. Singkat cerita: gunakan timedeltadan jangan main-main dengan kalender, itu akan menggigit Anda.
4
@Tibo tidak timedeltaberurusan dengan detik kabisat? Saya kira tidak. Ada banyak aplikasi di mana matematika sederhana ini lebih dari cukup.
Mark Ransom
1
@MarkRansom str(timedelta(hours=8) - timedelta(hours=10))hasilnya adalah '-1 hari, 22:00:00' jadi ... idk jika bekerja dengan detik kabisat tetapi tidak bekerja dengan angka negatif.
cprn
70

Saya hampir tidak dapat menyebutkannya dengan cara yang mudah (setidaknya saya tidak dapat mengingat sintaks), tetapi dimungkinkan untuk menggunakan time.strftime , yang memberikan lebih banyak kontrol atas pemformatan:

from time import strftime
from time import gmtime

strftime("%H:%M:%S", gmtime(666))
'00:11:06'

strftime("%H:%M:%S", gmtime(60*60*24))
'00:00:00'

gmtime digunakan untuk mengonversi detik ke format tuple khusus yang strftime()memerlukan.

Catatan: Potong setelah 23:59:59

techtonik anatoly
sumber
Yah, jawabannya sebenarnya disediakan di sini - stackoverflow.com/questions/1384406/…
anatoly techtonik
13
Sayangnya metode ini mulai mengukur hari dari 1 sehingga tidak dirancang untuk mewakili delta waktu, dan karenanya merupakan kecelakaan yang menunggu untuk terjadi. Misalnya dengan time.strftime('%d %H:%M:%S', time.gmtime(1))=> '1 hari, 0:00:01'.
Riaz Rizvi
41

Menggunakan datetime:

Dengan ':0>8'format:

from datetime import timedelta

"{:0>8}".format(str(timedelta(seconds=66)))
# Result: '00:01:06'

"{:0>8}".format(str(timedelta(seconds=666777)))
# Result: '7 days, 17:12:57'

"{:0>8}".format(str(timedelta(seconds=60*60*49+109)))
# Result: '2 days, 1:01:49'

Tanpa ':0>8'format:

"{}".format(str(timedelta(seconds=66)))
# Result: '00:01:06'

"{}".format(str(timedelta(seconds=666777)))
# Result: '7 days, 17:12:57'

"{}".format(str(timedelta(seconds=60*60*49+109)))
# Result: '2 days, 1:01:49'

Menggunakan time:

from time import gmtime
from time import strftime

# NOTE: The following resets if it goes over 23:59:59!

strftime("%H:%M:%S", gmtime(125))
# Result: '00:02:05'

strftime("%H:%M:%S", gmtime(60*60*24-1))
# Result: '23:59:59'

strftime("%H:%M:%S", gmtime(60*60*24))
# Result: '00:00:00'

strftime("%H:%M:%S", gmtime(666777))
# Result: '17:12:57'
# Wrong
marcell
sumber
1
gagal jika delta kurang dari satu detik:"{:0>8}".format(timedelta(milliseconds=66)) '0:00:00.066000'
jfs
1
Untuk orang lain: without ':0>8':Contohnya tidak ada 0. {:0>8}nol bantalan di sebelah kiri nol nol.
TankorSmash
2
Dalam python 3.5.2, saya mendapatkan TypeError. Saya memformat time.time()-startvariabel. Adakah wawasan? TypeError: non-empty format string passed to object.__format__
medley56
Saya mencoba menggunakan datetime.now()alih-alih time.time()untuk menghasilkan objek timedelta saya dan saya mendapatkan kesalahan yang sama.
medley56
@ medley56 Bila menggunakan Python3, Anda perlu menggunakan str()jika Anda akan menggunakan format seperti 0>8: "{:0>8}".format(str(datetime.timedelta(seconds=666777))). Periksa jawaban ini untuk info lebih lanjut.
Berriel
9

Jika Anda perlu mendapatkan datetime.timenilai, Anda dapat menggunakan trik ini:

my_time = (datetime(1970,1,1) + timedelta(seconds=my_seconds)).time()

Anda tidak dapat menambahkan timedeltauntuk time, tetapi dapat menambahkannya ke datetime.

UPD : Variasi lain dari teknik yang sama:

my_time = (datetime.fromordinal(1) + timedelta(seconds=my_seconds)).time()

Alih-alih 1Anda dapat menggunakan angka lebih besar dari 0. Di sini kami menggunakan fakta bahwa datetime.fromordinalakan selalu mengembalikan datetimeobjek dengan timekomponen menjadi nol.

MarSoft
sumber
6

Ini adalah bagaimana saya mendapatkannya.

def sec2time(sec, n_msec=3):
    ''' Convert seconds to 'D days, HH:MM:SS.FFF' '''
    if hasattr(sec,'__len__'):
        return [sec2time(s) for s in sec]
    m, s = divmod(sec, 60)
    h, m = divmod(m, 60)
    d, h = divmod(h, 24)
    if n_msec > 0:
        pattern = '%%02d:%%02d:%%0%d.%df' % (n_msec+3, n_msec)
    else:
        pattern = r'%02d:%02d:%02d'
    if d == 0:
        return pattern % (h, m, s)
    return ('%d days, ' + pattern) % (d, h, m, s)

Beberapa contoh:

$ sec2time(10, 3)
Out: '00:00:10.000'

$ sec2time(1234567.8910, 0)
Out: '14 days, 06:56:07'

$ sec2time(1234567.8910, 4)
Out: '14 days, 06:56:07.8910'

$ sec2time([12, 345678.9], 3)
Out: ['00:00:12.000', '4 days, 00:01:18.900']
Lee
sumber
1
Apa keuntungannya dari jawaban di atas? str(datetime.timedelta(seconds=666))
Riaz Rizvi
@RiazRizvi memberikan panjang string yang konsisten untuk mikrodetik 666.0dan 666.1nilai.
anatoly techtonik
6

Set berikut bekerja untuk saya.

def sec_to_hours(seconds):
    a=str(seconds//3600)
    b=str((seconds%3600)//60)
    c=str((seconds%3600)%60)
    d=["{} hours {} mins {} seconds".format(a, b, c)]
    return d


print(sec_to_hours(10000))
# ['2 hours 46 mins 40 seconds']

print(sec_to_hours(60*60*24+105))
# ['24 hours 1 mins 45 seconds']
decoder naif
sumber
3

dateutil.relativedeltanyaman jika Anda perlu mengakses jam, menit dan detik juga mengapung. datetime.timedeltatidak menyediakan antarmuka yang sama.

from dateutil.relativedelta import relativedelta
rt = relativedelta(seconds=5440)
print(rt.seconds)
print('{:02d}:{:02d}:{:02d}'.format(
    int(rt.hours), int(rt.minutes), int(rt.seconds)))

Cetakan

40.0
01:30:40
teekarna
sumber
1
Saya mendapatkan hasil yang berbeda dari milik Anda, yang membuat saya berpikir Anda salah ketik. Anda mungkin dimaksudkan untuk menggunakan seconds=5440bukan seconds=5540. Saya suka jawaban Anda!
JL
2

jam (h) dihitung berdasarkan pembagian lantai (dengan //) detik oleh 3600 (60 mnt / jam * 60 dt / mnt)

menit (m) dihitung berdasarkan pembagian lantai detik yang tersisa (sisa dari perhitungan jam, dengan%) sebesar 60 (60 detik / mnt)

sama halnya, detik dengan sisa perhitungan jam dan menit.

Istirahat hanyalah pemformatan string!

def hms(seconds):
    h = seconds // 3600
    m = seconds % 3600 // 60
    s = seconds % 3600 % 60
    return '{:02d}:{:02d}:{:02d}'.format(h, m, s)

print(hms(7500))  # Should print 02h05m00s
Sam
sumber
Meskipun kode ini dapat memberikan solusi untuk pertanyaan OP, lebih baik menambahkan konteks mengapa / cara kerjanya. Ini dapat membantu pengguna di masa depan belajar, dan menerapkan pengetahuan itu ke kode mereka sendiri. Anda juga cenderung mendapat umpan balik positif dari pengguna dalam bentuk upvotes, ketika kode dijelaskan.
borchvm
2
Baru saja melakukannya, Terima kasih @borchvm untuk menunjukkan!
Sam
-2

Anda dapat membagi detik dengan 60 untuk mendapatkan menit

import time
seconds = time.time()
minutes = seconds / 60
print(minutes)

Ketika Anda membaginya dengan 60 lagi, Anda akan mendapatkan jam

alosha002
sumber
-3

division = 3623 // 3600 #to hours
division2 = 600 // 60 #to minutes
print (division) #write hours
print (division2) #write minutes

PS Kode saya tidak profesional

Denis Kerstens Denisik35
sumber
2
hei, pertanyaannya meminta format dalam jam: min: dtk, bukan divisi sederhana ..
StupidWolf