Jak mogę przekonwertować obiekt datetime na milisekundy od epoki (czas uniksowy) w Pythonie?

Odpowiedzi:

471

Wydaje mi się, że najprostszym sposobem na to jest

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Sophie Alpert
źródło
32
Jak dotąd jest to najlepsze rozwiązanie (jeśli wersja Pythona> 2.7). Ponieważ implementacja %szależy od systemu operacyjnego! Dlatego każdy chce, aby kod działał niezawodnie, niezależnie od tego, jakiego systemu operacyjnego NIGDY nie należy używać %s. Dla 2.3 <py ver <2.7. Można po prostu zbudować coś total_seconds()takiego:delta.days*86400+delta.seconds+delta.microseconds/1e6
Wang
14
Uwaga: dtmusi być w UTC (nie lokalnym). Zobacz podobną odpowiedź ze wsparciem dla
języka
7
Warto wspomnieć, że jeśli wszystko, czego chcesz, to prawdziwy uniksowy znacznik czasu zdefiniowany tutaj en.wikipedia.org/wiki/Unix_time (i tak będzie używać tylko funkcji unix_time z tej odpowiedzi), to powinieneś owinąć delta.total_seconds () z int, aby unikaj
skończenia
1
epoka obliczona przy użyciu utcfromtimestamp(0)może powodować przesunięcie „tz” tylko wtedy, gdy „tz” nie wynosi 0. Wynika to z faktu, że dt in dt- epochma obliczone w nim „tz”, gdzie jako epoką jest czas UTC. Najlepszym sposobem obliczenia epoki jest uwzględnienie epoch = datetime.datetime(1970, 1, 1)strefy czasowej.
ahj
35
Dlaczego och, dlaczego datetime.utcfromtimestamp(0)zwraca datetime bez tzinfo? Jest tam w nazwie metody, utc fromtimestamp. Aby uczynić go nie naiwnym, muszę zrobić coś takiego datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC). Jest to konieczne, jeśli dtwiadomo o strefie czasowej lub dostanieszTypeError: can't subtract offset-naive and offset-aware datetimes
FGreg
168

W Pythonie 3.3 dodano nową metodę timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

Twoje pytanie brzmiało, że potrzebujesz milisekund, które możesz uzyskać w następujący sposób:

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

Jeśli używasz timestampnaiwnego obiektu typu data-godzina, zakłada się, że znajduje się on w lokalnej strefie czasowej. Użyj obiektów datetime uwzględniających strefę czasową, jeśli nie to chcesz.

eshizhan
źródło
28
Uwaga: .timestamp()metoda zakłada, że ​​naiwna wejściowa data / godzina znajduje się w lokalnej strefie czasowej (a czas lokalny może być niejednoznaczny). Jeśli jest w UTC, użyj dt.replace(tzinfo=timezone.utc).timestamp()zamiast tego .
jfs
11
datetime.timestamp () zwraca liczbę epoki sekund jako liczbę zmiennoprzecinkową. Aby uzyskać milisekundy: int (datetime.timestamp () * 1000)
Solar.gy
9
Ta odpowiedź nie jest przykładem do skopiowania i wklejenia, w duchu nieprzyjaznych ludziom dokumentów na docs.python.org/3/library/… - to jest: datetime.datetime.timestamp(datetime.datetime.now())
MarkHu
3
W wersji 3.6 (przynajmniej) datetime.timestamp () zakłada, że ​​strefa czasowa naiwna (tzinfo = None) datetime znajduje się w UTC. Więc zawsze lepiej jest ustawić strefę czasową: datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()ale nie (zawsze) równa datetime.datetime.now().timestamp()(ta ostatnia jest równa reszcie, jeśli lokalna tz to UTC ...)
Bluu
1
Dla twojego zainteresowania jest na odwrót] fromtimestamp( docs.python.org/3/library/… )
Flimm
98
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Lub pomoc modułu czasu (i bez formatowania daty):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Odpowiedzi udzielono z pomocą: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Dokumentacja:

miku
źródło
6
Btw, strftime („% s”) zwraca mi pusty ciąg. Drugi sposób działa dobrze.
Pavel Vlasov
23
Ma tylko drugą celność
shuckc
6
„% s” nie jest obsługiwany przez Python, np. może być nieobecny w systemie Windows. .timetuple()zwraca tm_isdst=-1siłę mktime()do zgadnięcia. Może źle zgadnąć podczas DST (50% szansy na błąd +/- godziny). Zarówno „% s”, jak i mktime()może używać niewłaściwego przesunięcia utc dla dat z przeszłości. Potrzebujesz historycznej bazy danych strefy czasowej, takiej jak dostarczona przez pytzmoduł, aby niezawodnie konwertować czas lokalny na sygnaturę czasową POSIX (chyba że system operacyjny już zapewnia taką db)
jfs
1
time.mktime(ts.timetuple())gdzie ts jest obiektem datetime Pythona
suhailvs
1
@suhail: przeczytaj mój komentarz powyżej na temat mktime/timetuple. timetuple()Usuwa również ułamki sekundy, a celem pytania jest uzyskanie znacznika czasu z milisekundową precyzją.
jfs
13

