Konwertuj datetime Pythona na epokę za pomocą strftime


209

Mam czas w UTC, od którego chcę liczbę sekund od epoki.

Używam strftime, aby przekonwertować go na liczbę sekund. Biorąc za przykład 1 kwietnia 2012 r.

>>>datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

1 kwietnia 2012 UTC z epoki to 1333238400, ale powyższy zwraca 1333234800, który różni się o 1 godzinę.

Wygląda więc na to, że strftime bierze pod uwagę mój czas systemowy i stosuje gdzieś zmianę strefy czasowej. Myślałem, że data i godzina była czysto naiwna?

Jak mogę to obejść? Jeśli to możliwe, unikaj importowania innych bibliotek, chyba że standardowe. (Mam obawy dotyczące przenośności).



11
Czy jestem jedynym, który zauważa, że ​​używasz literałów ósemkowych w liczbach?
Fish Monitor


3
Nowszy Python 3.3+ madatetime.datetime.timestamp(datetime.datetime.utcnow())
MarkHu

Odpowiedzi:


389

Jeśli chcesz przekonwertować datetime Pythona na sekundy od epoki, możesz to zrobić jawnie:

>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

W Python 3.3+ możesz timestamp()zamiast tego użyć :

>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

Dlaczego nie powinieneś używać datetime.strftime('%s')

Python tak naprawdę nie obsługuje% s jako argumentu dla strftime (jeśli sprawdzisz na http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior nie ma go na liście), jedyne powodem tego jest fakt, że Python przekazuje informacje do strftime systemu, który wykorzystuje lokalną strefę czasową.

>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

7
Oszalałem próbując dowiedzieć się, dlaczego często widzę strftime („% s”), ale nie ma go w dokumentacji. Dziękuję za nic tego!
Jonathan Vanasco

54
nie używaj .strftime("%s"): nie jest obsługiwany, nie jest przenośny, może dyskretnie wygenerować zły wynik dla świadomego obiektu datetime, nie powiedzie się, jeśli dane wejściowe są w UTC (jak w pytaniu), ale lokalna strefa czasowa nie jest w UTC
jfs

2
@earthmeLon Braketing jest nieprawidłowy. Timedeltas (utworzony przez odjęcie dwóch czasów danych) ma total_seconds, ale czasy danych nie.
jleahy,

2
To nie działa dla mnie:AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
Michael

3
@ Michael Ta funkcja jest nowa w Pythonie 2.7, musisz używać starszej wersji. W przypadku wersji wcześniejszych niż 2.7 możesz to zrobić td.seconds + td.days*24*3600. To odrzuca część mikrosekund.
jleahy

100

Miałem poważne problemy ze strefami czasowymi i tym podobne. Sposób, w jaki Python radzi sobie z tym wszystkim, jest dość mylący (dla mnie). Wydaje się, że wszystko działa dobrze przy użyciu modułu kalendarza (patrz linki 1 , 2 , 3 i 4 ).

>>> import datetime
>>> import calendar
>>> aprilFirst=datetime.datetime(2012, 04, 01, 0, 0)
>>> calendar.timegm(aprilFirst.timetuple())
1333238400

7
+1, ponieważ jest to jedyna odpowiedź, która działa na dane wejściowe w pytaniu.
jfs

czy to jest przenośne?
benjaminz

1
Należy to zaznaczyć jako słuszną odpowiedź, ponieważ stanowi to odpowiedź na pytanie, o które chodzi. vnice kudos
Leo Prince

2
To „działa”, ale zwróć uwagę na pytanie: „Mam czas w UTC”. Ta metoda zawsze używa lokalnej strefy czasowej systemu. Nie ma możliwości określenia strefy czasowej. Gdyby aprilFirstw tym przykładzie wystąpiła „świadoma” instancja i używała strefy czasowej innej niż strefa czasowa systemu, wynik nie byłby prawidłowy (strefa czasowa gubi się w timetuple()wywołaniu). Aby uzyskać właściwą odpowiedź na „świadomą” datę, możesz użyć awaredt.timestamp()najnowszego Pythona 3. W Pythonie 2 jest trudniej; Jednym ze sposobów jest użycie arrowbiblioteki. arrow.get(awaredt).timestampzrobię to dobrze.
Adam Williamson

1
Dobra uwaga, @AdamWilliamson, ale kod w tym przykładzie nie lokalizuje datetimeobiektu, więc założyłem, że „mam czas w UTC” oznaczało, że OP miał nieświadomy datetimeobiekt, który, jak zakładano, znajdował się w UTC, dla którego chciał dostać epoch(jeśli datetimezdarzyło się, że był świadomy TZ, to może rzeczywiście zmienić rzeczy). Pamiętaj też, że ta odpowiedź ma prawie 8 lat i od tego czasu wydarzyło się wiele rzeczy ( arrowna przykład została wydana w 2013 r.)
BorrajaX

35
import time
from datetime import datetime
now = datetime.now()

time.mktime(now.timetuple())

