Jak w Pythonie przekonwertować obiekt `datetime` na sekundy?


226

Przepraszam za proste pytanie ... Jestem nowy w Pythonie ... Szukałem i nic nie działa.

Mam kilka obiektów z datetime i chcę obliczyć liczbę sekund od ustalonego czasu w przeszłości dla każdego z nich (na przykład od 1 stycznia 1970 r.).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Wydaje się, że rozróżnia to tylko daty z różnymi dniami:

t.toordinal()

Każda pomoc jest mile widziana.



2
Prawdopodobnie przekonwertowałbym oba na S od epoki i stamtąd: int(t.timestamp())
nerdwaller

dla operacji odwrotnej przejdź tutaj: konwersja sekund od epoki
Trevor Boyd Smith

Odpowiedzi:


233

Na specjalną datę 1 stycznia 1970 r. Istnieje wiele opcji.

Dla każdej innej daty początkowej musisz uzyskać różnicę między tymi dwiema datami w sekundach. Odejmowanie dwóch dat daje timedeltaobiekt, który od Pythona 2.7 pełni total_seconds()funkcję.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

Data rozpoczęcia jest zwykle określona w UTC, więc aby uzyskać prawidłowe wyniki datetime, należy podać również tę formułę w UTC. Jeśli datetimenie ma Cię jeszcze w UTC, musisz go przekonwertować przed użyciem lub dołączyć tzinfoklasę o odpowiednim przesunięciu.

Jak zauważono w komentarzach, jeśli masz tzinfozałącznik do niego datetime, będziesz go również potrzebować w dniu rozpoczęcia, w przeciwnym razie odejmowanie się nie powiedzie; dla powyższego przykładu dodałbym, tzinfo=pytz.utcjeśli używasz Python 2 lub tzinfo=timezone.utcjeśli używasz Python 3.


1
Python ostrzega mnie teraz: „Błąd typu: nie można odjąć czasów danych naiwnych i uwzględniających przesunięcia” Jakie jest najlepsze rozwiązanie, aby to naprawić?
Aaron Ash

2
@Charybdis, spróbuj datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Mark Ransom,

9
Rozważ użycie: datetime.datetime.utcfromtimestamp(0) Użyłem tego, aby łatwo uzyskać „epokę”. Pamiętaj, że epoka nie zawsze jest taka sama we wszystkich systemach.
DA

3
Zachowaj szczególną ostrożność w strefach czasowych tutaj. Ja na UTC + 2, co oznacza, że produkcja time.time()i datetime.now() - datetime(1970, 1, 1)różnią się o 7200 sekund. Raczej użyć (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Czy nie używać utcfromtimestamp(0), jeśli chcesz przekonwertować datetime w lokalnej strefy czasowej.
Carl

2
@DA: Python nie obsługuje epok innych niż POSIX . Wszystkie systemy, w których działa Python, korzystają z tej samej Epoki: 1970-01-01 00:00:00 UTC
jfs

130

Aby uzyskać czas uniksowy (sekundy od 1 stycznia 1970 r.):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0

22
zachowaj ostrożność, używając time.mktime do wyrażania czasu lokalnego i zależy od platformy
Shih-Wen Su

7
Rzeczywiście bądź ostrożny. Bardzo mnie ugryzło w tyłek
Arg

zakłada, że tjest to czas lokalny. Przesunięcie UTC dla lokalnej strefy czasowej mogło być inne w przeszłości i jeśli mktime()(biblioteka C) nie ma dostępu do danych historycznych strefy czasowej na danej platformie, może się nie powieść ( pytzjest to przenośny sposób na dostęp do bazy danych tz). Również czas lokalny może być niejednoznaczny, np. Podczas przejścia czasu letniego - potrzebujesz dodatkowych informacji, aby ujednoznacznić, np. Jeśli wiesz, że kolejne wartości daty / godziny powinny rosnąć w pliku dziennika
jfs

1
Zachowaj ostrożność podczas korzystania z tego czasu, który ma ułamki sekundy. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())skutkuje 1564819506.0cichym upuszczeniem milisekund, ale datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(odpowiedź Andrzeja Pronobisa) powoduje 1564819506.912oczekiwany wynik.
Alex

