Convertir cadenas a fecha y hora en Python

Introducción

Los datos se pueden representar de varias formas, y una forma conveniente de representar fechas y horas es instrumentos de cuerda. Sin embargo, para trabajar con estas fechas y horas de forma aritmética (como calcular diferencias de tiempo, agregar o quitar tiempo, etc.), debemos convertirlas en un datetime objeto.

Una de las fuentes más comunes de fechas y horas con formato de cadena son API REST que devuelven cadenas agnósticas, que luego podemos convertir a otros formatos.

Además, las zonas horarias son un dolor de cabeza común cuando se trata de trabajar con objetos de fecha y hora, por lo que también tendremos que pensar en eso al convertir.

En esta guía, veremos cómo convertir una cadena de fecha/hora en una datetime objeto en Python, usando el incorporado datetime módulo, pero también módulos de terceros como dateutil, arrow y Maya, teniendo en cuenta las zonas horarias.

Conversión de cadenas usando fecha y hora

El datetime consta de tres tipos de objetos diferentes: date, timey datetime. date el objeto contiene la fecha, time mantiene el tiempo, y datetime tiene fecha y hora!

import datetime
print(f'Current date/time: {datetime.datetime.now()}')

Ejecutar este código daría como resultado:

Current date/time: 2022-12-01 10:27:03.929149

Cuando no se proporciona un formato personalizado, se usa el formato de cadena predeterminado, es decir, el formato para "2022-12-01 10:27:03.929149" está en ISO 8601 formato (AAAA-MM-DDTHH:MM:SS.mmmmmm). Si nuestra cadena de entrada para crear un datetime el objeto está en el mismo formato ISO 8601 o si conoce el formato que recibirá por adelantado, podemos analizarlo fácilmente en un datetime :

import datetime

date_time_str = '2022-12-01 10:27:03.929149'

date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

Ejecutarlo imprimirá la fecha, hora y fecha-hora:

Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149

Aquí, usamos el strptime() método, que acepta dos argumentos:

  • La fecha con formato de cadena
  • El formato del primer argumento.

Especificar el formato de esta manera hace que el análisis sea mucho más rápido ya que datetime no necesita intentar interpretar el formato por sí mismo, lo cual es mucho más costoso computacionalmente. El valor de retorno es del tipo datetime.

En nuestro ejemplo, "2022-12-01 10:27:03.929149" es la cadena de entrada y "%Y-%m-%d %H:%M:%S.%f" es el formato de nuestra cadena de fecha. El retorno datetime el valor se almacena como date_time_obj.

Ya que este es un datetime objeto, podemos llamar al date() y time() métodos directamente en él. Como puede ver en la salida, ¡imprime la parte de 'fecha' y 'hora' de la cadena de entrada!

Fichas de formato

Vale la pena tomarse un momento para entender fichas de formato - La "%Y-%m-%d %H:%M:%S.%f" desde antes.

Cada token representa una parte diferente de la fecha y hora, como día, mes, año, día del mes o semana, etc. lista de fichas admitidas es lo suficientemente extenso como para permitir varios formatos. Algunos de los más utilizados, que también hemos utilizado anteriormente, son:

  • %Y: Año (4 dígitos)
  • %m: Mes
  • %d: Dia del mes
  • %H: Hora (24 horas)
  • %M: Minutos
  • %S: Segundos
  • %f: Microsegundos

Nota: Se espera que todos estos tokens, excepto el año, se rellenen con ceros (es decir, agosto es el octavo mes y se rellena con ceros para 08).

Uso de tokens de formato strptime () para convertir cadenas a diferentes formatos de fecha y hora

Si se conoce el formato de una cadena, se puede analizar fácilmente a un datetime objeto usando strptime(). Echemos un vistazo a un ejemplo no trivial que se traduce de un formato a otro:

import datetime

date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

La cadena de entrada tenía un formato: "17 de julio de 2022 9:20 a. m.". Conociendo este formato, mapeamos los elementos constituyentes al formato ISO 8601 y lo convertimos a un datetime :

Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00

Aquí hay una breve lista de fechas y horas comunes con formato de cadena y sus formatos correspondientes para strptime():

"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"

Puede analizar una cadena de fecha y hora de cualquier formato, siempre que use la cadena correcta de tokens de formato para la entrada que está recibiendo.

Convertir cadena a fecha y hora con zonas horarias

El manejo de fechas y horas se vuelve más complejo cuando se trata de zonas horarias. Todos los ejemplos anteriores hasta ahora son ingenuos para la zona horaria. Estos son conocidos como objetos ingenuos de fecha y hora.

