Python Crie timestamp de unix cinco minutos no futuro

297

Preciso criar um valor "Expira" daqui a 5 minutos, mas preciso fornecê-lo no formato UNIX Timestamp. Eu tenho isso até agora, mas parece um hack.

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

Existe um módulo ou função que faça a conversão de carimbo de data e hora para mim?

Daniel Rhoden
fonte
7
Eu recomendo mudar o assunto desta pergunta. A pergunta é boa, mas não se trata de converter data e hora em carimbo de data / hora do Unix. É sobre como obter um carimbo de data / hora do Unix em 5 minutos no futuro.
DA
Discordo, @DA A pergunta diz essencialmente "Preciso fazer X e Y. Aqui está o que tenho agora. Qual é a melhor maneira de fazer Y?" Talvez há melhores maneiras de fazer X, mas o título eo corpo claramente perguntar sobre Y.
Rob Kennedy
6
Concordo plenamente com você na questão, e acho que é uma boa com uma boa resposta. O problema é que "data e hora do Python para o carimbo de data e hora do Unix" não reflete a pergunta nem a resposta. Encontrei este post procurando uma maneira de fazer a conversão e perdi tempo por causa da linha de assunto enganosa. Sugiro: "Python, 5 minutos no futuro como carimbo de data / hora do UNIX"
DA
3
@JimmyKane - Uma resposta muito abrangente sobre como obter um timestamp a partir de uma data e hora podem ser encontrados aqui: stackoverflow.com/questions/8777753/...
Tim Tisdall
@TimTisdall sim, uma vez que o título foi alterado, não faz sentido #
Jimmy Kane

Respostas:

349

Outra maneira é usar calendar.timegm:

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

Também é mais portátil do que %ssinalizar strftime(o que não funciona no Windows).

Cat Plus Plus
fonte
Obrigado D.Shawley. a ajuda (datetime.timedelta) não mencionou esse atalho. Ele tinha apenas dias, segundos e microssegundos.
Daniel Rhoden
12
Note-se que, combinando os dois últimos comentários, a solução certa é: calendar.timegm(future.utctimetuple()). Isso garante que a hora UTC seja passada calendar.timegm.
shadowmatter 31/01
1
Não é possível votar o comentário de @ tumbleweed o suficiente. Se você estiver tentando obter um registro de data e hora do UNIX (e, portanto, um no UTC), use calendar.timegm.
Bialecki
@tumbleweed, certo. Se você usar mktime mais gmtime (0), resultará em um delta de ida e volta diferente de zero para qualquer fuso horário além do UTC: por exemplo, `time.mktime (datetime.fromtimestamp (time.mktime (time.gmtime (0))). Scheduleuple ())` dá 21600.0segundos (6 horas) em vez de 0,0 para TZ da minha máquina unix
Placas
Se você deseja obter UTC timestamp você deve usar este: calendar.timegm(datetime.datetime.utcnow().timetuple()). O método usando datetime.datetime.now().utctimetuple()não funciona para mim (Python 3.2).
Wookie88
155

Agora, em Python> = 3.3, você pode chamar o método timestamp () para obter o timestamp como um float.

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
fonte
4
+1 para isso. Ele deve ser exibido muito maior, porque é a maneira limpa como fazer isso em Python 3
Viktor Stískala
2
@ scott654 Eu pensei que tê-lo logo no início do comentário deixou claro o suficiente, mas eu adicionei alguns ousados ​​também.
precisa
1
Eu faria a anotação como um comentário no bloco de código, porque todos nós apenas digitalizamos o código nas respostas primeiro e só lemos o resto se o código parecer bom. Boa resposta embora.
Matthew Purdon
2
a hora local pode ser ambígua . O exemplo ( datetime.now()) é ruim porque incentiva o uso de objetos de data / hora ingênuos que representam a hora local e pode falhar durante as transições de horário de verão (devido à ambiguidade inerente). Você poderia usar em seu ts = datetime.now(timezone.utc).timestamp()lugar.
JFS
@JFSebastian - bom ponto. Eu não queria adicionar às importações, então mudei para utcnow(). Estou acostumado a trabalhar em máquinas em que o fuso horário está definido como UTC, mas isso não deve ser assumido neste trecho de código.
precisa
139

Acabei de encontrar isso, e é ainda mais curto.