128

Począwszy od Python 3.3, datetime.timestamp()metoda ta staje się bardzo łatwa . Przyda się to oczywiście tylko wtedy, gdy potrzebujesz liczby sekund od 1970-01-01 UTC.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

Zwracana wartość będzie liczbą zmiennoprzecinkową reprezentującą nawet ułamki sekundy. Jeśli data-godzina jest naiwna dla strefy czasowej (jak w powyższym przykładzie), zakłada się, że obiekt datetime reprezentuje czas lokalny, tzn. Będzie to liczba sekund od bieżącej godziny w Twojej lokalizacji do 1970-01-01 UTC.


3
Ktokolwiek to ocenił, mógłbyś wyjaśnić dlaczego?
Andrzej Pronobis

5
Zakładam, że opinia negatywna wynika z tagu python-2.7 w pytaniu (to tylko przypuszczenie).
jfs

3
To powinna być zaakceptowana odpowiedź / zaakceptowana odpowiedź powinna zostać odpowiednio zaktualizowana.
DreamFlasher

11
Chyba czas na aktualizację;)
DreamFlasher

czy można obliczyć tę odległość od innej daty początkowej? (Mam na myśli zmianę daty 1970-01-01)
pellerossa pelles

29

Może nie na temat: aby uzyskać czas UNIX / POSIX z datetime i przekonwertować go z powrotem:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Zauważ, że różne strefy czasowe mają wpływ na wyniki, np. Moje obecne zwroty TZ / DST:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

dlatego należy rozważyć normalizację do UTC przy użyciu wersji funkcji UTC.

Pamiętaj, że poprzedni wynik może być wykorzystany do obliczenia przesunięcia UTC bieżącej strefy czasowej. W tym przykładzie jest to + 1h, tj. UTC + 0100.

Bibliografia:


mktime()może zawieść . Ogólnie rzecz biorąc, musisz pytzprzekonwertować czas lokalny na utc, aby uzyskać znacznik czasu POSIX.
jfs

calendar.timegm () wydaje się być utc wersją time.mktime ()
frankster

27

int (t.strftime("%s")) działa również


1
Działa dla mnie w Pythonie 2.7 z import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(jak określono przez OP). Ale tak naprawdę wątpię, aby% s to ostatnio dodany format czasu.
dan3

1
@ dan3: źle. %snie jest obsługiwany (może działać na niektórych platformach iff tjest naiwnym obiektem typu data-godzina reprezentującym czas lokalny i jeśli lokalna biblioteka C ma dostęp do bazy danych tz, w przeciwnym razie wynik może być nieprawidłowy). Nie używaj tego.
jfs

%snie jest nigdzie udokumentowane. Siałem to w prawdziwym kodzie i zastanawiałem się, co to jest, i zajrzałem do dokumentacji i nie ma czegoś takiego jak %s. Jest tylko z dużym S tylko na kilka sekund.
VStoykov

13

z dokumentacji Pythona:

timedelta.total_seconds()

Zwraca całkowitą liczbę sekund zawartą w czasie trwania. Równoważny

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

obliczone przy włączonym prawdziwym dzieleniu.

Należy pamiętać, że w przypadku bardzo dużych przedziałów czasowych (dłuższych niż 270 lat na większości platform) metoda ta straci mikrosekundową dokładność.

Ta funkcja jest nowa w wersji 2.7.


1
jest mały problem z obliczeniami, musi to być 10 6 zamiast 10 * 6 ... td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu

@ sdu great catch - podwójna gwiazdka jest w mojej odpowiedzi, ale przepełnienie stosu ją pochłania, próby sprostowania tylko pogrubiają tekst.
Michael

2

Aby przekonwertować obiekt datetime reprezentujący czas w UTC na znacznik czasu POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

Aby przekonwertować obiekt datetime reprezentujący czas w lokalnej strefie czasowej na znacznik czasu POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Zobacz Jak przekonwertować czas lokalny na UTC w Pythonie? Jeśli baza danych tz jest dostępna na danej platformie; rozwiązanie tylko dla stdlib może działać .

Skorzystaj z łączy, jeśli potrzebujesz rozwiązań dla <3.3wersji Python.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.