Tomemos un ejemplo concreto de fechas y horas para poder programar en Python y con el módulo datetime
: una compañía nos contrató para implementar su sistema de puntos, controlando cuándo llega y se va un empleado. El sistema debe mostrar la fecha y la hora en cada registro, como confirmación para el empleado.
Conocemos el módulo datetime de la biblioteca nativa de Python, por lo que incluso sabemos cómo obtener la fecha actual a través de la clase date, simplemente impórtelo y llame al método today ()
:
from datetime import date
fecha_actual = date.today()
print(fecha_actual)
Como esperado:
2020-9-1
Pero calma. ¡Sería bueno si pudiéramos imprimir la fecha en formato DD / MM / AAAA para evitar confusiones! El problema es que el date
fuerza automáticamente el estándar ANSI cada vez que intentamos imprimir.
Dado que la clase date
puede proporcionar cada sección de la fecha por separado, podemos resolver este problema con un formato de string:
fecha_en_texto = ‘{}/{}/{}’.format(fecha_actual.day, fecha_actual.month, fecha_actual.year)
Lo que resulta en:
1/9/2020
Mejor, pero todavía no es exactamente lo que queríamos. Tenga en cuenta que tanto el día como el mes no tienen el prefijo 0, lo que no está en el estándar deseado. En este caso, incluso podríamos evitar esto simplemente agregando un 0 antes:
fecha_en_texto = ‘0{}/0{}/{}’.format(fecha_actual.day, fecha_actual.month,fecha_actual.year)
Lo que funcionaría, pero causaría problemas si el día o mes fuera mayor o igual a 10:
010/010/2020
Para evitar más complicaciones, la clase de fecha resuelve esto con un único método: strftime ()
, que toma como parámetro el formato que queremos en nuestra string de fecha, por lo tanto, nos da más libertad para decidir cómo queremos mostrar la fecha.
Este formato utiliza códigos mejor explicados en la documentación. Al final del texto, también damos una breve explicación sobre ellos. En nuestro caso se ve así:
fecha_en_texto = fecha_actual.strftime(‘%d/%m/%Y’)
print(fecha_en_texto)
E asi:
01/09/2020
En el caso de nuestro ejemplo que resultó en 010/010/2020:
10/10/2020
Ahora solo necesitamos encontrar una manera de almacenar el tiempo también. ¿Quién puede encargarse de eso? Como habrás adivinado, el mismo módulo datetime
desde el que importamos la clase date
también tiene clases que facilitan la manipulación de los tiempos.
Si bien podemos usar el tipo time, destinado exclusivamente para tiempos, el módulo nos brinda una solución mucho más apropiada para nuestro problema con el tipo datetime: sí, tiene el mismo nombre que el módulo, ¡cuidado con la confusión!
Una de las ventajas de la clase datetime
es que puede manejar la fecha y la hora al mismo tiempo. La única diferencia en nuestro uso es que, en lugar del método today ()
, usaremos el método now ()
:
from datetime import datetime
fecha_y_hora_atuais = datetime.now()
fecha_y_hora_en_texto = fecha_y_hora_actuales.strftime(‘%d/%m/%Y’)
print(fecha_y_hora_en_texto)
El resultado es como el anterior:
01/09/2020
Aunque ya estamos usando la clase datetime
, que incorpora la hora, necesitamos declarar en el formato que pasamos como parámetro a strftime ()
que también queremos mostrar la hora y los minutos:
fecha_y_hora_en_texto = fecha_y_hora_actuales.strftime(‘%d/%m/%Y %H:%M’) print(fecha_y_hora_en_texto)
Y ahora si:
01/09/2020 12:30
¡Perfecto! Hasta ahora hemos aprendido a tomar la fecha actual con date
, datetime
y incluso hemos aprendido a formatear fechas, transformándolas en strings. ¿Pero y si tuviéramos que ir para otro lado?
Si tuviéramos una string de date y quisiéramos transformarla en datetime
, ¿qué haríamos? De nuevo, un método simple resuelve todo, esta vez strptime ()
, desde la misma clase datetime
:
from datetime import datetime
fecha_y_hora_em_texto = ‘01/09/2020 12:30’
fecha_y_hora = datetime.strptime(fecha_y_texto, ‘%d/%m/%Y %H:%M’)
Revisé la configuración de una de estas computadoras y descubrí que su reloj estaba en una zona horaria diferente a la de Bogotá, donde se encuentra la compañía.
No podemos dejar que el tiempo en nuestro programa dependa de cada máquina, porque no podemos garantizar que todas las máquinas que ejecutan este programa estén en la zona horaria que deseamos. Lo ideal, entonces, sería forzar la zona horaria para donde quieras.
A partir de Python 3, tenemos la clase timezone, también del módulo datetime
:
from datetime import datetime, timezone
fecha_y_hora_actuales = datetime.now()
zona_horaria = timezone()
print(zona_horaria)
Veamos qué se imprime en la pantalla:
Traceback (most recent call last):
File "teste.py", line 4, in >
fuso_horario = timezone()
TypeError: Required argument 'offset' (pos 1) not found
La excepción TypeError
que recibimos indica que no se encontró el argumento offset
, esperado en el constructor timezone. Realmente no hicimos ese argumento. Pero, ¿qué significa?
El parámetro offset
representa la diferencia entre la zona horaria que queremos crear y el tiempo universal coordinado (UTC). En nuestro caso, en Bogotá, tenemos una diferencia de -5 horas, mejor conocida como UTC-5. Sabiendo esto, intentemos nuevamente:
zona_horaria = timezone(-5)
print(zona_horaria)
Ahora que hemos configurado el parámetro de compensación, veamos qué aparece en la pantalla:
Traceback (most recent call last):
File "teste.py", line 4, in <module>
fuso_horario = timezone(-5)
TypeError: timezone() argument 1 must be datetime.timedelta, not int
Esta vez, el mensaje de excepción es diferente, lo que indica que el argumento pasado al constructor timezone debe ser del tipo datetime.timedelta
, no un entero, que es lo que pasamos.
La clase timedelta tiene el propósito de representar una duración y, en nuestro caso, una diferencia entre horarios. Ahora, ejemplifiquemos en una variable e intentemos imprimir, para ver qué sucede:
diferencia = timedelta()
print(diferencia)
Mira lo que apareció:
0:00:00
De acuerdo, 0 días, 0 horas y 0 minutos. Pero necesitamos que nuestro objeto timedelta
se corresponda con la diferencia UTC, a -5 horas:
diferencia = timedelta(-5)
print(diferencia)
¿Qué aparece ahora?
-5 days, 0:00:00
¿Que? -¿5 días? ¡Queríamos -5 horas! El problema es que el constructor timedelta recibe varios otros argumentos más allá de la hora, en ese orden:
Entonces, si solo le enviamos un -5, ese número se interpreta como si fuera en días. Podemos pasar 0 para los primeros 5 parámetros y -5 para las horas, pero esto es un poco extraño, teniendo en cuenta que, de hecho, solo queremos definir las horas.
Usando la funcionalidad de Python de parámetros con nombre, es posible especificar que estamos configurando el parámetro horas (hours), de la siguiente manera:
diferencia = timedelta(hours=-5)
print(diferencia)
Y ahora:
-1 day, 19:00:00
Bueno, si ponemos -5, ¿por qué apareció todo esto? Resulta que timedelta
entiende -5 horas como 0 días, 0 horas y 0 minutos - 5 horas, es decir, -1 día, 19 horas.
Ahora, creemos un objeto de zona horaria correspondiente a UTC-5, indicando esta diferencia con respecto a UTC como parámetro del constructor:
zona_horaria = timezone(diferencia)
print(zona_horaria)
Tenemos justo lo que queríamos:
UTC-05:00
Finalmente, podemos convertir el tiempo de la máquina al de Bogotá, utilizando el método astimezone ()
:
fecha_y_hora_bogota = fecha_y_hora_actuales.astimezone(zona_horario)
fecha_y_hora_bogota_en_texto = fecha_y_hora_bogota.strftime(‘%d/%m/%Y %H:%M’)
print(fecha_y_hora_bogota_en_texto)
Ahora todo está estandarizado:
01/09/2020 12:30
Ahora tenemos todo arreglado con la zona horaria, pero ¿y si le mostramos nuestro código a otro programador, él entendería lo que significa -5? ¿No es muy fácil, verdad?
De hecho, para cada zona horaria tendríamos que investigar cuál es su diferencia con UTC, que es un problema molesto. ¿No hay una manera más simple y elegante de resolver este problema?
La comunidad de Python, ante esta necesidad, creó varias bibliotecas para facilitar la manipulación de timezones,, como pytz. Para instalar pytz, puede usar pip desde la terminal:
pip install pytz
Es probable que la instalación en sistemas basados en UNIX requiera permiso sudo.
Una vez instalado, podemos importar su clase timezone
y es fácil obtener la zona horaria que queremos:
from datetime import datetime
from pytz import timezone
fecha_y_hora_actuales = datetime.now()
zona_horaria = timezone(‘America/Bogota’)
fecha_y_hora_bogota = fecha_y_hora_actualrs.astimezone(fuso_horario)
fecha_y_hora_bogota_en_texto = fecha_y_hora_bogota.strftime(‘%d/%m/%Y %H:%M’)
print(fecha_y_hora_bogota_en_texto)
Tenga en cuenta que ponemos el timezone
como América / Bogota. ¿Pero qué pasa si queremos conocer otras posibilidades, como Ciudad de México, São Paulo, Buenos Aires? Puede ver la lista de zonas horarias compatibles con pytz
iterando sobre pytz.all_timezones
:
import pytz
for tz in pytz.all_timezones:
print(tz)
¡Trabajar con fechas para nosotros ya no será un problema!
A lo largo de esta publicación, utilizamos varios códigos de formato de fecha, como el estándar %d/%m/%Y% H:%M. ¿Pero qué significa?
Estos códigos están definidos por la documentación del strftime (3). Los utilizados en nuestros ejemplos son:
Comenzamos la publicación con la necesidad de manipular las fechas con Python y vimos cómo hacerlo usando el tipo date
. Aprendimos cómo agregar nuestra fecha a una hora usando la clase datetime
, y cómo formatear esta información en un string que nos sea fácil de leer.
Terminamos teniendo un problema con la zona horaria y vimos cómo resolverlo con la clase timezone
en Python 3. También vimos una manera más simple de resolver este problema con la biblioteca pytz
, creada por la comunidad Python.
¿Qué tal aprender más sobre Python y sus diversos recursos? Entonces, ¡Mira nuestros cursos de Python para Data Science aquí en Alura!
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Cursos de Programación, Front End, Data Science, Innovación y Gestión.
Luri es nuestra inteligencia artificial que resuelve dudas, da ejemplos prácticos y ayuda a profundizar aún más durante las clases. Puedes conversar con Luri hasta 100 mensajes por semana
Paga en moneda local en los siguientes países
Puedes realizar el pago de tus planes en moneda local en los siguientes países:
País | |||||||
---|---|---|---|---|---|---|---|
Plan Semestral |
487.37
BOB |
68350.30
CLP |
308587.97
COP |
65.90
USD |
261.42
PEN |
1425.63
MXN |
3016.99
UYU |
Plan Anual |
738.82
BOB |
103614.50
CLP |
467798.76
COP |
99.90
USD |
396.30
PEN |
2161.16
MXN |
4573.56
UYU |
Acceso a todos
los cursos
Estudia las 24 horas,
dónde y cuándo quieras
Nuevos cursos
cada semana