import time
def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    return int(time.time()+300)
Daniel Rhoden
fonte
12
Isso não responde à pergunta.
Jesse Dhillon
22
@JesseDhillon, ele responde à pergunta (faça um carimbo de data e hora do UNIX daqui a 5 minutos), mas não o título.
DBR
3
time.time()pode ser recuado. Para criar um valor "Expira" daqui a 5 minutos, pode ser necessário time.monotonic()analógico, dependendo do seu caso de uso.
JFS
@ jf-sebastian time.monotonic () não retorna um registro de data e hora do UNIX, ele retorna um registro de data e hora com um ponto de referência indefinido.
rspeer
@rspeer: sim, como dizem os documentos , apenas a diferença entre chamadas consecutivas é válida. A monotonicpossibilidade de utilização depende do seu caso de uso, por exemplo, o subprocessmódulo o utiliza para implementar a timeoutopção.
JFS
57

Isto é o que você precisa:

import time
import datetime
n = datetime.datetime.now()
unix_time = time.mktime(n.timetuple())
Todos
fonte
Qual é a diferença ou o valor agregado ao 'Cat Plus Plus' fornecido?
David
3
Por exemplo, esta é a resposta para a pergunta "Data e hora do Python para o registro de data e hora do Unix", enquanto o Cat Plus Plus respondeu a pergunta "Data e hora do Python que estará em 5 minutos para o registro de data e hora do Unix". Portanto, este é limpo e óbvio.
running.t
@ running.t: lembra-me: "todo problema tem solução simples, óbvia e errada ". Veja possíveis problemas commktime(dt.timetuple()) . datetime.now(timezone.utc).timestamp()fornecido por @Tim Tisdall é a solução em Python 3.3+. Caso contrário, (dt - epoch).total_seconds()poderia ser usado .
JFS
@JFSebastian, e se eu realmente quiser que todo o cálculo ocorra no horário local? É o caso quando, por exemplo. analisar uma sequência ingênua que se sabe que é hora local e decidir se havia horário de verão em vigor naquele horário específico?
N611x007
1
@ Naxa: Sim, alguns horários locais são ambíguos ou inexistentes. Além disso, o deslocamento do fuso horário pode ser diferente por outros motivos que não o DST (você precisa de um banco de dados tz, como o pytz, para descobrir o deslocamento correto). Hora local significa que qualquer político local acha que é uma boa ideia medir o tempo, ou seja, pode ser altamente irregular.
JFS
48

Você pode usar datetime.strftimepara obter o horário no formato Época, usando a %ssequência de formato:

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

Nota: Isso funciona apenas no linux, e esse método não funciona com fusos horários.

mipadi
fonte
32
Esse é um comportamento não documentado ( python.org/doc/current/library/datetime.html ). Parece estar trabalhando no linux e não no win32 (gerando ValueError: Invalid format string).
Antony Hatchkins
3
Este método não funciona com fusos horários. A alteração do fuso horário fornecerá o mesmo 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

Aqui está uma datetimesolução menos quebrada para converter do objeto datetime para o carimbo de data / hora posix:

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

Veja mais detalhes em Convertendo datetime.date para carimbo de data e hora UTC em Python .

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

A chave é garantir que todas as datas que você está usando estejam no fuso horário utc antes de iniciar a conversão. Veja http://pytz.sourceforge.net/ para saber como fazer isso corretamente. Ao normalizar para utc, você elimina a ambiguidade das transições de horário de verão. Em seguida, você pode usar com segurança o timedelta para calcular a distância da época unix e depois converter para segundos ou milissegundos.

Observe que o registro de data e hora unix resultante é o próprio fuso horário UTC. Se você deseja ver o registro de data e hora em um fuso horário localizado, precisará fazer outra conversão.

Observe também que isso funcionará apenas para datas 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
fonte
3
nota: não entendo "o carimbo de data / hora [unix] em um fuso horário localizado". O registro de data e hora é o mesmo (segundos decorridos desde 1970-01-01 00:00:00+00:00). Para obter um objeto datetime ingênuo no fuso horário local:datetime.fromtimestamp(ts)
JFS
4

O seguinte é baseado nas respostas acima (mais uma correção para os milissegundos) e emula datetime.timestamp()para o Python 3 antes do 3.3 quando os fusos horários são usados.

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 estritamente à pergunta, faça o seguinte:

datetime_timestamp(my_datetime) + 5 * 60

datetime_timestampfaz parte da data simples . Mas se você estivesse usando esse pacote, provavelmente digitaria:

SimpleDate(my_datetime).timestamp + 5 * 60

que lida com muitos outros formatos / tipos para my_datetime.

andrew cooke
fonte
você não deve adicionar (5 * 60) para adicionar 5 minutos? Eu acho que apenas adicionar 5 adiciona apenas 5 segundos ao registro de data e hora.
precisa saber é o seguinte
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
fonte
1

Observe que as soluções com timedelta.total_seconds()trabalho em python-2.7 +. Use calendar.timegm(future.utctimetuple())para versões inferiores do Python.

mighq
fonte