"zoneinfo" --- Soporte de zona horaria IANA
*******************************************

Nuevo en la versión 3.9.

======================================================================

El módulo "zoneinfo" proporciona una implementación concreta de zonas
horarias para soportar la base de datos de zonas horarias de IANA tal
y como se especificó originalmente en **PEP 615**. Por defecto,
"zoneinfo" utiliza los datos de zona horaria del sistema si están
disponibles; si no hay datos de zona horaria del sistema, la
biblioteca volverá a utilizar el paquete de primera parte tzdata
disponible en PyPI.

Ver también:

  Modulo: "datetime"
     Proporciona los tipos "time" y "datetime" con los que está
     diseñada la clase "ZoneInfo".

  Paquete tzdata
     Paquete de origen mantenido por los desarrolladores del núcleo de
     CPython para suministrar datos de zonas horarias a través de
     PyPI.


Usando "ZoneInfo"
=================

"ZoneInfo" es una implementación concreta de la clase base abstracta
"datetime.tzinfo", y está pensada para ser adjuntada a "tzinfo", bien
a través del constructor, del método "datetime.replace" o de
"datetime.astimezone":

   >>> from zoneinfo import ZoneInfo
   >>> from datetime import datetime, timedelta

   >>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))
   >>> print(dt)
   2020-10-31 12:00:00-07:00

   >>> dt.tzname()
   'PDT'

Las fechas construidas de esta manera son compatibles con la
aritmética de fechas y manejan las transiciones del horario de verano
sin ninguna otra intervención:

   >>> dt_add = dt + timedelta(days=1)

   >>> print(dt_add)
   2020-11-01 12:00:00-08:00

   >>> dt_add.tzname()
   'PST'

Estas zonas horarias también soportan el atributo "fold" introducido
en **PEP 495**.  Durante las transiciones de desfase que inducen
tiempos ambiguos (como una transición de horario de verano a horario
estándar), se utiliza el desfase de *antes* de la transición cuando
"fold=0", y el desfase *después* de la transición cuando "fold=1", por
ejemplo:

   >>> dt = datetime(2020, 11, 1, 1, tzinfo=ZoneInfo("America/Los_Angeles"))
   >>> print(dt)
   2020-11-01 01:00:00-07:00

   >>> print(dt.replace(fold=1))
   2020-11-01 01:00:00-08:00

Al convertir desde otra zona horaria, el pliegue se ajustará al valor
correcto:

   >>> from datetime import timezone
   >>> LOS_ANGELES = ZoneInfo("America/Los_Angeles")
   >>> dt_utc = datetime(2020, 11, 1, 8, tzinfo=timezone.utc)

   >>> # Before the PDT -> PST transition
   >>> print(dt_utc.astimezone(LOS_ANGELES))
   2020-11-01 01:00:00-07:00

   >>> # After the PDT -> PST transition
   >>> print((dt_utc + timedelta(hours=1)).astimezone(LOS_ANGELES))
   2020-11-01 01:00:00-08:00


Fuentes de datos
================

El módulo "zoneinfo" no proporciona directamente los datos de la zona
horaria, y en su lugar extrae la información de la zona horaria de la
base de datos de la zona horaria del sistema o del paquete de PyPI
tzdata, si está disponible. Algunos sistemas, incluyendo notablemente
los sistemas Windows, no tienen una base de datos IANA disponible, por
lo que para los proyectos que tienen como objetivo la compatibilidad
entre plataformas que requieren datos de zona horaria, se recomienda
declarar una dependencia de tzdata. Si no están disponibles ni los
datos del sistema ni los de tzdata, todas las llamadas a "ZoneInfo"
lanzarán un "ZoneInfoNotFoundError".


Configurando los orígenes de datos
----------------------------------

Cuando se llama a "ZoneInfo(key)", el constructor busca primero en los
directorios especificados en "TZPATH" un archivo que coincida con
"key", y en caso de fallo busca una coincidencia en el paquete tzdata.
Este comportamiento puede configurarse de tres maneras:

1. El "TZPATH" por defecto cuando no se especifica otra cosa puede
   configurarse en tiempo de compilación.

2. "TZPATH" puede configurarse utilizando una variable de entorno.

3. En runtime, la ruta de búsqueda puede ser manipulada usando la
   función "reset_tzpath()".