Sin embargo, a pesar de la datetime los objetos contienen un campo exactamente para almacenar datos relacionados con la zona horaria – tzinfo:

import datetime as dt
dtime = dt.datetime.now()

print(dtime) 
print(dtime.tzinfo) 

El tzinfo campo está destinado a ser un datetime.timezone objeto, que denota la información de la zona horaria. Es None de forma predeterminada, e indica que el objeto de fecha y hora es ingenuo de zona horaria. Una biblioteca externa muy común para manejar zonas horarias es pytz. Puedes configurar PyTz objetos como el tzinfo campo también.

Si aún no lo tiene, instálelo a través de:

$ pip install pytz

Usando PyTz, podemos crear un ancla para fechas y horas conscientes de la zona horaria, como UTC:

import datetime as dt
import pytz

dtime = dt.datetime.now(pytz.utc)

print(dtime)
print(dtime.tzinfo)

Salida:

2022-12-01 02:07:41.960920+00:00
UTC

Ya no son las 11 a. m., sino las 2 a. m., ¡porque hemos atrasado la zona horaria unas horas! Este cambia la zona horaria de la fecha y hora.

+00:00 es la diferencia entre la hora mostrada y la hora UTC como ancla de coordinación global. Hemos configurado la hora para que esté en UTC, por lo que el desplazamiento es 00:00. Esta es una objeto consciente de la zona horaria.

Del mismo modo, podemos cambiar la interpretación de la misma fecha y hora entre zonas horarias. Convirtamos una cadena, como "2022-06-29 17:08:00" en una fecha y hora y luego localizar a la zona horaria "América/Nueva_York":

import datetime as dt
import pytz

date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')

timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)

print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)

Nota: aplicaciones móviles convierte una fecha y hora ingenua de la zona horaria en una fecha y hora consciente de la zona horaria y trata la zona horaria como la local. Por lo tanto, la la fecha y hora permanece igual, pero dada la zona horaria diferente, ya no representa el mismo punto en el tiempo sin límites de zonas horarias.

obtenemos lo mismo valor de fecha y hora, compensado por -04: 00 en comparación con la hora UTC:

2022-06-29 17:08:00-04:00
America/New_York

17:08 en Tokio no va el mismo punto en el tiempo que las 17:08 en Nueva York. 17:08 en Tokio son 3:08 en Nueva York.

¿Cómo encontrar todos los códigos/alias de zona horaria?

Para encontrar todas las zonas horarias disponibles, inspeccione el all_timezones campo, que es una lista de todas las zonas horarias disponibles:

print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
   print(time_zone)

Consulte nuestra guía práctica y práctica para aprender Git, con las mejores prácticas, los estándares aceptados por la industria y la hoja de trucos incluida. Deja de buscar en Google los comandos de Git y, de hecho, aprenden ella!

There are 594 timezones in PyTz

Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...

Cambiar la zona horaria de Datetime

Podemos convertir la zona horaria de un timezone-aware datetime objeto de una región a otra, en lugar de localizar una fecha y hora ingenua de zona horaria a través de la lente de alguna zona horaria.

Esto es diferente de la localización, ya que la localización representa un punto diferente en el tiempo, pero convertir la zona horaria de un objeto representa el mismo punto en el tiempo, a través de una lente diferente:

import datetime as dt
import pytz

timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)

timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)


print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)

Primero, creamos un objeto de fecha y hora con la hora actual y lo configuramos como la zona horaria "América/Nueva_York". Luego usando el astimezone() método, hemos convertido este datetime a la zona horaria “Europa/Londres”. Ambos datetimes imprimirá diferentes valores, utilizando el desplazamiento UTC como enlace de referencia entre ellos:

America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00

2:24 del día siguiente en Londres is el mismo momento que las 21:24 del día anterior en Nueva York ya que Londres está 5 horas por delante.

Como era de esperar, las fechas y horas son diferentes ya que tienen una diferencia de aproximadamente 5 horas.

Convertir cadena a fecha y hora usando bibliotecas de terceros

Python datetime módulo puede convertir todos los diferentes tipos de cadenas a un datetime objeto. Pero el problema principal es que, para hacer esto, debe crear la cadena de código de formato adecuada que strptime() puede entender. Crear esta cadena lleva tiempo y hace que el código sea más difícil de leer.

En su lugar, podemos usar otras bibliotecas de terceros para hacerlo más fácil.

En algunos casos, estas bibliotecas de terceros también tienen un mejor soporte integrado para manipular y comparar fechas y horas, y algunas incluso tienen zonas horarias integradas, por lo que no necesita incluir un paquete PyTz adicional.

