Función Python para convertir segundos en minutos, horas y días.

Pregunta: Escriba un progtwig que le pida al usuario que ingrese un número de segundos y funciona de la siguiente manera:

  • Hay 60 segundos en un minuto. Si el número de segundos ingresados ​​por el usuario es mayor o igual a 60, el progtwig debe mostrar el número de minutos en esos segundos.

  • Hay 3600 segundos en una hora. Si el número de segundos ingresados ​​por el usuario es mayor o igual a 3600, el progtwig debe mostrar el número de horas en esos segundos.

  • Hay 86400 segundos en un día. Si el número de segundos ingresados ​​por el usuario es mayor o igual a 86400, el progtwig debe mostrar el número de días en tantos segundos.

Lo que tengo hasta ahora:

def time(): sec = int( input ('Enter the number of seconds:'.strip()) if sec <= 60: minutes = sec // 60 print('The number of minutes is {0:.2f}'.format(minutes)) if sec (<= 3600): hours = sec // 3600 print('The number of minutes is {0:.2f}'.format(hours)) if sec <= 86400: days = sec // 86400 print('The number of minutes is {0:.2f}'.format(days)) return 

Este tidbit es útil para mostrar el tiempo transcurrido a diversos grados de granularidad.

Personalmente creo que las cuestiones de eficiencia prácticamente no tienen sentido aquí, siempre y cuando no se haga algo summente ineficiente. La optimización prematura es la raíz de un poco de maldad. Esto es lo suficientemente rápido para que nunca sea tu punto de estrangulamiento.

 intervals = ( ('weeks', 604800), # 60 * 60 * 24 * 7 ('days', 86400), # 60 * 60 * 24 ('hours', 3600), # 60 * 60 ('minutes', 60), ('seconds', 1), ) def display_time(seconds, granularity=2): result = [] for name, count in intervals: value = seconds // count if value: seconds -= value * count if value == 1: name = name.rstrip('s') result.append("{} {}".format(value, name)) return ', '.join(result[:granularity]) 

..y esto proporciona una salida decente:

 In [52]: display_time(1934815) Out[52]: '3 weeks, 1 day' In [53]: display_time(1934815, 4) Out[53]: '3 weeks, 1 day, 9 hours, 26 minutes' 

Esto convertirá n segundos en d días, h horas, m minutos y s segundos.

 from datetime import datetime, timedelta def GetTime(): sec = timedelta(seconds=int(input('Enter the number of seconds: '))) d = datetime(1,1,1) + sec print("DAYS:HOURS:MIN:SEC") print("%d:%d:%d:%d" % (d.day-1, d.hour, d.minute, d.second)) 

Para convertir segundos (como cadena) en fecha y hora, esto también podría ayudar. Obtiene número de días y segundos. Los segundos se pueden convertir en minutos y horas.

 from datetime import datetime, timedelta sec = timedelta(seconds=(input('Enter the number of seconds: '))) time = str(sec) 
 seconds_in_day = 86400 seconds_in_hour = 3600 seconds_in_minute = 60 seconds = int(input("Enter a number of seconds: ")) days = seconds // seconds_in_day seconds = seconds - (days * seconds_in_day) hours = seconds // seconds_in_hour seconds = seconds - (hours * seconds_in_hour) minutes = seconds // seconds_in_minute seconds = seconds - (minutes * seconds_in_minute) print("{0:.0f} days, {1:.0f} hours, {2:.0f} minutes, {3:.0f} seconds.".format( days, hours, minutes, seconds)) 

No estoy completamente seguro de si lo desea, pero tuve una tarea similar y necesitaba eliminar un campo si es cero. Por ejemplo, 86401 segundos mostrarían “1 días, 1 segundos” en lugar de “1 días, 0 horas, 0 minutos, 1 segundos”. El siguiente código hace eso.

 def secondsToText(secs): days = secs//86400 hours = (secs - days*86400)//3600 minutes = (secs - days*86400 - hours*3600)//60 seconds = secs - days*86400 - hours*3600 - minutes*60 result = ("{} days, ".format(days) if days else "") + \ ("{} hours, ".format(hours) if hours else "") + \ ("{} minutes, ".format(minutes) if minutes else "") + \ ("{} seconds, ".format(seconds) if seconds else "") return result 

EDITAR: una versión ligeramente mejor que maneja la pluralización de palabras.

 def secondsToText(secs): days = secs//86400 hours = (secs - days*86400)//3600 minutes = (secs - days*86400 - hours*3600)//60 seconds = secs - days*86400 - hours*3600 - minutes*60 result = ("{0} day{1}, ".format(days, "s" if days!=1 else "") if days else "") + \ ("{0} hour{1}, ".format(hours, "s" if hours!=1 else "") if hours else "") + \ ("{0} minute{1}, ".format(minutes, "s" if minutes!=1 else "") if minutes else "") + \ ("{0} second{1}, ".format(seconds, "s" if seconds!=1 else "") if seconds else "") return result 

EDIT2: creó una esencia que hace eso en varios idiomas

 #1 min = 60 #1 hour = 60 * 60 = 3600 #1 day = 60 * 60 * 24 = 86400 x=input('enter a positive integer: ') t=int(x) day= t//86400 hour= (t-(day*86400))//3600 minit= (t - ((day*86400) + (hour*3600)))//60 seconds= t - ((day*86400) + (hour*3600) + (minit*60)) print( day, 'days' , hour,' hours', minit, 'minutes',seconds,' seconds') 
 def convertSeconds(seconds): h = seconds//(60*60) m = (seconds-h*60*60)//60 s = seconds-(h*60*60)-(m*60) return [h, m, s] 

La entrada de la función es una cantidad de segundos, y el retorno es una lista de horas, minutos y segundos que representa esa cantidad de segundos.

A primera vista, pensé que divmod sería más rápido ya que es una statement única y una función incorporada, pero el tiempo parece mostrar lo contrario. Considere este pequeño ejemplo que se me ocurrió cuando estaba tratando de descubrir el método más rápido para usarlo en un bucle que se ejecuta continuamente en un objeto idle_add dividiendo un contador de segundos en un tiempo legible por humanos para actualizar una etiqueta de la barra de progreso.

 import timeit def test1(x,y, dropy): while x > 0: y -= dropy x -= 1 # the test minutes = (yx) / 60 seconds = (yx) % 60.0 def test2(x,y, dropy): while x > 0: y -= dropy x -= 1 # the test minutes, seconds = divmod((yx), 60) x = 55 # litte number, also number of tests y = 10000 # make y > x by factor of drop dropy = 7 # y is reduced this much each iteration, for variation print "division and modulus:", timeit.timeit( lambda: test1(x,y,dropy) ) print "divmod function:", timeit.timeit( lambda: test2(x,y,dropy) ) 

La función divmod incorporada parece increíblemente más lenta en comparación con el uso de la división simple y el módulo.

 division and modulus: 12.5737669468 divmod function: 17.2861430645 

Estas funciones son bastante compactas y solo utilizan Python 2.6 estándar y posteriores.

 def ddhhmmss(seconds): """Convert seconds to a time string "[[[DD:]HH:]MM:]SS". """ dhms = '' for scale in 86400, 3600, 60: result, seconds = divmod(seconds, scale) if dhms != '' or result > 0: dhms += '{0:02d}:'.format(result) dhms += '{0:02d}'.format(seconds) return dhms def seconds(dhms): """Convert a time string "[[[DD:]HH:]MM:]SS" to seconds. """ components = [int(i) for i in dhms.split(':')] pad = 4 - len(components) if pad < 0: raise ValueError('Too many components to match [[[DD:]HH:]MM:]SS') components = [0] * pad + components return sum(i * j for i, j in zip((86400, 3600, 60, 1), components)) 

Y aquí hay pruebas para ir con ellos. Estoy usando el paquete pytest como una forma sencilla de probar las excepciones.

 import ddhhmmss import pytest def test_ddhhmmss(): assert ddhhmmss.ddhhmmss(0) == '00' assert ddhhmmss.ddhhmmss(2) == '02' assert ddhhmmss.ddhhmmss(12 * 60) == '12:00' assert ddhhmmss.ddhhmmss(3600) == '01:00:00' assert ddhhmmss.ddhhmmss(10 * 86400) == '10:00:00:00' assert ddhhmmss.ddhhmmss(86400 + 5 * 3600 + 30 * 60 + 1) == '01:05:30:01' assert ddhhmmss.ddhhmmss(365 * 86400) == '365:00:00:00' def test_seconds(): assert ddhhmmss.seconds('00') == 0 assert ddhhmmss.seconds('02') == 2 assert ddhhmmss.seconds('12:00') == 12 * 60 assert ddhhmmss.seconds('01:00:00') == 3600 assert ddhhmmss.seconds('1:0:0') == 3600 assert ddhhmmss.seconds('3600') == 3600 assert ddhhmmss.seconds('60:0') == 3600 assert ddhhmmss.seconds('10:00:00:00') == 10 * 86400 assert ddhhmmss.seconds('1:05:30:01') == 86400 + 5 * 3600 + 30 * 60 + 1 assert ddhhmmss.seconds('365:00:00:00') == 365 * 86400 def test_seconds_raises(): with pytest.raises(ValueError): ddhhmmss.seconds('') with pytest.raises(ValueError): ddhhmmss.seconds('foo') with pytest.raises(ValueError): ddhhmmss.seconds('1:00:00:00:00') 

Hágalo de otra manera restando los segundos según sea necesario, y no lo llame tiempo; hay un paquete con ese nombre

 def sec_to_time(): sec = int( input ('Enter the number of seconds:'.strip()) ) days = sec / 86400 sec -= 86400*days hrs = sec / 3600 sec -= 3600*hrs mins = sec / 60 sec -= 60*mins print days, ':', hrs, ':', mins, ':', sec 

Parcheando la respuesta del Sr. B (lo siento, no hay suficiente repetición para comentar), podemos devolver la granularidad variable según la cantidad de tiempo. Por ejemplo, no decimos “1 semana, 5 segundos”, solo decimos “1 semana”:

 def display_time(seconds, granularity=2): result = [] for name, count in intervals: value = seconds // count if value: seconds -= value * count if value == 1: name = name.rstrip('s') result.append("{} {}".format(value, name)) else: # Add a blank if we're in the middle of other values if len(result) > 0: result.append(None) return ', '.join([x for x in result[:granularity] if x is not None]) 

Algunos ejemplos de entrada:

 for diff in [5, 67, 3600, 3605, 3667, 24*60*60, 24*60*60+5, 24*60*60+57, 24*60*60+3600, 24*60*60+3667, 2*24*60*60, 2*24*60*60+5*60*60, 7*24*60*60, 7*24*60*60 + 24*60*60]: print "For %d seconds: %s" % (diff, display_time(diff, 2)) 

… devuelve esta salida:

 For 5 seconds: 5 seconds For 67 seconds: 1 minute, 7 seconds For 3600 seconds: 1 hour For 3605 seconds: 1 hour For 3667 seconds: 1 hour, 1 minute For 86400 seconds: 1 day For 86405 seconds: 1 day For 86457 seconds: 1 day For 90000 seconds: 1 day, 1 hour For 90067 seconds: 1 day, 1 hour For 172800 seconds: 2 days For 190800 seconds: 2 days, 5 hours For 604800 seconds: 1 week For 691200 seconds: 1 week, 1 day 

La respuesta “timeit” anterior que declara que divmod es más lenta tiene una lógica gravemente defectuosa.

Test1 llama a los operadores.

Test2 llama a la función divmod, y llamar a una función tiene una sobrecarga.

Una forma más precisa de probar sería:

 import timeit def moddiv(a,b): q= a/b r= a%b return q,r a=10 b=3 md=0 dm=0 for i in range(1,10): c=a*i md+= timeit.timeit( lambda: moddiv(c,b)) dm+=timeit.timeit( lambda: divmod(c,b)) print("moddiv ", md) print("divmod ", dm) moddiv 5.806157339000492 divmod 4.322451676005585 

divmod es más rápido.

Aunque se mencionó divmod (), no vi lo que consideré un buen ejemplo. Aquí está el mío:

 q=972021.0000 # For example days = divmod(q, 86400) # days[0] = whole days and # days[1] = seconds remaining after those days hours = divmod(days[1], 3600) minutes = divmod(hours[1], 60) print "%i days, %i hours, %i minutes, %i seconds" % (days[0], hours[0], minutes[0], minutes[1]) 

Qué salidas:

 11 days, 6 hours, 0 minutes, 21 seconds