convertir - string to datetime python3
Formato Python timedelta a cadena (21)
Aquí hay una función de propósito general para convertir un objeto timedelta
o un número regular (en forma de segundos o minutos, etc.) a una cadena con un formato agradable. Tomé la fantástica respuesta de mpounsett en una pregunta duplicada, la hice un poco más flexible, mejoré la legibilidad y añadí documentación.
Encontrarás que es la respuesta más flexible aquí hasta ahora, ya que te permite:
- Personalice el formato de cadena sobre la marcha en lugar de que esté codificado.
- Deje de lado ciertos intervalos de tiempo sin problemas (vea los ejemplos a continuación).
Función:
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)
Manifestación:
>>> 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
Soy un novato de Python (2 semanas) y tengo problemas para formatear un objeto datetime.timedelta
.
Esto es lo que estoy tratando de hacer: tengo una lista de objetos y uno de los miembros de la clase del objeto es un objeto timedelta que muestra la duración de un evento. Me gustaría mostrar esa duración en el formato de horas: minutos.
He intentado una variedad de métodos para hacer esto y estoy teniendo dificultades. Mi enfoque actual es agregar métodos a la clase para mis objetos que devuelven horas y minutos. Puedo obtener las horas al dividir los segundos de timedelta por 3600 y redondearlo. Estoy teniendo problemas para obtener los segundos restantes y convertir eso en minutos.
Por cierto, estoy usando Google AppEngine
con Django Templates
para su presentación.
Si alguien puede ayudar o sabe de una mejor manera de resolver esto, sería muy feliz.
Gracias,
Como sabe, puede obtener los segundos de un objeto timedelta accediendo al atributo .seconds
.
Python proporciona la función incorporada divmod()
que permite:
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
o puede convertir a horas y al resto utilizando una combinación de módulo y resta:
# 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
Compruebe esta función: convierte el objeto timedelta en la cadena ''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)
Consideraría seriamente el enfoque de Occam''s Razor aquí:
td = str(timedelta).split(''.'')[0]
Esto devuelve una cadena sin los microsegundos
Si desea regenerar el objeto datetime.timedelta, simplemente haga esto:
h,m,s = re.split('':'', td)
new_delta = datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s))
2 años en, me encanta este idioma!
El interrogador quiere un formato mejor que el típico:
>>> 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''
Entonces, realmente hay dos formatos, uno donde los días son 0 y se omite, y otro donde hay texto "n días, h: m: s". Pero, los segundos pueden tener fracciones y no hay ceros iniciales en las impresiones, por lo que las columnas están desordenadas.
Aquí está mi rutina, si te gusta:
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
esto devuelve la salida como formato dd: hh: mm: ss:
00:00:00:15
00:00:00:19
02:01:31:40
02:01:32:22
Pensé en agregar años a esto, pero esto queda como un ejercicio para el lector, ya que la salida es segura a más de 1 año:
>>> str(datetime.timedelta(seconds=99999999))
''1157 days, 9:46:39''
Gracias a todos por su ayuda. Tomé muchas de tus ideas y las puse juntas, déjame saber lo que piensas.
Agregué dos métodos a la clase como este:
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
En mi django usé esto (la suma es el objeto y está en un diccionario):
<td>{{ sum.0 }}</td>
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>
Mis objetos datetime.timedelta
fueron más de un día. Así que aquí hay un problema más. Toda la discusión anterior supone menos de un día. Un timedelta
es en realidad una tupla de días, segundos y microsegundos. La discusión anterior debe usar td.seconds
como lo hizo joe, pero si tiene días, NO se incluye en el valor de segundos.
Estoy obteniendo un lapso de tiempo entre 2 fechas y días y horas de impresión.
span = currentdt - previousdt
print ''%d,%d/n'' % (span.days,span.seconds/3600)
Personalmente uso la biblioteca humanize
para esto:
>>> 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''
Por supuesto, no le da exactamente la respuesta que estaba buscando (que es, de hecho, str(timeA - timeB)
, pero descubrí que una vez que ha pasado más de unas pocas horas, la pantalla se vuelve rápidamente ilegible. soporte para valores mucho más grandes que son legibles por humanos, y también están bien localizados.
Está inspirado en el módulo contrib.humanize
de Django, al parecer, así que ya que estás usando Django, probablemente deberías usar eso.
Sé que esta es una antigua pregunta respondida, pero uso datetime.utcfromtimestamp()
para esto. Toma la cantidad de segundos y devuelve una datetime
y datetime
que se puede formatear como cualquier otra datetime
y datetime
.
duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime(''%H:%M'')
Mientras permanezca en los rangos legales durante el tiempo que deben funcionar, es decir, no devuelve 1234: 35, ya que las horas son <= 23.
Si ya tiene un obj timedelta, simplemente convierta ese obj en una cadena. Quite los últimos 3 caracteres de la cadena e imprima. Esto truncará la parte de segundos e imprimirá el resto en el formato Horas: Minutos.
t = str(timedeltaobj)
print t[:-3]
Siguiendo el ejemplo del valor de Joe anterior, usaría el operador aritmético de módulo, así:
td = datetime.timedelta(hours=10.56)
td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)
Tenga en cuenta que la división de enteros en Python se redondea de forma predeterminada; Si desea ser más explícito, use math.floor () o math.ceil () según corresponda.
Simplemente puede convertir el timedelta en una cadena con str (). Aquí hay un ejemplo:
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
Tuve un problema similar con el resultado del cálculo de horas extra en el trabajo. El valor siempre debe aparecer en HH: MM, incluso cuando es mayor que un día y el valor puede ser negativo. Combiné algunas de las soluciones mostradas y tal vez alguien más encuentre útil esta solución. Me di cuenta de que si el valor de timedelta es negativo, la mayoría de las soluciones que se muestran con el método divmod no funcionan de manera inmediata:
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 a HH: MM cadena:
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''
Ya tiene un objeto timedelta, ¿por qué no usar su método integrado total_seconds () para convertirlo en segundos, luego usar divmod () para obtener horas y minutos?
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)
Esto funciona independientemente de si el delta del tiempo tiene días o años pares.
humanfriendly
biblioteca Python humanfriendly
el humanfriendly
para hacer esto, funciona muy bien.
import humanfriendly
from datetime import timedelta
delta = timedelta(seconds = 321)
humanfriendly.format_timespan(delta)
''5 minutes and 21 seconds''
Disponible en https://pypi.org/project/humanfriendly/
>>> 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
Pasar el objeto timedelta
a la función str()
llama al mismo código de formato que usamos si simplemente print td
. Como no desea los segundos, podemos dividir la cadena por dos puntos (3 partes) y volver a unirlos solo con las 2 primeras partes.
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
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)
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)
Esto producirá:
>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
''10 years 10 days 8 hours 20 minutes''
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime(''%H:%M''))
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)
Así que para
StartTime = ''15:28:53 21-07-13''
EndTime = ''15:32:40 21-07-13''
devoluciones:
''0:03:47''