1
jest to niepoprawny sposób pisania time.time()( mktime()może się nie powieść podczas przejścia DST, gdy time.time()nadal działa). I nie odpowiada na pytanie, chyba że lokalna strefa czasowa to UTC (dane wejściowe w pytaniu są w UTC). Nawet jeśli dane wejściowe reprezentowałyby czas lokalny, mktime()mogą również zawieść dla przeszłych / przyszłych dat, jeśli nie będą korzystać z bazy danych tz i jeśli lokalna strefa czasowa może mieć różne przesunięcia utc na przestrzeni lat, np. Europa / Moskwa w latach 2010-2015 - - zamiast tego używaj czasu UTC (jak w pytaniu) lub obiektów daty-godziny obsługujących strefę czasową.
jfs

oto więcej problemów z konwertowaniem czasu lokalnego (np. zwróconego przez .now()) na znacznik czasu epoki (zwrócony przez mktime()) . Jeśli to przeczytasz; rozumiesz, dlaczego dane wejściowe UTC (użyte w pytaniu) są (o wiele) lepsze niż naiwny obiekt datetime reprezentujący czas lokalny
jfs

14
import time
from datetime import datetime
now = datetime.now()

# same as above except keeps microseconds
time.mktime(now.timetuple()) + now.microsecond * 1e-6

(Przepraszam, nie pozwala mi to komentować istniejącej odpowiedzi)


Jest tak, ponieważ time.mktime nie uwzględnia części mikrosekundowej, prawda?
Eduardo

1
Poprawny. Struktura krotki czasowej (oparta na strut C) nie ma miejsca na mikrosekundy, więc musimy pobrać informacje z obiektu datetime i dodać je na końcu.
Charles Plager


Na moich komputerach działa to poprawnie, mimo że moją strefą czasową jest ET.
Charles Plager

1
To da ci różne znaczniki czasu w różnych systemach w zależności od lokalnego czasu systemu.
Yousaf

6

jeśli potrzebujesz tylko znacznika czasu w czasie uniksowym / epoki, ta jedna linia działa:

created_timestamp = int((datetime.datetime.now() - datetime.datetime(1970,1,1)).total_seconds())
>>> created_timestamp
1522942073L

i zależy tylko od datetime pracy w python2 i python3


2

Działa to w Python 2 i 3:

>>> import time
>>> import calendar
>>> calendar.timegm(time.gmtime())
1504917998

Wystarczy postępować zgodnie z oficjalnymi dokumentami ... https://docs.python.org/2/library/time.html#module-time


1) Zakłada się, że chcesz teraz przekonwertować, a nie losowy obiekt datetime. 2) Nie potrzebujesz kalendarza. time.mktime (randomDateTime.timetuple ()) + randomDateTime.microsecond * 1e-6
Charles Plager

@CharlesPlager time.mktime jest niepoprawny; interpretuje argument w lokalnej strefie czasowej, podczas gdy OP chce czasu interpretowanego w UTC (tak jak robi to kalendarz.timegm).
stewbasic

To jest dla mnie najdokładniejsza odpowiedź, jeśli chcesz przekonwertować swój czas w GMT i chcesz, aby tak było w przypadku konwersji na znacznik czasu epoki.
Yousaf

Wystarczy postępować zgodnie z odpowiedzią, calendar.timegm (datetime.strptime („2019-05-03T05: 40: 09.770494 + 00: 00” [: 16], „% Y-% m-% dT% H:% M”). timetuple ()) Mam znacznik czasu w utc i bez względu na system, na którym działasz, daje mi prawidłowy znacznik czasu, sztuczka polega na użyciu strptime.timetumple
Yousaf

2

Aby uzyskać jednoznaczne rozwiązanie niezależne od strefy czasowej, użyj biblioteki pytz.

import datetime
import pytz

pytz.utc.localize(datetime.datetime(2012,4,1,0,0), is_dst=False).timestamp()

Wyjście (liczba zmiennoprzecinkowa): 1333238400.0


widziałem podobną odpowiedź na stackoverflow.com/a/21145908/4355695 , ale ten jako jedno-liniowy jest świetny w moim przypadku użycia, w którym przychodzące dane są w UTC, a tylko .timestamp () zakładał, że jest to czas lokalny .
Nikhil VJ

Działa to dla dat mniejszych niż 1970. Dziękuję. Przyjęta odpowiedź nie działa dla dat krótszych niż 1970. (Python 3.7.3 64-bit Anaconda3)
canbax

-1

W Pythonie 3.7

Zwraca datę i godzinę odpowiadającą łańcuchowi daty w jednym z formatów emitowanych przez date.isoformat () i datetime.isoformat (). W szczególności ta funkcja obsługuje ciągi w formacie (-ach) RRRR-MM-DD [* HH [: MM [: SS [.fff [fff]]]] [+ HH: MM [: SS [.ffffff]]]] , gdzie * może pasować do dowolnego pojedynczego znaku.

https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat


1
Pamiętaj, że zostało to wprowadzone w Pythonie 3.7.
keithpjolley
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.