Python Crear marca de tiempo de Unix cinco minutos en el futuro

297

Tengo que crear un valor "Expira" 5 minutos en el futuro, pero tengo que proporcionarlo en formato UNIX Timestamp. Tengo esto hasta ahora, pero parece un truco.

def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    epoch = datetime.datetime(1970, 1, 1)
    seconds_in_a_day = 60 * 60 * 24
    five_minutes = datetime.timedelta(seconds=5*60)
    five_minutes_from_now = datetime.datetime.now() + five_minutes
    since_epoch = five_minutes_from_now - epoch
    return since_epoch.days * seconds_in_a_day + since_epoch.seconds

¿Hay algún módulo o función que realice la conversión de marca de tiempo para mí?

Daniel Rhoden
fuente
77
Recomiendo cambiar el tema de esta pregunta. La pregunta es buena, pero no se trata de convertir la fecha y hora a la marca de tiempo de Unix. Se trata de cómo obtener una marca de tiempo Unix 5 minutos en el futuro.
DA
No estoy de acuerdo, @DA La pregunta esencialmente dice: "Necesito hacer X e Y. Esto es lo que tengo ahora. ¿Cuál es una mejor manera de hacer Y?" Tal vez hay mejores formas de hacer X, pero el título y el cuerpo claramente preguntan sobre Y.
Rob Kennedy
66
Estoy completamente de acuerdo con usted en la pregunta, y creo que es buena y tiene una buena respuesta. El problema es "Python datetime to Unix timestamp" no refleja ni la pregunta ni la respuesta. Encontré esta publicación buscando una forma de hacer la conversión, y perdí tiempo debido a la línea de asunto engañosa. Sugiero: "Python, 5 minutos en el futuro como marca de tiempo UNIX"
DA
3
@JimmyKane: una respuesta bastante completa sobre cómo obtener una marca de tiempo de una fecha y hora se puede encontrar aquí: stackoverflow.com/questions/8777753/…
Tim Tisdall
@TimTisdall sí, ya que el título ha cambiado, no tiene sentido
Jimmy Kane

Respuestas:

349

Otra forma es usar calendar.timegm:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return calendar.timegm(future.timetuple())

También es más portátil que %sflag to strftime(que no funciona en Windows).

Cat Plus Plus
fuente
Gracias D.Shawley. help (datetime.timedelta) no mencionó ese acceso directo. Solo tenía días, segundos y microsegundos.
Daniel Rhoden
12
Tenga en cuenta que, la combinación de los dos comentarios anteriores, la solución correcta es: calendar.timegm(future.utctimetuple()). Esto asegura que se pasa una hora UTC calendar.timegm.
shadowmatter
1
No puedo votar lo suficiente el comentario de @ tumbleweed. Si está intentando obtener una marca de tiempo UNIX (y, por lo tanto, una en UTC), use calendar.timegm.
Bialecki
@tumbleweed, cierto. Si usa mktime más gmtime (0) dará como resultado un delta de ida y vuelta distinto de cero para cualquier zona horaria además de UTC: por ejemplo, `time.mktime (datetime.fromtimestamp (time.mktime (time.gmtime (0))). Timetuple ())` da 21600.0segundos (6 horas) en lugar de 0.0 para el TZ de mi máquina Unix
hobs
Si desea obtener UTC marca de tiempo se debe utilizar la siguiente: calendar.timegm(datetime.datetime.utcnow().timetuple()). El método de uso datetime.datetime.now().utctimetuple()no funciona para mí (Python 3.2).
Wookie88
155

Ahora en Python> = 3.3 puede llamar al método timestamp () para obtener la marca de tiempo como flotante.

import datetime
current_time = datetime.datetime.now(datetime.timezone.utc)
unix_timestamp = current_time.timestamp() # works if Python >= 3.3

