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.