Estoy tratando de restar un valor de fecha del valor de datetime.today()
para calcular cuánto tiempo hace que algo estaba. Pero se queja:
TypeError: can't subtract offset-naive and offset-aware datetimes
El valor datetime.today()
no parece ser "consciente de la zona horaria", mientras que mi otro valor de fecha sí lo es. ¿Cómo obtengo un valor datetime.today()
que tenga en cuenta la zona horaria?
En este momento, me está dando la hora en hora local, que es PST, es decir, UTC: 8 horas. En el peor de los casos, ¿hay alguna manera de ingresar manualmente un valor de zona horaria en el datetime
objeto devuelto por datetime.today()
y configurarlo en UTC-8?
Por supuesto, la solución ideal sería conocer automáticamente la zona horaria.
datetime.now().astimezone()
desde Python 3.6Respuestas:
En la biblioteca estándar, no hay una forma multiplataforma para crear zonas horarias conscientes sin crear su propia clase de zona horaria.
En Windows, hay
win32timezone.utcnow()
, pero eso es parte de pywin32. Prefiero sugerir utilizar la biblioteca pytz , que tiene una base de datos actualizada constantemente de la mayoría de las zonas horarias.Trabajar con zonas horarias locales puede ser muy complicado (consulte los enlaces de "Lecturas adicionales" a continuación), por lo que puede preferir utilizar UTC en toda su aplicación, especialmente para operaciones aritméticas como calcular la diferencia entre dos puntos de tiempo.
Puede obtener la fecha / hora actual de esta manera:
Tenga en cuenta eso
datetime.today()
ydatetime.now()
devuelva la hora local , no la hora UTC, por lo que solicitarla.replace(tzinfo=pytz.utc)
no sería correcto.Otra buena manera de hacerlo es:
que es un poco más corto y hace lo mismo.
Leer más / ver por qué preferir UTC en muchos casos:
fuente
datetime.now(pytz.utc)
lugar dedatetime.utcnow().replace(tzinfo = pytz.utc)
?now(utc)
no regresa hoy (a menos que sea medianoche en UTC), devuelve la hora actual en UTC. También necesita.replace(hour=0, minute=0, ...)
obtener el comienzo del día (comodatetime.today()
)today()
devuelve la hora actual, no la medianoche. Si hay un caso de uso donde se requiere medianoche, sí, el reemplazo debe hacerse en consecuencia. Dado que la pregunta original era sobre la diferencia de fecha y hora, no creo que sea necesaria la medianoche.datetime.today()
escombine(date.today(), time())
.datetime
tiene ambos.now()
y.today()
métodos que (como has señalado correctamente) devuelven (casi) lo mismo. No haydate.now()
métododate
y losdatetime
objetos no son intercambiables. Usar un objeto datetime en lugar de undate
objeto puede producir errores sutiles; No veo ninguna razón paradatetime.today()
existir si es casi un duplicado dedatetime.now()
.timezone.now()
lugar de,datetime.now()
ya que usará UTC automáticamente siUSE_TZ = True
.timezone
se encuentra endjango.utils.timezone
, documentación: docs.djangoproject.com/en/1.11/topics/i18n/timezonesObtenga la hora actual, en una zona horaria específica:
fuente
datetime.datetime(2016, 11, 5, 9, 43, 45, tzinfo=pytz.timezone('US/Pacific'))
y vea si eso es lo que esperabaEn Python 3, la biblioteca estándar hace que sea mucho más fácil especificar UTC como la zona horaria:
Si desea una solución que use solo la biblioteca estándar y que funcione tanto en Python 2 como en Python 3, consulte la respuesta de jfs .
Si necesita la zona horaria local, no UTC, vea la respuesta de Mihai Capotă
fuente
Aquí hay una solución stdlib que funciona tanto en Python 2 como en 3:
donde
today
es una instancia de fecha y hora consciente que representa el comienzo del día (medianoche) en UTC yutc
es un objeto tzinfo ( ejemplo de la documentación ):Relacionado: comparación de rendimiento de varias formas de llegar a la medianoche (inicio de un día) para una hora UTC determinada . Nota: es más complejo obtener la medianoche para una zona horaria con un desplazamiento UTC no fijo .
fuente
Otro método para construir un objeto datetime con reconocimiento de zona horaria que representa la hora actual:
fuente
pytz.utc
ypytz.UTC
ambos están definidos (y son lo mismo)replace()
la zona horaria ing es generalmente propensa a errores en la mayoría de los otros usos, mientras quelocalize()
ing es la forma preferida de asignar la zona horaria a las marcas de tiempo ingenuas..localize()
método falla para horas locales ambiguas (entrada no utc). La respuesta de @ philfreo que utiliza.now(pytz_timezone)
continúa funcionando en tales casos..now(pytz_timezone)
hace exactamente lo mismo quelocalize(utcnow)
: primero genera la hora actual en UTC, luego le asigna una zona horaria: "<...> En este caso, el resultado es equivalente atz.fromutc(datetime.utcnow().replace(tzinfo=tz))
". Ambas respuestas son correctas y funcionan siempre.pytz
través de OLSON db, debe saber cómo convertirlo a cualquier zona horaria del mundo. Hacer consciente cualquier otra zona horaria ingenua (no utc) es difícil debido a la ambigüedad durante los turnos de verano. Eso no es un problema de.localize
(darle unis_dst
valor lo hace funcionar para cualquier fecha). Ese es un problema inherente a la práctica del horario de verano.Una línea utilizando solo la biblioteca estándar funciona a partir de Python 3.3. Puede obtener un
datetime
objeto consciente de la zona horaria local utilizandoastimezone
(como lo sugiere johnchen902 ):fuente
datetime.now()
se puede invocar sin ningún argumento y devolver el resultado local correcto (datetime
se presume que los ingenuos se encuentran en la zona horaria local).Si está utilizando Django , puede establecer fechas que no sean conscientes de tz (solo UTC ).
Comente la siguiente línea en settings.py:
fuente
pytz es una biblioteca de Python que permite cálculos de zona horaria precisos y multiplataforma con Python 2.3 o superior.
Con stdlib, esto no es posible.
Vea una pregunta similar sobre SO .
fuente
Aquí hay una forma de generarlo con stdlib:
date almacenará la fecha local y el desplazamiento desde UTC , no la fecha en la zona horaria UTC, por lo que puede usar esta solución si necesita identificar en qué zona horaria se genera la fecha . En este ejemplo y en mi zona horaria local:
La clave es agregar la
%z
directiva a la representación FORMAT, para indicar el desplazamiento UTC de la estructura de tiempo generada. Se pueden consultar otros formatos de representación en los documentos del módulo de fecha y horaSi necesita la fecha en la zona horaria UTC, puede reemplazar time.localtime () con time.gmtime ()
Editar
Esto solo funciona en python3 . La directiva z no está disponible en el código de python 2 _strptime.py
fuente
Use dateutil como se describe en Python datetime.datetime.now () que conoce la zona horaria :
fuente
tzlocal()
función sigue siendo una de las soluciones más simples y definitivamente debería mencionarse aquí.Obtener una fecha con
utc
reconocimiento de la zona horaria en la zona horaria es suficiente para que funcione la resta de fechas.Pero si desea una fecha que reconozca la zona horaria en su zona horaria actual, este
tzlocal
es el camino a seguir:PS
dateutil
tiene una función similar (dateutil.tz.tzlocal
). Pero a pesar de compartir el nombre, tiene una base de código completamente diferente, que, como señaló JF Sebastian, puede dar resultados incorrectos.fuente
Aquí hay una solución que utiliza una zona horaria legible y que funciona con today ():
Puede enumerar todas las zonas horarias de la siguiente manera:
fuente
Especialmente para zonas horarias no UTC:
La única zona horaria que tiene su propio método es
timezone.utc
, pero puede evitar una zona horaria con cualquier desplazamiento UTC si lo necesita usandotimedelta
&timezone
y forzándolo a usar.replace
.Usar
timezone(timedelta(hours=n))
como zona horaria es la verdadera bala de plata aquí, y tiene muchas otras aplicaciones útiles.fuente
Si obtiene la hora y fecha actuales en python, importe la fecha y la hora, paquete pytz en python después de que obtendrá la fecha y hora actuales como ..
fuente
Otra alternativa, en mi opinión una mejor, está usando en
Pendulum
lugar depytz
. Considere el siguiente código simple:Para instalar Pendulum y ver su documentación, vaya aquí . Tiene toneladas de opciones (como ISO8601 simple, RFC3339 y muchos otros formatos compatibles), un mejor rendimiento y tiende a producir un código más simple.
fuente
Use la zona horaria como se muestra a continuación para obtener una fecha y hora que tenga en cuenta la zona horaria. El valor predeterminado es UTC:
fuente
Tyler de 'howchoo' hizo un artículo realmente genial que me ayudó a tener una mejor idea de los objetos de fecha y hora, enlace a continuación
Trabajando con fecha y hora
esencialmente, acabo de agregar lo siguiente al final de mis dos objetos de fecha y hora
Ejemplo:
fuente
intente pnp_datetime , todo el tiempo que se ha utilizado y devuelto es con la zona horaria, y no causará ningún problema ingenuo y consciente del desplazamiento.
fuente
Debe enfatizarse que desde Python 3.6, solo necesita la lib estándar para obtener un objeto datetime con reconocimiento de zona horaria que represente la hora local (la configuración de su sistema operativo). Usando astimezone ()
(Ver el comentario de @ johnchen902).
fuente