¿Hay alguna forma de obtener la marca de tiempo UTC especificando la fecha? Lo que esperaría:
datetime(2008, 1, 1, 0, 0, 0, 0)
debería resultar en
1199145600
Crear un objeto de fecha y hora ingenuo significa que no hay información de zona horaria. Si miro la documentación de datetime.utcfromtimestamp, crear una marca de tiempo UTC significa omitir la información de la zona horaria. Entonces, supongo que crear un objeto de fecha y hora ingenuo (como lo hice yo) daría como resultado una marca de tiempo UTC. Sin embargo:
then = datetime(2008, 1, 1, 0, 0, 0, 0)
datetime.utcfromtimestamp(float(then.strftime('%s')))
resultados en
2007-12-31 23:00:00
¿Todavía hay información de zona horaria oculta en el objeto de fecha y hora? ¿Qué estoy haciendo mal?
then.strftime('%s')
que espera la hora local pero la marca de tiempo indica quedatetime(2008, 1, 1)
está en UTC.Respuestas:
Ingenuo
datetime
versus conscientedatetime
datetime
Se dice que los objetos predeterminados son "ingenuos": mantienen la información de la hora sin la información de la zona horaria. Piense en ingenuodatetime
como un número relativo (es decir:)+4
sin un origen claro (de hecho, su origen será común en todos los límites de su sistema).Por el contrario, piense en el conocimiento
datetime
como números absolutos (es decir:)8
con un origen común para todo el mundo.Sin información de la zona horaria, no se puede convertir la fecha y hora "ingenua" en una representación de la hora no ingenua (¿dónde están los
+4
objetivos si no sabemos por dónde empezar?). Por eso no puedes tener undatetime.datetime.toutctimestamp()
método. (cf: http://bugs.python.org/issue1457227 )Para comprobar si
datetime
dt
es ingenuo, compruebedt.tzinfo
, siNone
, entonces es ingenuo:datetime.now() ## DANGER: returns naïve datetime pointing on local time datetime(1970, 1, 1) ## returns naïve datetime pointing on user given time
Tengo citas ingenuas, ¿qué puedo hacer?
Debes hacer una suposición dependiendo de tu contexto particular: La pregunta que debes hacerte es: ¿estabas
datetime
en UTC? o era la hora local?Si estaba usando UTC (no tiene problemas):
import calendar def dt2ts(dt): """Converts a datetime object to UTC timestamp naive datetime will be considered UTC. """ return calendar.timegm(dt.utctimetuple())
Si NO usaba UTC , bienvenido al infierno.
Tienes que hacer que tu
datetime
no sea ingenuo antes de usar la función anterior, devolviéndoles su zona horaria prevista.Necesitará el nombre de la zona horaria y la información sobre si el horario de verano estaba en vigor al producir la fecha y hora ingenua de destino (la última información sobre el horario de verano es necesaria para las esquinas):
import pytz ## pip install pytz mytz = pytz.timezone('Europe/Amsterdam') ## Set your timezone dt = mytz.normalize(mytz.localize(dt, is_dst=True)) ## Set is_dst accordingly
Consecuencias de no proporcionar
is_dst
:No usar
is_dst
generará una hora incorrecta (y una marca de tiempo UTC) si se produjo la fecha y hora objetivo mientras se implementó un DST hacia atrás (por ejemplo, cambiando el tiempo de DST eliminando una hora).Por
is_dst
supuesto, proporcionar información incorrecta generará una hora incorrecta (y una marca de tiempo UTC) solo en la superposición o los huecos de DST. Y, al proporcionar también un tiempo incorrecto, que ocurre en "huecos" (tiempo que nunca existió debido al cambio de horario de verano hacia adelante),is_dst
dará una interpretación de cómo considerar este tiempo falso, y este es el único caso en el.normalize(..)
que realmente se hará algo aquí. ya que luego lo traducirá como una hora válida real (cambiando la fecha y hora Y el objeto DST si es necesario). Tenga en cuenta que.normalize()
no es necesario para tener una marca de tiempo UTC correcta al final, pero probablemente se recomienda si no le gusta la idea de tener tiempos falsos en sus variables, especialmente si reutiliza esta variable en otro lugar.y EVITE USAR LO SIGUIENTE : (cf: Conversión de fecha y hora usando pytz )
dt = dt.replace(tzinfo=timezone('Europe/Amsterdam')) ## BAD !!
¿Por qué? porque
.replace()
reemplaza ciegamente eltzinfo
sin tener en cuenta el tiempo objetivo y elegirá un objeto DST incorrecto. Considerando que.localize()
utiliza el tiempo objetivo y suis_dst
pista para seleccionar el objeto DST correcto.ANTIGUA respuesta incorrecta (gracias @JFSebastien por mencionar esto):
Con suerte, es bastante fácil adivinar la zona horaria (su origen local) cuando crea su
datetime
objeto ingenuo, ya que está relacionado con la configuración del sistema que, con suerte, NO cambiaría entre la creación del objeto de fecha y hora ingenuo y el momento en que desea obtener el Marca de tiempo UTC. Este truco se puede utilizar para dar una pregunta imperfecta .Al usar
time.mktime
podemos crear unutc_mktime
:def utc_mktime(utc_tuple): """Returns number of seconds elapsed since epoch Note that no timezone are taken into consideration. utc tuple must be: (year, month, day, hour, minute, second) """ if len(utc_tuple) == 6: utc_tuple += (0, 0, 0) return time.mktime(utc_tuple) - time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0)) def datetime_to_timestamp(dt): """Converts a datetime object to UTC timestamp""" return int(utc_mktime(dt.timetuple()))
Debe asegurarse de que su
datetime
objeto se cree en la misma zona horaria que la que creó sudatetime
.Esta última solución es incorrecta porque supone que el desfase UTC a partir de ahora es el mismo que el desfase UTC de EPOCH. Lo cual no es el caso de muchas zonas horarias (en un momento específico del año para las compensaciones del horario de verano (DST)).
fuente
datetime.timestamp()
método en Python 3.3.time.mktime()
debe usarse solo para la hora local.calendar.timegm()
podría usarse para convertir la tupla de tiempo utc en una marca de tiempo posix. O mejor aún, use solo métodos de fecha y hora. Ver mi respuesta.replace()
con una zona horaria que tenga un desplazamiento utc no fijo como'Europe/Amsterdam'
. Consulte Conversión de fecha y hora con pytz ..replace(tzinfo=get_localzone())
? 2-timegm()
devuelveint
ya. No es necesario envolverloint
. Además,.timetuple()
cae fracciones de segundo.Otra posibilidad es:
d = datetime.datetime.utcnow() epoch = datetime.datetime(1970,1,1) t = (d - epoch).total_seconds()
Esto funciona ya que tanto "d" como "época" son fechas y horas ingenuas, lo que hace que el operador "-" sea válido y devuelve un intervalo.
total_seconds()
convierte el intervalo en segundos. Tenga en cuenta quetotal_seconds()
devuelve un flotador, inclusod.microsecond == 0
fuente
También tenga en cuenta la función calendar.timegm () como se describe en esta entrada de blog:
import calendar calendar.timegm(utc_timetuple)
La salida debe coincidir con la solución de vaab.
fuente
Si el objeto de fecha y hora de entrada está en UTC:
>>> dt = datetime(2008, 1, 1, 0, 0, 0, 0) >>> timestamp = (dt - datetime(1970, 1, 1)).total_seconds() 1199145600.0
Nota: devuelve float, es decir, los microsegundos se representan como fracciones de segundo.
Si el objeto de fecha de entrada está en UTC:
>>> from datetime import date >>> utc_date = date(2008, 1, 1) >>> timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * 24*60*60 1199145600
Vea más detalles en Conversión de datetime.date a marca de tiempo UTC en Python .
fuente
Siento que la respuesta principal aún no está tan clara, y vale la pena tomarse el tiempo para comprender la hora y las zonas horarias .
¡Lo más importante que hay que entender cuando se trata de tiempo es que el tiempo es relativo !
2017-08-30 13:23:00
: (una fecha y hora ingenua), representa una hora local en algún lugar del mundo, pero tenga2017-08-30 13:23:00
en cuenta que en Londres NO ES LA MISMA HORA que2017-08-30 13:23:00
en San Francisco.Debido a que la misma cadena de tiempo se puede interpretar como diferentes puntos en el tiempo dependiendo de dónde se encuentre en el mundo, existe la necesidad de una noción absoluta de tiempo.
Una marca de tiempo UTC es un número en segundos (o milisegundos) de Epoch (definido como
1 January 1970 00:00:00
en laGMT
zona horaria +00: 00 offset).Epoch está anclado en la zona horaria GMT y, por lo tanto, es un punto absoluto en el tiempo. Por lo tanto, una marca de tiempo UTC que es un desplazamiento de un tiempo absoluto define un punto absoluto en el tiempo .
Esto hace posible ordenar eventos en el tiempo.
Sin información de la zona horaria, el tiempo es relativo y no se puede convertir en una noción absoluta de tiempo sin proporcionar alguna indicación de a qué zona horaria se debe anclar la fecha y hora ingenua.
¿Cuáles son los tipos de tiempo utilizados en el sistema informático?
fecha y hora ingenua : generalmente para mostrar, en la hora local (es decir, en el navegador) donde el sistema operativo puede proporcionar información de zona horaria al programa.
Marcas de tiempo UTC : una marca de tiempo UTC es un punto absoluto en el tiempo, como se mencionó anteriormente, pero está anclado en una zona horaria determinada, por lo que una marca de tiempo UTC se puede convertir en una fecha y hora en cualquier zona horaria, sin embargo, no contiene información de la zona horaria. Qué significa eso? Eso significa que 1504119325 corresponde a
2017-08-30T18:55:24Z
,2017-08-30T17:55:24-0100
o también2017-08-30T10:55:24-0800
. No le dice de dónde es la fecha y hora registrada. Por lo general, se usa en el lado del servidor para registrar eventos (registros, etc.) o se usa para convertir una fecha y hora consciente de la zona horaria en un punto absoluto en el tiempo y calcular las diferencias de tiempo .Cadena de fecha y hora ISO-8601 : ISO-8601 es un formato estandarizado para registrar la fecha y hora con la zona horaria. (De hecho, son varios formatos, lea aquí: https://en.wikipedia.org/wiki/ISO_8601 ) Se utiliza para comunicar información de fecha y hora consciente de la zona horaria de una manera serializable entre sistemas.
¿Cuándo usar cuál? o más bien, ¿cuándo debe preocuparse por las zonas horarias?
Si necesita preocuparse por la hora del día , necesita información sobre la zona horaria. Un calendario o una alarma necesitan la hora del día para programar una reunión a la hora correcta para cualquier usuario del mundo. Si estos datos se guardan en un servidor, el servidor necesita saber a qué zona horaria corresponde la fecha y hora.
Para calcular las diferencias de tiempo entre eventos que provienen de diferentes lugares del mundo, la marca de tiempo UTC es suficiente, pero pierde la capacidad de analizar a qué hora del día ocurrieron los eventos (es decir, para análisis web, es posible que desee saber cuándo los usuarios visitan su sitio en su hora local : ¿ves más usuarios por la mañana o por la noche? No puedes averiguarlo sin la información de la hora del día.
Desplazamiento de zona horaria en una cadena de fecha :
Otro punto que es importante es que el desplazamiento de zona horaria en una cadena de fecha no es fijo . Eso significa que porque
2017-08-30T10:55:24-0800
dice la compensación-0800
o 8 horas atrás, ¡no significa que siempre lo será!En el verano bien podría ser en horario de verano, y sería
-0700
Lo que eso significa es que el desplazamiento de la zona horaria (+0100) no es lo mismo que el nombre de la zona horaria (Europa / Francia) o incluso la designación de la zona horaria (CET)
America/Los_Angeles
La zona horaria es un lugar del mundo , pero se convierte en unaPST
notación de compensación de zona horaria (Hora estándar del Pacífico) en invierno, yPDT
(Hora de verano del Pacífico) en verano.Por lo tanto, además de obtener el desplazamiento de la zona horaria de la cadena de fecha, también debe obtener el nombre de la zona horaria para que sea preciso.
La mayoría de los paquetes podrán convertir las compensaciones numéricas del horario de verano al horario estándar por sí mismas, pero eso no es necesariamente trivial con solo una compensación. Por ejemplo, la
WAT
designación de zona horaria en África Occidental es UTC + 0100 al igual queCET
zona horaria en Francia, pero Francia observa el horario de verano, mientras que África occidental no (porque están cerca del ecuador)Entonces, en resumen, es complicado. MUY complicado, y es por eso que no debe hacerlo usted mismo, sino que confíe en un paquete que lo haga por usted y ¡MANTÉNGALO ACTUALIZADO!
fuente
Una solución sencilla sin utilizar módulos externos:
from datetime import datetime, timezone dt = datetime(2008, 1, 1, 0, 0, 0, 0) int(dt.replace(tzinfo=timezone.utc).timestamp())
fuente
De hecho, existe un problema con el uso de utcfromtimestamp y la especificación de zonas horarias. Hay un buen ejemplo / explicación disponible sobre la siguiente pregunta:
¿Cómo especificar la zona horaria (UTC) al convertir a la hora Unix? (Pitón)
fuente
Creo que la forma correcta de formular tu pregunta es
Is there a way to get the timestamp by specifying the date in UTC?
porque la marca de tiempo es solo un número absoluto, no relativo. La pieza relativa (o consciente de la zona horaria) es la fecha.Encuentro que los pandas son muy convenientes para las marcas de tiempo, así que:
import pandas as pd dt1 = datetime(2008, 1, 1, 0, 0, 0, 0) ts1 = pd.Timestamp(dt1, tz='utc').timestamp() # make sure you get back dt1 datetime.utcfromtimestamp(ts1)
fuente
La respuesta aceptada parece no funcionar para mí. Mi solución:
import time utc_0 = int(time.mktime(datetime(1970, 01, 01).timetuple())) def datetime2ts(dt): """Converts a datetime object to UTC timestamp""" return int(time.mktime(dt.utctimetuple())) - utc_0
fuente
dt
desplazamiento UTC actual ( ) de la zona horaria local y en 1970 difieren.mktime()
espera la hora local.Manera más sencilla:
>>> from datetime import datetime >>> dt = datetime(2008, 1, 1, 0, 0, 0, 0) >>> dt.strftime("%s") '1199163600'
Editar: @Daniel es correcto, esto lo convertiría a la zona horaria de la máquina. Aquí hay una respuesta revisada:
>>> from datetime import datetime, timezone >>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0, timezone.utc) >>> dt = datetime(2008, 1, 1, 0, 0, 0, 0, timezone.utc) >>> int((dt-epoch).total_seconds()) '1199145600'
De hecho, ni siquiera es necesario especificarlo
timezone.utc
, porque la diferencia horaria es la misma siempre que ambosdatetime
tengan la misma zona horaria (o ninguna).>>> from datetime import datetime >>> epoch = datetime(1970, 1, 1, 0, 0, 0, 0) >>> dt = datetime(2008, 1, 1, 0, 0, 0, 0) >>> int((dt-epoch).total_seconds()) 1199145600
fuente
timezone.utc
objeto, a continuación, sólo tiene que utilizar con.timestamp()
:datetime(2008, 1, 1, tzinfo=timezone.utc).timestamp()
. No es necesario crear un objeto de época y restar ..