Python Utwórz uniksowy znacznik czasu pięć minut w przyszłości

297

Muszę utworzyć wartość „Wygasa” za 5 minut w przyszłości, ale muszę ją podać w formacie sygnatury czasowej UNIX. Mam to do tej pory, ale wygląda to na włamanie.

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

Czy istnieje moduł lub funkcja, która wykonuje dla mnie konwersję znacznika czasu?

Daniel Rhoden
źródło
7
Polecam zmianę tematu tego pytania. Pytanie jest dobre, ale nie dotyczy konwersji daty i godziny na uniksowy znacznik czasu. Chodzi o to, jak uzyskać uniksowy znacznik czasu 5 minut w przyszłości.
DA
Nie zgadzam się, @DA Pytanie zasadniczo brzmi: „Muszę wykonać X i Y. Oto, co mam teraz. Jaki jest lepszy sposób na Y?” Może są lepsze sposoby na X, ale tytuł i ciało wyraźnie pytają o Y.
Rob Kennedy
6
Zgadzam się z tobą całkowicie w tej kwestii i uważam, że jest to dobra odpowiedź z dobrą odpowiedzią. Problem polega na tym, że „Python datetime to Unix timestamp” nie odzwierciedla ani pytania, ani odpowiedzi. Znalazłem ten post, szukając sposobu na konwersję i straciłem czas z powodu wprowadzającego w błąd tematu. Sugeruję: „Python, 5 minut w przyszłości jako znacznik czasu UNIX”
DA
3
@JimmyKane - Całkiem wyczerpującą odpowiedź na temat uzyskiwania znacznika czasu z daty można znaleźć tutaj: stackoverflow.com/questions/8777753/...
Tim Tisdall
@TimTisdall tak, ponieważ tytuł został zmieniony, nie ma sensu
Jimmy Kane

Odpowiedzi:

349

Innym sposobem jest użycie calendar.timegm:

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

Jest również bardziej przenośny niż %sflaga do strftime(która nie działa w systemie Windows).

Cat Plus Plus
źródło
Dzięki D.Shawley. help (datetime.timedelta) nie wspomniał o tym skrócie. Miał tylko dni, sekundy i mikrosekundy.
Daniel Rhoden,
12
Należy zauważyć, że połączenie dwóch poprzednich komentarzy, właściwym rozwiązaniem jest: calendar.timegm(future.utctimetuple()). Zapewnia to, że czas UTC jest przekazywany calendar.timegm.
shadowmatter
1
Nie mogę wystarczająco wypowiedzieć się na komentarz @ tumbleweed. Jeśli próbujesz uzyskać sygnaturę czasową UNIX (i dlatego w UTC), użyj calendar.timegm.
Białecki
@tumbleweed, prawda. Jeśli użyjesz mktime plus gmtime (0) spowoduje niezerową różnicę w obie strony dla dowolnej strefy czasowej oprócz UTC: np. `Time.mktime (datetime.fromtimestamp (time.mktime (time.gmtime (0))). Harmonogramuple ())` daje 21600.0sekundy (6 godzin) zamiast 0,0 dla TZ mojej maszyny uniksowej
płyty
Jeśli chcesz uzyskać UTC timestamp należy użyć tego: calendar.timegm(datetime.datetime.utcnow().timetuple()). Użycie metody datetime.datetime.now().utctimetuple()nie działa dla mnie (Python 3.2).
Wookie88,
155

Teraz w Pythonie> = 3.3 możesz po prostu wywołać metodę timestamp (), aby uzyskać znacznik czasu jako zmiennoprzecinkowy.

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
źródło
4
+1 za to. Powinien być wyświetlany znacznie wyżej, ponieważ jest to czysty sposób, jak to zrobić w Pythonie 3
Viktor Stískala
2
@ scott654 Myślałem, że na samym początku komentarza jest to wystarczająco jasne, ale dodałem też trochę pogrubienia.
Tim Tisdall
1
Zrobiłbym notatkę jako komentarz w bloku kodu, ponieważ wszyscy po prostu skanujemy kod w odpowiedziach, a resztę czytamy tylko wtedy, gdy kod wygląda dobrze. Dobra odpowiedź.
Matthew Purdon
2
czas lokalny może być niejednoznaczny . Przykład ( datetime.now()) jest zły, ponieważ zachęca do korzystania z naiwnych obiektów typu data-godzina reprezentujących czas lokalny i może zawieść podczas przejścia DST (z powodu wewnętrznej niejednoznaczności). Możesz ts = datetime.now(timezone.utc).timestamp()zamiast tego użyć .
jfs
@JFSebastian - dobry punkt. Nie chciałem jednak dodawać do importu, więc zmieniłem to na utcnow(). Jestem przyzwyczajony do pracy na komputerach, na których strefa czasowa jest ustawiona na UTC, ale nie należy tego zakładać w tym fragmencie kodu.
Tim Tisdall,
139

Właśnie to znalazłem, a nawet jeszcze krócej.

import time
def expires():
    '''return a UNIX style timestamp representing 5 minutes from now'''
    return int(time.time()+300)
Daniel Rhoden
źródło
12
To nie odpowiada na pytanie.
Jesse Dhillon
22
@JesseDhillon odpowiada na pytanie (zrób znacznik czasu UNIX 5 minut w przyszłości), po prostu nie tytuł.
dbr
3
time.time()można cofnąć. Aby utworzyć wartość „Wygasa” za 5 minut w przyszłości, może być potrzebny time.monotonic()analog w zależności od przypadku użycia.
jfs
@ jf-sebastian time.monotonic () nie zwraca znacznika czasu UNIX, zwraca znacznik czasu z niezdefiniowanym punktem odniesienia.
rspeer
@rspeer: tak, jak mówią doktorzy , tylko różnica między kolejnymi wywołaniami jest poprawna. To, czy monotonicmożna użyć, zależy od przypadku użycia, np. subprocessModuł używa go do implementacji timeoutopcji.
jfs
57