Tak to robię:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000
estani
źródło
2
@JFSebastian Dzięki za heads up! w rzeczywistości nie bierze się pod uwagę dst. Jeśli twój serwer jest w czasie lokalnym zamiast UTC, to zrobi różnicę. Nie znalazłem (jeszcze) żadnego istotnego powodu, aby ustawić serwery w innym miejscu niż UTC. Moje motto to „pisz UTC, czytaj czas lokalny”, więc zawsze wiesz, gdzie się zatrzymujesz ...
estani
2
Zawsze możesz użyć calendar.timegm zamiast mktime, aby uniknąć problemu z odgadywaniem strefy czasowej przez mktime.
Decko
13

Zalecenia z dokumentacji Python 2.7 dla timemodułu

Konwersja między reprezentacjami czasu

Ankur Agarwal
źródło
@ChristopherBull Wystarczy podzielić liczbę milisekund przez 1000, aby uzyskać sekundy
Jonas
5
Źle zrozumiałeś i źle to zrozumiałeś. Wszystkie sekundy są już dostępne w powyższych funkcjach. Możesz przekonwertować go na milisekundy, ale byłoby to z dokładnością do sekundy.
Christopher Bull
1
Ta odpowiedź korzysta z timemodułu, ale OP zapytał o datetimemoduł. FWIW, najprostsza obecna epoka toint(time.time())
MarkHu
7
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
Corford
źródło
timegm()działa tylko z czasem utc. Nie używa, tm_isdstwięc możesz użyć utcnow.timetuple()zamiast utcnow.utctimetuple(). Uwaga: użycie naive_local_datetime.utctimetuple()byłoby niewłaściwe tutaj. Nie tłumaczy czasu lokalnego na utc. Wywołaj również timetuple()paski ułamków sekundy od wyniku (to, czy ma to znaczenie, zależy od zastosowania). Pytanie dotyczy także * mili * sekund, a nie sekund
jfs
Wolę używać utcnow () i utctimetuple (), aby kod był absolutnie jasny, że masz do czynienia z UTC (w ten sposób każdy, kto go czyta, nie musi pamiętać, że timegm to tylko UTC). utctimetuple () nie implikuje tłumaczenia na naiwny obiekt dttm (stąd inicjowanie dttm za pomocą utcnow ()). Pytanie dotyczy także sekund lub milisekund.
corford
Uwaga: powinienem był powiedzieć w ostatnim komentarzu, że czytam pytanie jako sugerujące, że chciał sekund lub milisekund (prawdopodobnie mój błąd). Dla millis wystarczy pomnożyć przez 1000 (jak sugeruje najlepsza odpowiedź punktowa).
corford
utctimetuple()wycina ułamki sekundy. Pomnożenie przez 1000nie spowoduje ich odzyskania.
jfs
1
Ze względu na sposób, w jaki OP zadał to pytanie, nie jest jasne, czego dokładnie chciał (tj. Prawdziwy uniksowy znacznik czasu lub znacznik czasu z dokładnością do milisekund). Niezależnie od tego oba pytania zostały już zadane i udzielono odpowiedzi w innym miejscu. Powiedziawszy to, myślę, że odpowiedzi tutaj są najszybsze i najczystsze dla ludzi, którzy chcą się rozejrzeć i wykonują niezłą robotę, ilustrując różne rozwiązania problemu.
corford
3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html

Jinesh
źródło
3

Oto kolejna forma rozwiązania z normalizacją obiektu czasowego:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0
arhoskins
źródło
2

Trochę kodu pandy:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
volhv
źródło
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
źródło
9
To jest źle! Harmonogram nie obejmuje milisekundy, dlatego mktime nie zwróci epoki z rozdzielczością milisekundową. W tym przypadku jest to bezużyteczne.
Wang
@ Wang - ma pan rację, to nie zwraca millis, tylko sekundy
MattoTodd,
1
Jeśli jednak usuniesz * 1000, dostaniesz seconds_since_epoch. Ulepszenie tej odpowiedzi, ponieważ w tej chwili nie dbam o milisekundy.
Michael Scheper
0

Oto funkcja, którą wykonałem na podstawie powyższej odpowiedzi

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

Możesz owinąć zwróconą wartość w następujący sposób: str (int (res)) Aby zwrócić ją bez wartości dziesiętnej do użycia jako łańcuch lub po prostu int (bez łańcucha)

Gil Allen
źródło
-14

To inne rozwiązanie dla potajemnej daty i godziny na unixtimestampmillis.

private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static long GetCurrentUnixTimestampMillis()
    {
        DateTime localDateTime, univDateTime;
        localDateTime = DateTime.Now;          
        univDateTime = localDateTime.ToUniversalTime();
        return (long)(univDateTime - UnixEpoch).TotalMilliseconds;
    } 
samsanthosh2008
źródło
2
Pytanie dotyczy języka Python
Stéphane