python - now - time without timezone postgresql example
No se pueden restar tiempos de datos offset-naive y offset-offset (10)
Tengo un campo timestamptz
consciente de la zona horaria en PostgreSQL. Cuando extraigo datos de la tabla, quiero restar el tiempo ahora mismo para que pueda obtener su edad.
El problema que tengo es que tanto datetime.datetime.now()
como datetime.datetime.utcnow()
parecen devolver las marcas de tiempo inconscientes de la zona horaria, lo que hace que este error aparezca:
TypeError: can''t subtract offset-naive and offset-aware datetimes
¿Hay alguna forma de evitar esto (preferiblemente sin un módulo de terceros que se esté utilizando)?
EDITAR: Gracias por las sugerencias, sin embargo, tratar de ajustar la zona horaria parece darme errores ... así que solo voy a usar las marcas de tiempo inconscientes de la zona horaria en PG y siempre inserte usando:
NOW() AT TIME ZONE ''UTC''
De esa manera, todas mis marcas de tiempo son UTC de forma predeterminada (aunque es más molesto hacerlo).
¿Has tratado de eliminar la conciencia de la zona horaria?
de http://pytz.sourceforge.net/
naive = dt.replace(tzinfo=None)
Puede que tenga que agregar la conversión de zona horaria también.
Edición: Tenga en cuenta la edad de esta respuesta. Una respuesta de Python 3 está abajo.
¿Hay alguna razón urgente por la que no pueda manejar el cálculo de la edad en PostgreSQL? Algo como
select *, age(timeStampField) as timeStampAge from myTable
El módulo psycopg2 tiene sus propias definiciones de zona horaria, así que terminé escribiendo mi propio envoltorio alrededor de utcnow:
def pg_utcnow():
import psycopg2
return datetime.utcnow().replace(
tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=0, name=None))
y solo use pg_utcnow
cuando necesite la hora actual para comparar con un sello de timestamptz
PostgreSQL
He encontrado que timezone.make_aware(datetime.datetime.now())
es útil en django (estoy en 1.9.1). Desafortunadamente, no puede simplemente hacer que un objeto datetime
tenga en cuenta el desplazamiento, luego timetz()
. Tienes que hacer una datetime
y datetime
y hacer comparaciones basadas en eso.
La solución correcta es agregar la información de la zona horaria, por ejemplo, para obtener la hora actual como un objeto de fecha y hora consciente en Python 3:
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
En versiones anteriores de Python, podría definir el objeto utc
tzinfo usted mismo (ejemplo de documentos de fecha y hora):
from datetime import tzinfo, timedelta, datetime
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()
entonces:
now = datetime.now(utc)
Sé que algunas personas usan Django específicamente como una interfaz para abstraer este tipo de interacción de base de datos. Django proporciona utilidades que pueden usarse para esto:
from django.utils import timezone
now_aware = timezone.now()
Debe configurar una infraestructura básica de configuración de Django, incluso si solo está utilizando este tipo de interfaz (en la configuración, debe incluir USE_TZ=True
para obtener una fecha y hora consciente).
Por sí mismo, esto probablemente no sea lo suficientemente cerca como para motivarte a usar Django como interfaz, pero hay muchos otros beneficios. Por otro lado, si tropezaste aquí porque estabas destrozando tu aplicación Django (como lo hice yo), quizás esto ayude ...
Sé que esto es antiguo, pero solo pensé que agregaría mi solución en caso de que alguien la encuentre útil.
Quería comparar el datetime local ingenuo con un datetime consciente de un servidor de tiempo. Básicamente, creé un nuevo objeto de fecha y hora ingenuo utilizando el objeto de fecha y hora compatible. Es un poco pirateado y no parece muy bonito, pero hace el trabajo.
import ntplib
import datetime
from datetime import timezone
def utc_to_local(utc_dt):
return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None)
try:
ntpt = ntplib.NTPClient()
response = ntpt.request(''pool.ntp.org'')
date = utc_to_local(datetime.datetime.utcfromtimestamp(response.tx_time))
sysdate = datetime.datetime.now()
... aquí viene el dulce de azúcar ...
temp_date = datetime.datetime(int(str(date)[:4]),int(str(date)[5:7]),int(str(date)[8:10]),int(str(date)[11:13]),int(str(date)[14:16]),int(str(date)[17:19]))
dt_delta = temp_date-sysdate
except Exception:
print(''Something went wrong :-('')
Se me ocurrió una solución ultra-simple:
import datetime
def calcEpochSec(dt):
epochZero = datetime.datetime(1970,1,1,tzinfo = dt.tzinfo)
return (dt - epochZero).total_seconds()
Funciona tanto con los valores de fecha y hora que tienen en cuenta la zona horaria como los que no lo son. Y no se requieren bibliotecas adicionales o soluciones de base de datos.
También me enfrenté al mismo problema. Luego encontré una solución después de mucho buscar.
El problema fue que cuando obtenemos el objeto de fecha y hora del modelo o la forma, éste es consciente de la compensación y, si obtenemos el tiempo por sistema, la compensación es nula .
Entonces, lo que hice es obtener la hora actual utilizando timezone.now () e importar la zona horaria desde django.utils importar zona horaria y poner el valor de USE_TZ = True en el archivo de configuración del proyecto.
Esta es una solución muy simple y clara.
Dos lineas de codigo
# First we obtain de timezone info o some datatime variable
tz_info = your_timezone_aware_variable.tzinfo
# Now we can subtract two variables using the same time zone info
# For instance
# Lets obtain the Now() datetime but for the tz_info we got before
diff = datetime.datetime.now(tz_info)-your_timezone_aware_variable
Debe administrar sus variables de fecha y hora con la misma información de tiempo