unix_timestamp_plus_5_min = unix_timestamp + (5 * 60)  # 5 min * 60 seconds
Tim Tisdall
fuente
44
+1 por esto. Debería mostrarse mucho más alto, porque es la manera limpia de cómo hacerlo en Python 3
Viktor Stískala
2
@ scott654 Pensé que tenerlo justo al comienzo del comentario lo dejó bastante claro, pero también le agregué algo audaz.
Tim Tisdall
1
Tomaría la nota como un comentario en el bloque de código porque todos simplemente escaneamos el código en las respuestas primero y solo leemos el resto si el código se ve bien. Buena respuesta sin embargo.
Matthew Purdon el
2
La hora local puede ser ambigua . El ejemplo ( datetime.now()) es malo porque alienta el uso de objetos ingenuos de fecha y hora que representan la hora local y puede fallar durante las transiciones DST (debido a la ambigüedad inherente). Podrías usar ts = datetime.now(timezone.utc).timestamp()en su lugar.
jfs
@JFSebastian - buen punto. Sin embargo, no quería agregar a las importaciones, así que lo cambié a utcnow(). Estoy acostumbrado a trabajar en máquinas donde la zona horaria está configurada en UTC, pero eso no debería suponerse en este fragmento de código.
Tim Tisdall
139

Acabo de encontrar esto, y es aún más corto.

import time
def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    return int(time.time()+300)
Daniel Rhoden
fuente
12
Esto no responde la pregunta.
Jesse Dhillon el
22
@JesseDhillon responde la pregunta (haga una marca de tiempo UNIX 5 minutos en el futuro), pero no el título.
dbr
3
time.time()se puede retroceder. Para crear un valor de "Caduca" 5 minutos en el futuro, es posible que necesite un time.monotonic()análogo dependiendo de su caso de uso.
JFS
@ jf-sebastian time.monotonic () no devuelve una marca de tiempo UNIX, devuelve una marca de tiempo con un punto de referencia indefinido.
rspeer
@rspeer: sí, como dicen los documentos , solo la diferencia entre llamadas consecutivas es válida. Si monotonicse puede usar depende de su caso de uso, por ejemplo, el subprocessmódulo lo usa para implementar la timeoutopción.
jfs
57

Esto es lo que necesitas:

import time
import datetime
n = datetime.datetime.now()
unix_time = time.mktime(n.timetuple())
Ali
fuente
¿Cómo es esto diferente o se agrega al que se proporciona 'Cat Plus Plus'?
David
3
Por ejemplo, esta es la respuesta a la pregunta "Fecha y hora de Python para la marca de tiempo de Unix", mientras que Cat Plus Plus respondió la pregunta "Fecha y hora de Python que será en 5 minutos para la marca de tiempo de Unix". Entonces este es limpio y obvio.
running.t
@ running.t: me recuerda: "cada problema tiene una solución simple, obvia e incorrecta ". Ver posibles problemas conmktime(dt.timetuple()) . datetime.now(timezone.utc).timestamp()proporcionado por @Tim Tisdall es la solución en Python 3.3+. De (dt - epoch).total_seconds()lo contrario podría ser utilizado .
jfs
@JFSebastian, ¿qué pasa si realmente quiero que todos los cálculos se realicen en la hora local? ¿Es el caso cuando eg. analizar una cadena ingenua que uno sabe que es hora local y decidir si hubo un horario de verano en ese momento en particular?
n611x007
1
@naxa: sí, algunas horas locales son ambiguas o inexistentes. Además, el desplazamiento de la zona horaria puede ser diferente por otros motivos que no sean DST (necesita una base de datos tz como pytz, para encontrar el desplazamiento correcto). La hora local significa que cualquier cosa que el político local piense que es una buena idea para medir el tiempo, es decir, puede ser muy irregular.
jfs
48

Puede usar datetime.strftimepara obtener el tiempo en forma de Época, usando la %scadena de formato:

def expires():
    future = datetime.datetime.now() + datetime.timedelta(seconds=5*60)
    return int(future.strftime("%s"))

Nota: Esto solo funciona en Linux, y este método no funciona con zonas horarias.