Echemos un vistazo a algunas de estas bibliotecas en las siguientes secciones.

Convertir cadena a fecha y hora con dateutil

El módulo dateutil es una extensión de la datetime módulo. ¡Una ventaja es que no necesitamos pasar ningún código de análisis para analizar una cadena!

Para convertir automáticamente una cadena a fecha y hora sin un token de formato usando Python dateutil:

from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')

print(datetime)

Este parse ¡La función analizará la cadena automáticamente! No tiene que incluir ninguna cadena de formato. Intentemos analizar diferentes tipos de cadenas usando dateutil:

from dateutil.parser import parse

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = parse(date)
    print(dt.date())
    print(dt.time())
    print(dt.tzinfo)
    print('n')

Salida:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None

Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None

Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None

Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None

Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None

Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None

Puede ver que casi cualquier tipo de cadena se puede analizar fácilmente usando el dateutil módulo.

Si bien esto es conveniente, recuerde que tener que predecir el formato hace que el código sea mucho más lento, por lo que si su código requiere un alto rendimiento, es posible que este no sea el enfoque adecuado para su aplicación.

Convertir cadena a fecha y hora con maya

Maya también hace que sea muy fácil analizar una cadena y cambiar las zonas horarias. Para convertir fácilmente una cadena con Maya de Python:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Salida:

2018-04-29
17:45:25
UTC

Para convertir la hora a una zona horaria diferente:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Salida:

2018-04-29
13:45:25
America/New_York

Ahora, ¿no es tan fácil de usar? vamos a probar maya con el mismo conjunto de cuerdas que hemos usado con dateutil:

import maya

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = maya.parse(date).datetime()
    print(dt)
    
    
    
    

Salida:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00

Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00

Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00

Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00

Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00

Como puede ver, ¡todos los formatos de fecha se analizaron con éxito!

Si no proporcionamos la información de la zona horaria, la convierte automáticamente a UTC. Por lo tanto, es importante tener en cuenta que nosotros debe proporcionar la to_timezone y naive parámetros si la hora no está en UTC.

Convertir cadena a fecha y hora con flecha

flecha es otra biblioteca para tratar con fecha y hora en Python. Y como antes con maya, también calcula el formato de fecha y hora automáticamente. Una vez interpretado, devuelve un Python datetime objeto del arrow objeto.

Para convertir fácilmente una cadena a fecha y hora usando Python arrow:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Salida:

2018-04-29
17:45:25
tzutc()

Y así es como puedes usar arrow para convertir zonas horarias usando el to() método:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())

Salida:

2018-04-29T13:45:25-04:00
2018-04-29
13:45:25

Como puede ver, la cadena de fecha y hora se convierte a la región "América/Nueva_York".

Ahora, usemos nuevamente el mismo conjunto de cadenas que hemos usado anteriormente:

import arrow

date_array = [
    '2018-06-29 08:15:27.243860',
    
    
    
    
    
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    
]

for date in date_array:
    dt = arrow.get(date)
    print('Parsing: ' + date)
    print(dt)
    
    
    
    

Este código fallará para las cadenas de fecha y hora que se han comentado, que es más de la mitad de nuestros ejemplos. La salida para otras cadenas será:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00

Para analizar correctamente las cadenas de fecha y hora que están comentadas, deberá pasar el correspondiente fichas de formato para dar pistas a la biblioteca sobre cómo analizarlo.

Conclusión

En este artículo hemos mostrado diferentes formas de analizar una cadena a un datetime objeto en Python. Puede optar por el Python predeterminado datetime library o cualquiera de las bibliotecas de terceros mencionadas en este artículo, entre muchas otras.

El principal problema con el valor predeterminado datetime paquete es que necesitamos especificar el código de análisis manualmente para casi todos los formatos de cadena de fecha y hora. Por lo tanto, si su formato de cadena cambia en el futuro, es probable que también tenga que cambiar su código. Pero muchas bibliotecas de terceros, como las mencionadas aquí, lo manejan automáticamente.

Otro problema al que nos enfrentamos es el manejo de las zonas horarias. La mejor manera de manejarlos siempre es almacenar la hora en su base de datos en formato UTC y luego convertirla a la zona horaria local del usuario cuando sea necesario.

Estas bibliotecas no solo son buenas para analizar cadenas, sino que también se pueden usar para muchos tipos diferentes de operaciones relacionadas con la fecha y la hora. Le animo a que revise los documentos para conocer las funcionalidades en detalle.

Sello de tiempo:

Mas de Abuso de pila