Configuración en tiempo de compilación
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

La ruta por defecto "TZPATH" incluye varias ubicaciones comunes de
despliegue para la base de datos de zonas horarias (excepto en
Windows, donde no hay ubicaciones "conocidas" para los datos de zonas
horarias). En los sistemas POSIX, los distribuidores posteriores y
aquellos que construyen Python desde el código fuente que saben dónde
se despliegan los datos de zona horaria de su sistema pueden cambiar
la ruta de zona horaria por defecto especificando la opción de
compilación "TZPATH" (o, más probablemente, la bandera "configure" "--
with-tzpath"), que debe ser una cadena delimitada por "os.pathsep".

En todas las plataformas, el valor configurado está disponible como la
clave "TZPATH" en "sysconfig.get_config_var()".


Configuración del entorno
~~~~~~~~~~~~~~~~~~~~~~~~~

Cuando se inicializa "TZPATH" (ya sea en el momento de la importación
o cuando se llama a "reset_tzpath()" sin argumentos), el módulo
"zoneinfo" utilizará la variable de entorno "PYTHONTZPATH", si existe,
para establecer la ruta de búsqueda.

PYTHONTZPATH

   Se trata de una cadena separada por "os.pathsep" que contiene la
   ruta de búsqueda de la zona horaria a utilizar. Debe consistir sólo
   en rutas absolutas y no relativas. Los componentes relativos
   especificados en "PYTHONTZPATH" no se utilizarán, pero por lo demás
   el comportamiento cuando se especifica una ruta relativa es
   definido por la implementación; CPython lanzará
   "InvalidTZPathWarning", pero otras implementaciones son libres de
   ignorar silenciosamente el componente erróneo o lanzar una
   excepción.

Para que el sistema ignore los datos del sistema y utilice el paquete
tzdata en su lugar, establezca "PYTHONTZPATH=""".


Configuración de tiempo de ejecución
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

La ruta de búsqueda de TZ también puede configurarse en tiempo de
ejecución mediante la función "reset_tzpath()". Por lo general, esta
operación no es aconsejable, aunque es razonable utilizarla en
funciones de prueba que requieran el uso de una ruta de zona horaria
específica (o que requieran deshabilitar el acceso a las zonas
horarias del sistema).


La clase "ZoneInfo"
===================

class zoneinfo.ZoneInfo(key)

   Una subclase concreta de "datetime.tzinfo" que representa una zona
   horaria IANA especificada por la cadena "key". Las llamadas al
   constructor primario siempre devolverán objetos que se comparan de
   forma idéntica; dicho de otro modo, salvo la invalidación de la
   caché mediante "ZoneInfo.clear_cache()", para todos los valores de
   "key", la siguiente afirmación siempre será verdadera:

      a = ZoneInfo(key)
      b = ZoneInfo(key)
      assert a is b

   La "key" debe tener la forma de una ruta POSIX relativa y
   normalizada, sin referencias de nivel superior. El constructor
   lanzará "ValueError" si se pasa una clave no conforme.

   Si no se encuentra ningún archivo que coincida con la "clave", el
   constructor lanzará "ZoneInfoNotFoundError".

La clase "ZoneInfo" tiene dos constructores alternativos:

classmethod ZoneInfo.from_file(fobj, /, key=None)

   Construye un objeto "ZoneInfo" a partir de un objeto tipo archivo
   que retorna bytes (por ejemplo, un archivo abierto en modo binario
   o un objeto "io.BytesIO"). A diferencia del constructor primario,
   éste siempre construye un nuevo objeto.

   El parámetro "key" establece el nombre de la zona a efectos de
   "__str__()" y "__repr__()".

   Los objetos creados a través de este constructor no pueden ser
   serializados (ver pickling).

classmethod ZoneInfo.no_cache(key)

   Un constructor alternativo que omite la caché del constructor. Es
   idéntico al constructor principal, pero retorna un nuevo objeto en
   cada llamada. Es muy probable que esto sea útil para propósitos de
   prueba o demostración, pero también se puede utilizar para crear un
   sistema con una estrategia de invalidación de caché diferente.

   Los objetos creados a través de este constructor también pasarán
   por encima de la caché de un proceso de deserialización cuando sean
   deserializados.

   Prudencia:

     El uso de este constructor puede cambiar la semántica de tus
     datetimes de manera sorprendente, sólo úsalo si sabes que lo
     necesitas.

También están disponibles los siguientes métodos de clase:

classmethod ZoneInfo.clear_cache(*, only_keys=None)

   Un método para invalidar la caché de la clase "ZoneInfo". Si no se
   pasan argumentos, se invalidan todas las cachés y la siguiente
   llamada al constructor primario de cada clave devolverá una nueva
   instancia.

   Si se pasa un iterable de nombres de claves al parámetro
   "only_keys", sólo se eliminarán de la caché las claves
   especificadas. Las claves pasadas a "only_keys" pero que no se
   encuentran en la caché se ignoran.

   Advertencia:

     La invocación de esta función puede cambiar la semántica de las
     fechas utilizando "ZoneInfo" de forma sorprendente; esto modifica
     el estado global del proceso y por lo tanto puede tener efectos
     de gran alcance. Utilícela sólo si sabe que lo necesita.

La clase tiene un atributo:

ZoneInfo.key

   Se trata de un *attribute* de sólo lectura que retorna el valor de
   "key" pasado al constructor, que debe ser una clave de búsqueda en
   la base de datos de zonas horarias de la IANA (por ejemplo,
   "America/New_York", "Europe/Paris" o "Asia/Tokyo".

   Para las zonas construidas a partir de un archivo sin especificar
   un parámetro "key", se establecerá como "None".

   Nota:

     Aunque es una práctica algo común exponerlos a los usuarios
     finales, estos valores están diseñados para ser claves primarias
     para representar las zonas relevantes y no necesariamente
     elementos orientados al usuario.  Se pueden utilizar proyectos
     como CLDR (Unicode Common Locale Data Repository) para obtener
     cadenas más fáciles de usar a partir de estas claves.


Representaciones de cadenas
---------------------------

La representación de cadena que se retorna al llamar a "str" sobre un
objeto "ZoneInfo" utiliza por defecto el atributo "ZoneInfo.key" (ver
la nota de uso en la documentación del atributo):

   >>> zone = ZoneInfo("Pacific/Kwajalein")
   >>> str(zone)
   'Pacific/Kwajalein'

   >>> dt = datetime(2020, 4, 1, 3, 15, tzinfo=zone)
   >>> f"{dt.isoformat()} [{dt.tzinfo}]"
   '2020-04-01T03:15:00+12:00 [Pacific/Kwajalein]'

Para los objetos construidos a partir de un fichero sin especificar un
parámetro "key", "str" vuelve a llamar a "repr`()". El parámetro
"repr" de "ZoneInfo" está definido por la implementación y no es
necesariamente estable entre versiones, pero se garantiza que no es
una clave válida de "ZoneInfo".Pickled.


Serialización de Pickle
-----------------------

En lugar de serializar todos los datos de transición, los objetos
"ZoneInfo" se serializan por clave, y los objetos "ZoneInfo"
construidos a partir de archivos (incluso los que tienen un valor por
"key" especifico) no pueden ser serializados.

El comportamiento de un archivo "ZoneInfo" depende de cómo se haya
construido:

1. "ZoneInfo(key)": Cuando se construye con el constructor primario,
   un objeto "ZoneInfo" se serializa por la clave, y cuando se
   deserializa, el proceso de deserialización utiliza el primario y
   por lo tanto se espera que estos sean el mismo objeto que otras
   referencias a la misma zona horaria.  Por ejemplo, si
   "europe_berlin_pkl" es una cadena que contiene un pickle construido
   a partir de "ZoneInfo("Europe/Berlin")", se esperaría el siguiente
   comportamiento:

      >>> a = ZoneInfo("Europe/Berlin")
      >>> b = pickle.loads(europe_berlin_pkl)
      >>> a is b
      True

2. "ZoneInfo.no_cache(key)": Cuando se construye a partir del
   constructor que evita la caché, el objeto "ZoneInfo" también se
   serializa por clave, pero cuando se deserializa, el proceso de
   deserialización utiliza el constructor que evita la caché. Si
   "europe_berlin_pkl_nc" es una cadena que contiene un pickle
   construido a partir de "ZoneInfo.no_cache("Europe/Berlin")", cabría
   esperar el siguiente comportamiento:

      >>> a = ZoneInfo("Europe/Berlin")
      >>> b = pickle.loads(europe_berlin_pkl_nc)
      >>> a is b
      False

3. "ZoneInfo.from_file(fobj, /, key=None)": Cuando se construye a
   partir de un fichero, el objeto "ZoneInfo" lanza una excepción al
   ser recogido. Si un usuario final quiere recoger un "ZoneInfo"
   construido a partir de un archivo, se recomienda que utilice un
   tipo de envoltura o una función de serialización personalizada: ya
   sea serializando por clave o almacenando el contenido del objeto
   archivo y serializándolo.

Este método de serialización requiere que los datos de la zona horaria
para la clave requerida estén disponibles tanto en el lado de
serialización como en el de deserialización, de forma similar a como
se espera que las referencias a las clases y funciones existan tanto
en el entorno de serialización como en el de deserialización. También
significa que no se garantiza la consistencia de los resultados cuando
se retira un "ZoneInfo" recogido en un entorno con una versión
diferente de los datos de la zona horaria.


Funciones
=========

zoneinfo.available_timezones()

   Obtiene un conjunto que contiene todas las claves válidas para las
   zonas horarias de la IANA disponibles en cualquier lugar de la ruta
   de zonas horarias. Se recalcula en cada llamada a la función.

   Esta función sólo incluye los nombres de zona canónicos y no
   incluye las zonas "especiales" como las que se encuentran bajo los
   directorios "posix/" y "right/", o la zona "posixrules".

   Prudencia:

     Esta función puede abrir un gran número de archivos, ya que la
     mejor manera de determinar si un archivo en la ruta de la zona
     horaria es una zona horaria válida es leer la "magic string"
     (cadena mágica) al principio.

   Nota:

     Estos valores no están diseñados para ser expuestos a los
     usuarios finales; para los elementos de cara al usuario, las
     aplicaciones deberían utilizar algo como CLDR (el Unicode Common
     Locale Data Repository) para obtener cadenas más fáciles de usar.
     Véase también la nota de advertencia sobre "ZoneInfo.key".

zoneinfo.reset_tzpath(to=None)

   Establece o restablece la ruta de búsqueda de la zona horaria
   ("TZPATH") para el módulo. Cuando se llama sin argumentos, "TZPATH"
   se establece en el valor por defecto.

   La llamada a "reset_tzpath" no invalidará la caché de "ZoneInfo",
   por lo que las llamadas al constructor primario de "ZoneInfo" sólo
   utilizarán el nuevo "TZPATH" en caso de que se pierda la caché.

   El parámetro "to" debe ser un *sequence* de cadenas o "os.PathLike"
   y no una cadena, todos los cuales deben ser rutas absolutas.
   "ValueError" se lanzará si se pasa algo que no sea una ruta
   absoluta.


Globales
========

zoneinfo.TZPATH

   Una secuencia de sólo lectura que representa la ruta de búsqueda de
   zonas horarias -- cuando se construye un "ZoneInfo" a partir de una
   clave, la clave se une a cada entrada del "TZPATH", y se utiliza el
   primer archivo encontrado.

   "TZPATH" sólo puede contener rutas absolutas, nunca relativas,
   independientemente de cómo esté configurado.

   El objeto al que apunta "zoneinfo.TZPATH" puede cambiar en
   respuesta a una llamada a "reset_tzpath()", por lo que se
   recomienda utilizar "zoneinfo.TZPATH" en lugar de importar "TZPATH"
   desde "zoneinfo" o asignar una variable de larga duración a
   "zoneinfo.TZPATH".

   Para más información sobre la configuración de la ruta de búsqueda
   de zonas horarias, consulte Configurando los orígenes de datos.


Excepciones y advertencias
==========================

exception zoneinfo.ZoneInfoNotFoundError

   Se lanza cuando la construcción de un objeto "ZoneInfo" falla
   porque la clave especificada no puede encontrarse en el sistema. Es
   una subclase de "KeyError".

exception zoneinfo.InvalidTZPathWarning

   Se lanza cuando "PYTHONTZPATH" contiene un componente no válido que
   será filtrado, como una ruta relativa.
