python - parse - Convertir cadena en fecha y hora
python parse date (19)
Algo que no se menciona aquí y es útil: agregar un sufijo al día. Desacoplé la lógica del sufijo para que pueda usarlo para cualquier número que desee, no solo fechas.
import time
def num_suffix(n):
''''''
Returns the suffix for any given int
''''''
suf = (''th'',''st'', ''nd'', ''rd'')
n = abs(n) # wise guy
tens = int(str(n)[-2:])
units = n % 10
if tens > 10 and tens < 20:
return suf[0] # teens with ''th''
elif units <= 3:
return suf[units]
else:
return suf[0] # ''th''
def day_suffix(t):
''''''
Returns the suffix of the given struct_time day
''''''
return num_suffix(t.tm_mday)
# Examples
print num_suffix(123)
print num_suffix(3431)
print num_suffix(1234)
print ''''
print day_suffix(time.strptime("1 Dec 00", "%d %b %y"))
print day_suffix(time.strptime("2 Nov 01", "%d %b %y"))
print day_suffix(time.strptime("3 Oct 02", "%d %b %y"))
print day_suffix(time.strptime("4 Sep 03", "%d %b %y"))
print day_suffix(time.strptime("13 Nov 90", "%d %b %y"))
print day_suffix(time.strptime("14 Oct 10", "%d %b %y"))
Corto y sencillo. Tengo una enorme lista de fechas y fechas como estas:
Jun 1 2005 1:33PM
Aug 28 1999 12:00AM
Voy a volver a colocarlos en campos de fecha y hora apropiados en una base de datos, así que necesito hacerles magia en objetos de fecha y hora reales.
Cualquier ayuda (incluso si es solo una patada en la dirección correcta) sería apreciada.
Edición: Esto está pasando por el ORM de Django, por lo que no puedo usar SQL para hacer la conversión al insertar.
Aquí hay dos soluciones que usan Pandas para convertir fechas formateadas como cadenas en objetos datetime.date.
import pandas as pd
dates = [''2015-12-25'', ''2015-12-26'']
# 1) Use a list comprehension.
>>> [d.date() for d in pd.to_datetime(dates)]
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]
# 2) Convert the dates to a DatetimeIndex and extract the python dates.
>>> pd.DatetimeIndex(dates).date.tolist()
[datetime.date(2015, 12, 25), datetime.date(2015, 12, 26)]
Tiempos
dates = pd.DatetimeIndex(start=''2000-1-1'', end=''2010-1-1'', freq=''d'').date.tolist()
>>> %timeit [d.date() for d in pd.to_datetime(dates)]
# 100 loops, best of 3: 3.11 ms per loop
>>> %timeit pd.DatetimeIndex(dates).date.tolist()
# 100 loops, best of 3: 6.85 ms per loop
Y aquí es cómo convertir los ejemplos de fecha y hora originales del OP:
datetimes = [''Jun 1 2005 1:33PM'', ''Aug 28 1999 12:00AM'']
>>> pd.to_datetime(datetimes).to_pydatetime().tolist()
[datetime.datetime(2005, 6, 1, 13, 33),
datetime.datetime(1999, 8, 28, 0, 0)]
Hay muchas opciones para convertir de cadenas a to_datetime
tiempo de Pandas usando to_datetime
, así que verifique los docs si necesita algo especial.
Del mismo modo, las marcas de tiempo tienen muchas propiedades y métodos a los que se puede acceder además de .date
Crea una pequeña función de utilidad como:
def date(datestr="", format="%Y-%m-%d"):
from datetime import datetime
if not datestr:
return datetime.today().date()
return datetime.strptime(datestr, format).date()
Esto es lo suficientemente versátil:
- Si no pasas ningún argumento volverá la fecha de hoy.
- Hay un formato de fecha como predeterminado que puede anular.
- Puede modificarlo fácilmente para devolver un datetime.
Ejemplo de objeto datetime Django Timezone.
import datetime
from django.utils.timezone import get_current_timezone
tz = get_current_timezone()
format = ''%b %d %Y %I:%M%p''
date_object = datetime.datetime.strptime(''Jun 1 2005 1:33PM'', format)
date_obj = tz.localize(date_object)
Esta conversión es muy importante para Django y Python cuando tienes USE_TZ = True
:
RuntimeWarning: DateTimeField MyModel.created received a naive datetime (2016-03-04 00:00:00) while time zone support is active.
El módulo de fecha y datetime Python es bueno para obtener los formatos de fecha y hora de fecha.
import datetime
new_date_format1 = datetime.datetime.strptime(''Jun 1 2005 1:33PM'', ''%b %d %Y %I:%M%p'')
new_date_format2 = datetime.datetime.strptime(''Jun 1 2005 1:33PM'', ''%b %d %Y %I:%M%p'').strftime(''%Y/%m/%d %I:%M%p'')
print new_date_format1
print new_date_format2
Salida:
2005-06-01 13:33:00
2005/06/01 01:33PM
He reunido un proyecto que puede convertir algunas expresiones realmente limpias. Echa un vistazo a timestring .
Aquí hay algunos ejemplos a continuación:
pip install timestring
>>> import timestring
>>> timestring.Date(''monday, aug 15th 2015 at 8:40 pm'')
<timestring.Date 2015-08-15 20:40:00 4491909392>
>>> timestring.Date(''monday, aug 15th 2015 at 8:40 pm'').date
datetime.datetime(2015, 8, 15, 20, 40)
>>> timestring.Range(''next week'')
<timestring.Range From 03/10/14 00:00:00 to 03/03/14 00:00:00 4496004880>
>>> (timestring.Range(''next week'').start.date, timestring.Range(''next week'').end.date)
(datetime.datetime(2014, 3, 10, 0, 0), datetime.datetime(2014, 3, 14, 0, 0))
Mira mi respuesta
En datos reales, este es un problema real: formatos de fecha múltiples, no coincidentes, incompletos, inconsistentes y multilenguaje / región, que a menudo se mezclan libremente en un conjunto de datos. No está bien que el código de producción falle, y mucho menos que salga feliz como un zorro.
Necesitamos probar ... capturar múltiples formatos de fecha y hora fmt1, fmt2, ..., fmtn y suprimir / manejar las excepciones (de strptime()
) para todos aquellos que no coincidan (y en particular, evitar la necesidad de un yukky n-deep sangrado Escalera de intencion ... cláusulas de captura). De mi solucion
def try_strptime(s, fmts=[''%d-%b-%y'',''%m/%d/%Y'']):
for fmt in fmts:
try:
return datetime.strptime(s, fmt)
except:
continue
return None # or reraise the ValueError if no format matched, if you prefer
Muchas marcas de tiempo tienen una zona horaria implícita. Para asegurarse de que su código funcione en cada zona horaria, debe usar UTC internamente y adjuntar una zona horaria cada vez que un objeto extraño ingrese al sistema.
Python 3.2+:
>>> datetime.datetime.strptime(
... "March 5, 2014, 20:13:50", "%B %d, %Y, %H:%M:%S"
... ).replace(tzinfo=datetime.timezone(datetime.timedelta(hours=-3)))
Personalmente, me gusta la solución utilizando el módulo de parser
, que es la segunda respuesta a esta pregunta y es hermosa, ya que no tienes que construir ningún literal de cadena para que funcione. Sin embargo, un inconveniente es que es 90% más lento que la respuesta aceptada con strptime
respuesta.
from dateutil import parser
from datetime import datetime
import timeit
def dt():
dt = parser.parse("Jun 1 2005 1:33PM")
def strptime():
datetime_object = datetime.strptime(''Jun 1 2005 1:33PM'', ''%b %d %Y %I:%M%p'')
print(timeit.timeit(stmt=dt, number=10**5))
print(timeit.timeit(stmt=strptime, number=10**5))
>10.70296801342902
>1.3627995655316933
Mientras no lo haga un millón de veces una y otra vez, sigo pensando que el método del parser
es más conveniente y manejará la mayoría de los formatos de tiempo automáticamente.
Puedes usar easy_date para hacerlo más fácil:
import date_converter
converted_date = date_converter.string_to_datetime(''Jun 1 2005 1:33PM'', ''%b %d %Y %I:%M%p'')
Recuerda esto y no necesitas volver a confundirte en la conversión de fecha y hora.
Cadena al objeto datetime = strptime
Objeto datetime a otros formatos = strftime
Jun 1 2005 1:33PM
es igual a
%b %d %Y %I:%M%p
% b Mes como nombre abreviado de la localidad (junio)
% d Día del mes como un número decimal rellenado con cero (1)
% Y Año con siglo como número decimal (2015)
% I hora (reloj de 12 horas) como un número decimal sin relleno (01)
% M minuto como un número decimal rellenado con cero (33)
El equivalente de% p Locale de AM o PM (PM)
por lo que necesita strptime es decir, convertir la string
a
>>> dates = []
>>> dates.append(''Jun 1 2005 1:33PM'')
>>> dates.append(''Aug 28 1999 12:00AM'')
>>> from datetime import datetime
>>> for d in dates:
... date = datetime.strptime(d, ''%b %d %Y %I:%M%p'')
... print type(date)
... print date
...
Salida
<type ''datetime.datetime''>
2005-06-01 13:33:00
<type ''datetime.datetime''>
1999-08-28 00:00:00
¿Qué pasa si tienes un formato diferente de fechas puedes usar panda o dateutil.parse?
>>> import dateutil
>>> dates = []
>>> dates.append(''12 1 2017'')
>>> dates.append(''1 1 2017'')
>>> dates.append(''1 12 2017'')
>>> dates.append(''June 1 2017 1:30:00AM'')
>>> [parser.parse(x) for x in dates]
Salida
[datetime.datetime(2017, 12, 1, 0, 0), datetime.datetime(2017, 1, 1, 0, 0), datetime.datetime(2017, 1, 12, 0, 0), datetime.datetime(2017, 6, 1, 1, 30)]
Sería útil para convertir la cadena a datetime y también con la zona horaria
def convert_string_to_time(date_string, timezone):
from datetime import datetime
import pytz
date_time_obj = datetime.strptime(date_string[:26], ''%Y-%m-%d %H:%M:%S.%f'')
date_time_obj_timezone = pytz.timezone(timezone).localize(date_time_obj)
return date_time_obj_timezone
date = ''2018-08-14 13:09:24.543953+00:00''
TIME_ZONE = ''UTC''
date_time_obj_timezone = convert_string_to_time(date, TIME_ZONE)
Si solo desea el formato de fecha, puede convertirlo manualmente pasando sus campos individuales como:
>>> import datetime
>>> date = datetime.date(int(''2017''),int(''12''),int(''21''))
>>> date
datetime.date(2017, 12, 21)
>>> type(date)
<type ''datetime.date''>
Puede pasar sus valores de cadena dividida para convertirlos en un tipo de fecha como:
selected_month_rec = ''2017-09-01''
date_formate = datetime.date(int(selected_month_rec.split(''-'')[0]),int(selected_month_rec.split(''-'')[1]),int(selected_month_rec.split(''-'')[2]))
Obtendrá el valor resultante en formato de fecha.
Utilice la biblioteca de dateutil terceros:
from dateutil import parser
dt = parser.parse("Aug 28 1999 12:00AM")
Puede manejar la mayoría de los formatos de fecha, incluido el que necesita analizar. Es más conveniente que strptime, ya que puede adivinar el formato correcto la mayor parte del tiempo.
Es muy útil para escribir pruebas, donde la legibilidad es más importante que el rendimiento.
Puedes instalarlo con:
pip install python-dateutil
datetime.strptime
es la rutina principal para analizar cadenas en tiempos de datos. Puede manejar todo tipo de formatos, con el formato determinado por una cadena de formato que le des:
from datetime import datetime
datetime_object = datetime.strptime(''Jun 1 2005 1:33PM'', ''%b %d %Y %I:%M%p'')
El objeto datetime
resultante es timezone-naive.
Campo de golf:
Documentación de Python para cadenas de formato
strptime
/strftime
: Python 2 , Python 3strftime.org es también una muy buena referencia para strftime
Notas:
-
strptime
= "tiempo de análisis de cadena" -
strftime
= "tiempo de formato de cadena" - Pronuncialo en voz alta hoy y no tendrás que buscarlo nuevamente en 6 meses.
arrow ofrece muchas funciones útiles para fechas y horas. Este bit de código proporciona una respuesta a la pregunta y muestra que la flecha también es capaz de formatear fechas fácilmente y mostrar información de otras configuraciones regionales.
>>> import arrow
>>> dateStrings = [ ''Jun 1 2005 1:33PM'', ''Aug 28 1999 12:00AM'' ]
>>> for dateString in dateStrings:
... dateString
... arrow.get(dateString.replace('' '','' ''), ''MMM D YYYY H:mmA'').datetime
... arrow.get(dateString.replace('' '','' ''), ''MMM D YYYY H:mmA'').format(''ddd, Do MMM YYYY HH:mm'')
... arrow.get(dateString.replace('' '','' ''), ''MMM D YYYY H:mmA'').humanize(locale=''de'')
...
''Jun 1 2005 1:33PM''
datetime.datetime(2005, 6, 1, 13, 33, tzinfo=tzutc())
''Wed, 1st Jun 2005 13:33''
''vor 11 Jahren''
''Aug 28 1999 12:00AM''
datetime.datetime(1999, 8, 28, 0, 0, tzinfo=tzutc())
''Sat, 28th Aug 1999 00:00''
''vor 17 Jahren''
Consulte http://arrow.readthedocs.io/en/latest/ para obtener más información.
para el formato unix / mysql 2018-10-15 20:59:29
from datetime import datetime
datetime_object = datetime.strptime(''2018-10-15 20:59:29'', ''%Y-%m-%d %H:%M:%S'')
In [34]: import datetime
In [35]: _now = datetime.datetime.now()
In [36]: _now
Out[36]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)
In [37]: print _now
2016-01-19 09:47:00.432000
In [38]: _parsed = datetime.datetime.strptime(str(_now),"%Y-%m-%d %H:%M:%S.%f")
In [39]: _parsed
Out[39]: datetime.datetime(2016, 1, 19, 9, 47, 0, 432000)
In [40]: assert _now == _parsed