Saltar al contenido

¿Cómo cambiar la zona horaria en el registro de Python?

No olvides que en las ciencias cualquier problema casi siempere suele tener más de una soluciones, por lo tanto te enseñaremos lo más óptimo y mejor.

Solución:

Cómo registrar la zona horaria

%Z desde el formato strftime

Ventanas

>>> import logging
>>> logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p %Z")
>>> logging.error('test')
11/03/2017 02:29:54 PM Mountain Daylight Time test

Linux

>>> import logging
>>> logging.basicConfig(format="%(asctime)s %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p %Z")
>>> logging.error('test')
11/03/2017 02:30:50 PM MDT test

Si la pregunta es

¿Cómo inicio sesión en una zona horaria diferente a la hora local en el servidor?

parte de la respuesta es logging.Formatter.converter, sin embargo, debe comprender los objetos de fecha y hora ingenuos y conscientes. A menos que desee escribir su propio módulo de zona horaria, le recomiendo encarecidamente la biblioteca pytz (pip install pytz). Python 3 incluye una zona horaria de compensación UTC y UTC, pero hay reglas que deberá implementar para el horario de verano u otras compensaciones, por lo que sugeriría la biblioteca pytz, incluso para Python 3.

Por ejemplo,

>>> import datetime
>>> utc_now = datetime.datetime.utcnow()
>>> utc_now.isoformat()
'2019-05-21T02:30:09.422638'
>>> utc_now.tzinfo
(None)

Si aplico una zona horaria a este objeto de fecha y hora, la hora no cambiará (o emitirá un ValueError para

>>> mst_now = utc_now.astimezone(pytz.timezone('America/Denver'))
>>> mst_now.isoformat()
'2019-05-21T02:30:09.422638-06:00'
>>> utc_now.isoformat()
'2019-05-21T02:30:09.422638'

Sin embargo, si en cambio lo hago

>>> import pytz
>>> utc_now = datetime.datetime.now(tz=pytz.timezone('UTC'))
>>> utc_now.tzinfo

ahora podemos crear una traducción adecuada datetime objeto en cualquier zona horaria que deseemos

>>> mst_now = utc_now.astimezone(pytz.timezone('America/Denver'))
>>> mst_now.isoformat()
'2019-05-20T20:31:44.913939-06:00'

¡Ajá! Ahora para aplicar esto al módulo de registro.

Marca de tiempo de la época a string representación con zona horaria

los LogRecord.created attribute está ajustado a la hora en que LogRecord fue creado (devuelto por time.time()), desde el time módulo. Esto devuelve una marca de tiempo (segundos desde la época). Puede hacer su propia traducción a una zona horaria determinada, pero nuevamente, sugiero pytz, anulando el convertidor.

import datetime
import logging
import pytz

class Formatter(logging.Formatter):
    """override logging.Formatter to use an aware datetime object"""
    def converter(self, timestamp):
        dt = datetime.datetime.fromtimestamp(timestamp)
        tzinfo = pytz.timezone('America/Denver')
        return tzinfo.localize(dt)
        
    def formatTime(self, record, datefmt=None):
        dt = self.converter(record.created)
        if datefmt:
            s = dt.strftime(datefmt)
        else:
            try:
                s = dt.isoformat(timespec='milliseconds')
            except TypeError:
                s = dt.isoformat()
        return s

Python 3.5, 2.7

>>> logger = logging.root
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(Formatter("%(asctime)s %(message)s"))
>>> logger.addHandler(handler)
>>> logger.setLevel(logging.DEBUG)
>>> logger.debug('test')
2019-05-20T22:25:10.758782-06:00 test

Python 3.7

>>> logger = logging.root
>>> handler = logging.StreamHandler()
>>> handler.setFormatter(Formatter("%(asctime)s %(message)s"))
>>> logger.addHandler(handler)
>>> logger.setLevel(logging.DEBUG)
>>> logger.debug('test')
2019-05-20T22:29:21.678-06:00 test

Sustituir America/Denver con America/Anchorage para la zona horaria posix definida por pytz

>>> next(_ for _ in pytz.common_timezones if 'Alaska' in _)
'US/Alaska'

EE.UU. / Alaska está obsoleto

>>> [_ for _ in pytz.all_timezones if 'Anchorage' in _]
['America/Anchorage']

Local

Si llegó a esta pregunta y respuestas buscando cómo registrar la zona horaria local, en lugar de codificar la zona horaria, obtenga tzlocal (pip install tzlocal) y reemplazar

        tzinfo = pytz.timezone('America/Denver')

con

        tzinfo = tzlocal.get_localzone()

Ahora funcionará en cualquier servidor que ejecute el script, con la zona horaria en el servidor.

Advertencia al no registrar UTC

Debo agregar, dependiendo de la aplicación, que iniciar sesión en las zonas horarias locales puede crear ambigüedad o al menos confusión dos veces al año, donde se omiten las 2 a.m. o se repite la 1 a.m., y posiblemente otras.

#!/usr/bin/env python
from datetime import datetime
import logging
import time

from pytz import timezone, utc


def main():
    logging.basicConfig(format="%(asctime)s %(message)s",
                        datefmt="%Y-%m-%d %H:%M:%S")
    logger = logging.getLogger(__name__)
    logger.error("default")

    logging.Formatter.converter = time.localtime
    logger.error("localtime")

    logging.Formatter.converter = time.gmtime
    logger.error("gmtime")

    def customTime(*args):
        utc_dt = utc.localize(datetime.utcnow())
        my_tz = timezone("US/Eastern")
        converted = utc_dt.astimezone(my_tz)
        return converted.timetuple()

    logging.Formatter.converter = customTime
    logger.error("customTime")

    # to find the string code for your desired tz...
    # print(pytz.all_timezones)
    # print(pytz.common_timezones)


if __name__ == "__main__":
    main()
  • Aparentemente el pytz package es la forma bendita de convertir zonas horarias en Python. Entonces comenzamos con datetime, convierta, luego obtenga el (inmutable) time_tuple para que coincida con el tipo de retorno del time métodos
  • Establecer el logging.Formatter.converter La función es recomendada por esta respuesta: (Registro de Python: Cómo configurar la hora en GMT).
  • Encuentre su código TZ favorito descomentando las líneas finales

#!/usr/bin/python

from datetime import datetime
from pytz import timezone
import logging

def timetz(*args):
    return datetime.now(tz).timetuple()

tz = timezone('Asia/Shanghai') # UTC, Asia/Shanghai, Europe/Berlin

logging.Formatter.converter = timetz

logging.basicConfig(
    format="%(asctime)s %(levelname)s: %(message)s",
    level=logging.INFO,
    datefmt="%Y-%m-%d %H:%M:%S",
)

logging.info('Timezone: ' + str(tz))

Usando pytz para definir una zona horaria relativa a UTC.
Basado en el ejemplo de: secsilm

Reseñas y puntuaciones

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *