create - Python: ¿Cómo obtener un valor de datetime.today() que es "consciente de la zona horaria"?
timedelta python example (14)
¿Por qué no usar dateutil como se describe aquí: http://joelinoff.com/blog/?p=802
from dateutil.tz import tzlocal
# Get the current date/time with the timezone.
now = datetime.datetime.now(tzlocal())
Estoy tratando de restar un valor de fecha del valor de datetime.today()
para calcular cuánto tiempo hace que algo era. Pero se queja:
TypeError: can''t subtract offset-naive and offset-aware datetimes
El valor de datetime.today()
no parece ser "consciente de la zona horaria", mientras que mi otro valor de fecha es. ¿Cómo obtengo un valor de datetime.today()
que tiene en cuenta la zona horaria? En este momento me está dando la hora en hora local, que es PST, es decir, UTC-8hrs. En el peor de los casos, ¿hay alguna manera de ingresar manualmente un valor de zona horaria en el objeto datetime
devuelto por datetime.today()
y configurarlo en UTC-8? Por supuesto, la solución ideal sería que conozca automáticamente la zona horaria.
Aquí hay una forma de generarlo con el stdlib:
import time
from datetime import datetime
FORMAT=''%Y-%m-%dT%H:%M:%S%z''
date=datetime.strptime(time.strftime(FORMAT, time.localtime()),FORMAT)
La fecha almacenará la fecha local y el desplazamiento de 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:
date
datetime.datetime(2017, 8, 1, 12, 15, 44, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
date.tzname()
''UTC+02:00''
La clave es agregar la directiva %z
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 docs módulo datetime.
Si necesita la fecha en la zona horaria UTC, puede reemplazar time.localtime () con time.gmtime ()
date=datetime.strptime(time.strftime(FORMAT, time.gmtime()),FORMAT)
date
datetime.datetime(2017, 8, 1, 10, 23, 51, tzinfo=datetime.timezone.utc)
date.tzname()
''UTC''
Editar
Esto funciona solo en python3 . La directiva z no está disponible en el código python 2 _strptime.py
Aquí hay una solución estándar que funciona tanto en Python 2 como en 3:
from datetime import datetime
now = datetime.now(utc) # timezone-aware datetime.utcnow()
today = datetime(now.year, now.month, now.day, tzinfo=utc) # midnight
donde today
es una instancia de datetime que representa el comienzo del día (medianoche) en UTC y utc
es un objeto tzinfo ( ejemplo de la documentación ):
from datetime import tzinfo, timedelta
ZERO = timedelta(0)
class UTC(tzinfo):
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
utc = UTC()
Relacionado: comparación de rendimiento de varias maneras de obtener la medianoche (inicio de un día) para una hora UTC determinada .
Nota: es más complejo, para obtener la medianoche para una zona horaria con un desplazamiento utc no fijo .
En Python 3, la biblioteca estándar lo hace mucho más fácil:
>>> import datetime
>>> datetime.datetime.now(datetime.timezone.utc)
datetime.datetime(2016, 8, 26, 14, 34, 34, 74823, tzinfo=datetime.timezone.utc)
Si desea una solución que use solo la biblioteca estándar y que funcione tanto en Python 2 como en Python 3, vea la respuesta de JF Sebastien .
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. Preferiría sugerir el uso de 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 es posible que desee utilizar UTC en toda su aplicación, especialmente para operaciones aritméticas como el cálculo de la diferencia entre dos puntos de tiempo.
Puede obtener la fecha / hora actual así:
import pytz
from datetime import datetime
datetime.utcnow().replace(tzinfo=pytz.utc)
datetime.today()
cuenta que datetime.today()
y datetime.now()
devuelven la hora local , no la hora UTC, por lo que aplicarles .replace(tzinfo=pytz.utc)
no sería correcto.
Otra buena forma de hacerlo es:
datetime.now(pytz.utc)
que es un poco más corto y hace lo mismo.
Seguir leyendo / viendo por qué preferir UTC en muchos casos:
- documentación de pytz
- Lo que todo desarrollador debe saber sobre el tiempo : sugerencias de desarrollo para muchos casos de uso de la vida real
- The Problem with Time & Timezones - Computerphile - explicación divertida y reveladora sobre la complejidad de trabajar con zonas horarias (video)
Obtener una fecha que tenga en cuenta la zona horaria en utc
timezone es suficiente para que la resta de la fecha funcione.
Pero si desea una fecha con tzlocal
zona horaria en su zona horaria actual, tzlocal
es el camino a seguir:
from tzlocal import get_localzone # pip install tzlocal
from datetime import datetime
datetime.now(get_localzone())
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 lo noted JF Sebastian, puede dar resultados erróneos.
Obtenga la hora actual, en una zona horaria específica:
import datetime
import pytz
my_date = datetime.datetime.now(pytz.timezone(''US/Pacific''))
Otra alternativa, en mi opinión una mejor, es usar el Pendulum
lugar de pytz
. Considere el siguiente código simple:
>>> import pendulum
>>> dt = pendulum.now().to_iso8601_string()
>>> print (dt)
2018-03-27T13:59:49+03:00
>>>
Para instalar el Péndulo y ver su documentación, entra here . Tiene toneladas de opciones (como ISO8601 simple, RFC3339 y muchos otros formatos de soporte), mejor rendimiento y tienden a producir código más simple.
Otro método para construir un objeto de fecha y hora que tenga en cuenta la zona horaria que represente la hora actual
import datetime
import pytz
pytz.utc.localize( datetime.datetime.utcnow() )
Puede crear una zona timezone
local usando datetime
analizando la salida de una llamada time.strftime
que usa la directiva %z
(introducida en Python 3.3), como lo muestra jcazor . Puede usar esa timezone
para crear una instancia de datetime
consciente con una sola línea:
import time
from datetime import datetime
aware_local_now = datetime.now(
tz=datetime.strptime(time.strftime("%z", time.localtime()), "%z").tzinfo)
print(aware_local_now)
2018-03-01 13:41:26.753644-08:00
Si está utilizando Django, puede establecer fechas que no son compatibles con tz (solo utc).
Comenta la siguiente línea en settings.py:
USE_TZ = True
Si obtiene la fecha y hora actual en python, entonces importe la fecha y la hora, el paquete pytz en python después de que obtenga la fecha y la hora actual como ...
from datetime import datetime
import pytz
import time
str(datetime.strftime(datetime.now(pytz.utc),"%Y-%m-%d %H:%M:%S%t"))
Use la zona horaria como se muestra a continuación para la fecha y hora de la zona horaria, el valor predeterminado es UTC:
from django.utils import timezone
today = timezone.now()