Tiempo de redondeo en Python

¿Cuál sería una forma elegante, eficiente y Pythonic para realizar operaciones de redondeo ah / m / s en tipos relacionados con el tiempo en Python con control sobre la resolución de redondeo?

Mi conjetura es que requeriría una operación de módulo de tiempo. Ejemplos ilustrativos:

  • 20:11:13% (10 segundos) => (3 segundos)
  • 20:11:13% (10 minutos) => (1 minutos y 13 segundos)

Tipos relevantes relacionados con el tiempo que se me ocurren:

  • datetime.datetime \ datetime.time
  • struct_time

¿Qué hay de usar datetime.timedelta s:

 import time import datetime as dt hms=dt.timedelta(hours=20,minutes=11,seconds=13) resolution=dt.timedelta(seconds=10) print(dt.timedelta(seconds=hms.seconds%resolution.seconds)) # 0:00:03 resolution=dt.timedelta(minutes=10) print(dt.timedelta(seconds=hms.seconds%resolution.seconds)) # 0:01:13 

Para un redondeo de datetime.datetime, vea esta función: https://stackoverflow.com/a/10854034/1431079

Muestra de uso:

 print roundTime(datetime.datetime(2012,12,31,23,44,59,1234),roundTo=60*60) 2013-01-01 00:00:00 

Creo que convertiría el tiempo en segundos y utilizaría la operación de módulo estándar desde ese punto.

20:11:13 = 20*3600 + 11*60 + 13 = 72673 segundos

72673 % 10 = 3

72673 % (10*60) = 73

Esta es la solución más fácil en la que puedo pensar.

Puedes convertir ambas veces a segundos, hacer el modulo operati

 from datetime import time def time2seconds(t): return t.hour*60*60+t.minute*60+t.second def seconds2time(t): n, seconds = divmod(t, 60) hours, minutes = divmod(n, 60) return time(hours, minutes, seconds) def timemod(a, k): a = time2seconds(a) k = time2seconds(k) res = a % k return seconds2time(res) print(timemod(time(20, 11, 13), time(0,0,10))) print(timemod(time(20, 11, 13), time(0,10,0))) 

Salidas:

 00:00:03 00:01:13 

Esto redondeará los datos de tiempo a una resolución como se pregunta en la pregunta:

 import datetime as dt current = dt.datetime.now() current_td = dt.timedelta(hours=current.hour, minutes=current.minute, seconds=current.second, microseconds=current.microsecond) # to seconds resolution to_sec = dt.timedelta(seconds=round(current_td.total_seconds())) print dt.datetime.combine(current,dt.time(0))+to_sec # to minute resolution to_min = dt.timedelta(minutes=round(current_td.total_seconds()/60)) print dt.datetime.combine(current,dt.time(0))+to_min # to hour resolution to_hour = dt.timedelta(hours=round(current_td.total_seconds()/3600)) print dt.datetime.combine(current,dt.time(0))+to_hour 

Uso el siguiente fragmento de código para redondear a la siguiente hora:

 import datetime as dt tNow = dt.datetime.now() # round to the next full hour tNow -= dt.timedelta(minutes = tNow.minute, seconds = tNow.second, microseconds = tNow.microsecond) tNow += dt.timedelta(hours = 1) 

Aquí hay una versión con pérdida * del redondeo horario:

 dt = datetime.datetime now = dt.utcnow() rounded = dt.utcfromtimestamp(round(now.timestamp() / 3600, 0) * 3600) 

El mismo principio se puede aplicar a diferentes períodos de tiempo.

* El método anterior supone que se usa UTC, ya que cualquier información de la zona horaria se destruirá en la conversión a la marca de tiempo.

 def round_dt_to_seconds(dt): datetime.timedelta(seconds=dt.seconds)