Oto, czego potrzebujesz:

import time
import datetime
n = datetime.datetime.now()
unix_time = time.mktime(n.timetuple())
Ali
źródło
Czym to się różni lub stanowi dodatek do oferowanego „Cat Plus Plus”?
David
3
EG to odpowiedź na pytanie „Datetime Python do sygnatury czasowej Unix”, podczas gdy Cat Plus Plus odpowiedział na pytanie „Datetime Python za 5 minut do datownika Unix”. Więc ten jest czysty i oczywisty.
running.t
@ running.t: przypomina mi: „każdy problem ma proste, oczywiste i złe rozwiązanie”. Zobacz możliwe problemy zmktime(dt.timetuple()) . datetime.now(timezone.utc).timestamp()dostarczone przez @Tim Tisdall jest rozwiązaniem w Python 3.3+. W przeciwnym razie (dt - epoch).total_seconds()można zastosować .
jfs
@JFSebastian co zrobić, jeśli naprawdę chcę, aby wszystkie obliczenia odbywały się w czasie lokalnym? Czy tak jest, gdy np. przeanalizować naiwny ciąg znaków, o którym wiadomo, że jest czasem lokalnym i zdecydować, czy w danym czasie obowiązywał czas letni?
n611x007
1
@naxa: tak, niektóre czasy lokalne są niejednoznaczne lub nie istnieją. Również przesunięcie strefy czasowej może być inne z powodów innych niż DST (potrzebujesz bazy danych tz, takiej jak pytz, aby znaleźć prawidłowe przesunięcie). Czas lokalny oznacza, że ​​jakikolwiek lokalny polityk uważa, że ​​dobrym pomysłem jest mierzenie czasu, to znaczy może być bardzo nieregularny.
jfs
48

datetime.strftimeAby uzyskać czas w formie Epoki, możesz użyć %sciągu formatu:

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

Uwaga: Działa to tylko w systemie Linux i ta metoda nie działa w strefach czasowych.

mipadi
źródło
32
Jest to nieco nieudokumentowane zachowanie ( python.org/doc/current/library/datetime.html ). Wygląda na to, że działa pod Linuksem, a nie pod Win32 (generowanie ValueError: Invalid format string).
Antony Hatchkins,
3
Ta metoda nie działa w strefach czasowych. Zmiana strefy czasowej da ten sam wynik datetime (2013,12,7, tzinfo = strefa czasowa („Ameryka / Chicago”)). Strftime („% s”) 1386385200 datetime (2013,12,7, tzinfo = strefa czasowa („Europa / Ryga ")). Strftime ("% s ") 1386385200
Martins Balodis
11

Oto mniej zepsute datetimerozwiązanie do konwersji z obiektu datetime na znacznik czasu POSIX:

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

Zobacz więcej szczegółów w Konwertowanie datetime.date na znacznik czasu UTC w Pythonie .

jfs
źródło
6
def in_unix(input):
  start = datetime.datetime(year=1970,month=1,day=1)
  diff = input - start
  return diff.total_seconds()
Sravan
źródło
4

Kluczem jest upewnienie się, że wszystkie używane daty znajdują się w strefie czasowej utc przed rozpoczęciem konwersji. Zobacz http://pytz.sourceforge.net/ aby dowiedzieć się, jak to zrobić poprawnie. Normalizując do utc, eliminujesz niejednoznaczność zmian czasu letniego. Następnie możesz bezpiecznie użyć timedelta, aby obliczyć odległość od epoki uniksowej, a następnie przekonwertować na sekundy lub milisekundy.

Zauważ, że wynikowy znacznik czasu unix sam jest w strefie czasowej UTC. Jeśli chcesz zobaczyć znacznik czasu w zlokalizowanej strefie czasowej, musisz wykonać kolejną konwersję.

Pamiętaj też, że będzie to działać tylko w przypadku dat po 1970 roku.

   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
źródło
3
Uwaga: Nie rozumiem „znacznika czasu [unix] w zlokalizowanej strefie czasowej”. Znacznik czasu jest taki sam (minęły sekundy 1970-01-01 00:00:00+00:00). Aby uzyskać naiwny obiekt datetime.fromtimestamp(ts)
daty
4

Poniższe informacje oparte są na powyższych odpowiedziach (plus poprawka na milisekundy) i emulują datetime.timestamp()dla Pythona 3 przed 3.3, gdy używane są strefy czasowe.

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

Aby ściśle odpowiedzieć na zadane pytanie, chcesz:

datetime_timestamp(my_datetime) + 5 * 60

datetime_timestampjest częścią simple-date . Ale jeśli korzystasz z tego pakietu, prawdopodobnie wpisz:

SimpleDate(my_datetime).timestamp + 5 * 60

który obsługuje wiele innych formatów / typów dla my_datetime.

Andrzej Cooke
źródło
nie należy dodawać (5 * 60), aby dodać 5 minut? Myślę, że dodanie 5 dodaje tylko 5 sekund do znacznika czasu.
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
źródło
1

Zauważ, że rozwiązania timedelta.total_seconds()działające na Python-2.7 +. Użyj calendar.timegm(future.utctimetuple())dla niższych wersji Pythona.

potężny
źródło