mipadi
fuente
32
Este es un comportamiento algo indocumentado ( python.org/doc/current/library/datetime.html ). Parece estar trabajando en Linux y no funciona en Win32 (generación ValueError: Invalid format string).
Antony Hatchkins
3
Este método no funciona con zonas horarias. Cambiar la zona horaria dará el mismo resultado datetime (2013,12,7, tzinfo = timezone ("America / Chicago")). Strftime ("% s") 1386385200 datetime (2013,12,7, tzinfo = timezone ("Europe / Riga ")). Strftime ("% s ") 1386385200
Martins Balodis
11

Aquí hay una datetimesolución de base menos rota para convertir de un objeto de fecha y hora a una marca de tiempo posix:

future = datetime.datetime.utcnow() + datetime.timedelta(minutes=5)
return (future - datetime.datetime(1970, 1, 1)).total_seconds()

Ver más detalles en Convertir datetime.date a marca de tiempo UTC en Python .

jfs
fuente
6
def in_unix(input):
  start = datetime.datetime(year=1970,month=1,day=1)
  diff = input - start
  return diff.total_seconds()
Sravan
fuente
4

La clave es asegurarse de que todas las fechas que está utilizando estén en la zona horaria utc antes de comenzar a convertir. Consulte http://pytz.sourceforge.net/ para saber cómo hacerlo correctamente. Al normalizar a utc, elimina la ambigüedad de las transiciones de horario de verano. Luego puede usar timedelta de manera segura para calcular la distancia desde la época de Unix y luego convertirlo a segundos o milisegundos.

Tenga en cuenta que la marca de tiempo de Unix resultante se encuentra en la zona horaria UTC. Si desea ver la marca de tiempo en una zona horaria localizada, deberá realizar otra conversión.

También tenga en cuenta que esto solo funcionará para fechas posteriores a 1970.

   import datetime
   import pytz

   UNIX_EPOCH = datetime.datetime(1970, 1, 1, 0, 0, tzinfo = pytz.utc)
   def EPOCH(utc_datetime):
      delta = utc_datetime - UNIX_EPOCH
      seconds = delta.total_seconds()
      ms = seconds * 1000
      return ms
fawce
fuente
3
nota: no entiendo "la marca de tiempo [unix] en una zona horaria localizada". La marca de tiempo es la misma (segundos transcurridos desde entonces 1970-01-01 00:00:00+00:00). Para obtener un objeto de fecha y hora ingenuo en la zona horaria local:datetime.fromtimestamp(ts)
jfs
4

Lo siguiente se basa en las respuestas anteriores (más una corrección para los milisegundos) y emula datetime.timestamp()para Python 3 antes de 3.3 cuando se usan zonas horarias.

def datetime_timestamp(datetime):
    '''
    Equivalent to datetime.timestamp() for pre-3.3
    '''
    try:
        return datetime.timestamp()
    except AttributeError:
        utc_datetime = datetime.astimezone(utc)
        return timegm(utc_datetime.timetuple()) + utc_datetime.microsecond / 1e6

Para responder estrictamente a la pregunta que se le preguntó, querría:

datetime_timestamp(my_datetime) + 5 * 60

datetime_timestampes parte de fecha simple . Pero si estuviera usando ese paquete, probablemente escribiría:

SimpleDate(my_datetime).timestamp + 5 * 60

que maneja muchos más formatos / tipos para my_datetime.

Andrew Cooke
fuente
¿no deberías agregar (5 * 60) para agregar 5 minutos? Creo que solo agregar 5 agrega solo 5 segundos a la marca de tiempo.
Tim Tisdall
1
def expiration_time():
    import datetime,calendar
    timestamp = calendar.timegm(datetime.datetime.now().timetuple())
    returnValue = datetime.timedelta(minutes=5).total_seconds() + timestamp
    return returnValue
hd1
fuente
1

Tenga en cuenta que las soluciones con timedelta.total_seconds()trabajo en python-2.7 +. Usar calendar.timegm(future.utctimetuple())para versiones inferiores de Python.

mighq
fuente