
Comenzamos…
Dejamos ya importadas las librerías que vamos a necesitar:
import datetime
import time
import numpy as np
from datetime import datetime,timedelta
from zoneinfo import ZoneInfo, available_timezones
import calendar
%matplotlib inline
import pandas as pd
import sys
A raiz de la actualización del código que soporta al @elgalloaurora he estado jugando y probando con el tratamiento y gestión de horas con sus diferentes versiones “naive” y “no naive” y el cambio entre UTC, referenciadas a diferentes timezones y en modo segundos desde un determinado epoch. He escrito este pqueño doc para que me sirva de memoria para futuros trabajos
Vemos cosas básicas, como :
Horal actual local
datetime.now(ZoneInfo('Europe/Madrid'))
datetime.datetime(2024, 5, 26, 11, 50, 47, 425942, tzinfo=zoneinfo.ZoneInfo(key='Europe/Madrid'))
datetime.now(ZoneInfo('US/Hawaii'))
datetime.datetime(2024, 5, 25, 23, 50, 47, 666428, tzinfo=zoneinfo.ZoneInfo(key='US/Hawaii'))
y aquí se puede encontrar todas las zonas disponibles:
available_timezones()
{'Africa/Abidjan',
'Africa/Accra',
'Africa/Addis_Ababa',
'Africa/Algiers',
'Africa/Asmara',
'Africa/Asmera',
'Africa/Bamako',
'Africa/Bangui',
'Africa/Banjul',
'Africa/Bissau',
'Africa/Blantyre',
'Africa/Brazzaville',
'Africa/Bujumbura',
'Africa/Cairo',
'Africa/Casablanca',
'Africa/Ceuta',
'Africa/Conakry',
.....
'US/Samoa',
'UTC',
'Universal',
'W-SU',
'WET',
'Zulu',
'build/etc/localtime'}
Otra manera de conseguir la hora actual en otra zona horaría es con astimezone
datetime.now(ZoneInfo('Europe/Madrid')).astimezone(ZoneInfo('Europe/Lisbon'))
datetime.datetime(2024, 5, 26, 10, 50, 49, 27417, tzinfo=zoneinfo.ZoneInfo(key='Europe/Lisbon'))
o directamente:
datetime.now().astimezone(ZoneInfo('Europe/Lisbon'))
datetime.datetime(2024, 5, 26, 10, 50, 49, 474078, tzinfo=zoneinfo.ZoneInfo(key='Europe/Lisbon'))
Como caso especial tenemos la hora UTC, muy útil pues es la que nos devuelven, y aceptan, muchas librerías:
datetime.now(ZoneInfo('UTC'))
datetime.datetime(2024, 5, 26, 9, 50, 50, 453552, tzinfo=zoneinfo.ZoneInfo(key='UTC'))
Hora naive y no naive:
fecha = datetime(year=2024,month=5,day=1,hour=10,minute=10)
Esa hora no tiene asociao ningún timezone, y lo podemos confirmar llamando a la función tzinfo:
fecha.tzinfo
Sin embargo esta fecha sí está asociada, en particular a Lisboa:
fecha_lisboa = datetime(year=2024,month=5,day=1,hour=10,minute=10,tzinfo=ZoneInfo(key='Europe/Lisbon'))
en efecto:
fecha_lisboa.tzinfo
zoneinfo.ZoneInfo(key='Europe/Lisbon')
Y que impacto tiene esa diferencia?: por ejemplo, que no puedes restarlas. No puedes calcular la diferencia en tiempo entre una fecha naive y no naive
fecha-fecha_lisboa
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[114], line 1
----> 1 fecha-fecha_lisboa
TypeError: can't subtract offset-naive and offset-aware datetimes
Sin embargo esto si funciona al estar comparando dos naives :
fecha_1 = datetime(year=2024,month=5,day=1,hour=10,minute=10,tzinfo= ZoneInfo('Europe/Lisbon'))
fecha_2 = datetime(year=2024,month=5,day=1,hour=11,minute=10,tzinfo= ZoneInfo('Europe/Madrid'))
qué resultado dará la resta anterior?
(fecha_1-fecha_2).seconds
0
efectivamente, la 11:10 hora local en Madrid corresponden con las 11:10 en Lisboa
Horas medidas en segundos
Este resultado nos da los segundos desde un epoch en particular. Y qué es eso de un epoch?..es una referencia, tal como se define en la documentacion oficial de la librería time :
> The epoch is the point where the time starts, the return value of time.gmtime(0). It is January 1, 1970, 00:00:00 (UTC) on all platforms.
time.time()
1716717063.091218
y como conseguimos esa referencia?. La conseguimos con la ordent:
time.gmtime(0)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
que podemos convertir a formato ´datetime`
datetime.fromtimestamp(time.mktime(time.gmtime(0)))
datetime.datetime(1970, 1, 1, 0, 0)
ese time.time() nos da un resultado en hora UTC. Para comprobarlo vamos a usar la función gmtime
time.gmtime(time.time())
time.struct_time(tm_year=2024, tm_mon=5, tm_mday=26, tm_hour=9, tm_min=51, tm_sec=5, tm_wday=6, tm_yday=147, tm_isdst=0)
y para conseguirla en hora actual:
time.localtime(time.time())
time.struct_time(tm_year=2024, tm_mon=5, tm_mday=26, tm_hour=11, tm_min=51, tm_sec=5, tm_wday=6, tm_yday=147, tm_isdst=1)
Y podemos conseguir esa hora en formato datetime tal como lo veíamos anteriormente
datetime.fromtimestamp(time.time()) #ojo...en local, aunque no naive
datetime.datetime(2024, 5, 26, 11, 51, 7, 303250)
datetime.fromtimestamp(time.time()).replace(tzinfo=ZoneInfo('Europe/Madrid'))
datetime.datetime(2024, 5, 26, 11, 51, 7, 536789, tzinfo=zoneinfo.ZoneInfo(key='Europe/Madrid'))
ojo, que replace tan solo cambia la timezone pero no recalcula la hora de acuerdo a ese cambio.
datetime.fromtimestamp(time.time()).replace(tzinfo=ZoneInfo('Europe/Madrid')).replace(tzinfo=ZoneInfo('Europe/Lisbon'))
datetime.datetime(2024, 5, 26, 11, 51, 7, 950463, tzinfo=zoneinfo.ZoneInfo(key='Europe/Lisbon'))
y para generar una hora en segundos desde una estructurada:
time.time()
1716717068.888389
time.gmtime(time.time())
time.struct_time(tm_year=2024, tm_mon=5, tm_mday=26, tm_hour=9, tm_min=51, tm_sec=9, tm_wday=6, tm_yday=147, tm_isdst=0)
calendar.timegm(time.gmtime(time.time()))
1716717069
que es dentro de una hora (los 3600 segundos sumados)
Y para pasar a un formato no naive desde segundos:
datetime.fromtimestamp(time.time()+3600,tz=ZoneInfo('Europe/Madrid'))
datetime.datetime(2024, 5, 26, 12, 51, 10, 228910, tzinfo=zoneinfo.ZoneInfo(key='Europe/Madrid'))
datetime.fromtimestamp(time.time(),tz=ZoneInfo('Europe/Lisbon'))
datetime.datetime(2024, 5, 26, 10, 51, 10, 435502, tzinfo=zoneinfo.ZoneInfo(key='Europe/Lisbon'))
Así como resumen, y replicando el cuadro de la documentación de la librería:
-
Cambio de segundos desde epoch a struc_time en UTC :
gmtime() -
Cambio de segundos desde epoch a struct_time en LocatTime :
localtime() -
Cambio de struct_time en UTC a segundos :
calendar.timegm() -
Cambio de struct_time local time a segundos:
mktime()y añado dos más:
-
Cambo de datetime a time_struct :
datetime.timetuple() -
Cambio de time_struct a datetime :
datetime.fromtimestamp(mktime(time_struc))



