Konwersja ciągów znaków na datetime w Pythonie

Wprowadzenie

Dane mogą być reprezentowane w różnych formach – i wygodny sposób przedstawiania dat i godzin smyczki. Jednak aby pracować z tymi datami i godzinami w sposób arytmetyczny (taki jak obliczanie różnic czasowych, dodawanie lub odejmowanie czasu itp.) – musimy je przekonwertować na datetime obiekt.

Jedno z najczęstszych źródeł datetime w formacie łańcuchowym to interfejsy API REST, które zwracają łańcuchy agnostyczne, które możemy następnie przekonwertować na inne formaty.

Dodatkowo – strefy czasowe są częstym problemem podczas pracy z obiektami datetime, więc będziemy musieli o tym pomyśleć również podczas konwersji.

W tym przewodniku – przyjrzymy się, jak przekonwertować ciąg znaków data/czas na a datetime obiekt w Pythonie, używając wbudowanego datetime moduł, ale także moduły innych firm, takie jak dateutil, arrow i Maya, uwzględniając strefy czasowe.

Konwersja ciągów przy użyciu datetime

Połączenia data i godzina moduł składa się z trzech różnych typów obiektów: date, time, datetime, date obiekt posiada datę, time trzyma czas i datetime zawiera zarówno datę, jak i czas!

import datetime
print(f'Current date/time: {datetime.datetime.now()}')

Uruchomienie tego kodu spowoduje:

Current date/time: 2022-12-01 10:27:03.929149

Jeśli nie podano niestandardowego formatowania, używany jest domyślny format ciągu, tj. format „2022-12-01 10:27:03.929149” to ISO 8601 format (RRRR-MM-DDTHG:MM:SS.mmmmmm). Jeśli nasz ciąg wejściowy do utworzenia pliku datetime obiekt jest w tym samym formacie ISO 8601 lub jeśli znasz format, który otrzymasz z góry, możemy łatwo przeanalizować go do datetime obiekt:

import datetime

date_time_str = '2022-12-01 10:27:03.929149'

date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

Uruchomienie spowoduje wydrukowanie daty, godziny i daty i godziny:

Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149

Tutaj używamy strptime() metoda, która przyjmuje dwa argumenty:

  • Data w formacie ciągu
  • Format pierwszego argumentu

Określenie formatu w ten sposób sprawia, że ​​parsowanie jest znacznie szybsze datetime nie musi samodzielnie próbować interpretować formatu, co jest znacznie droższe obliczeniowo. Zwracana wartość jest typu datetime.

W naszym przykładzie "2022-12-01 10:27:03.929149" jest ciągiem wejściowym i "%Y-%m-%d %H:%M:%S.%f" jest formatem naszego ciągu daty. zwrócony datetime wartość jest przechowywana jako date_time_obj.

Ponieważ jest to datetime obiekt, możemy nazwać date() i time() metody bezpośrednio na nim. Jak widać na wyjściu, drukuje część „daty” i „czasu” ciągu wejściowego!

Formatuj tokeny

Warto poświęcić chwilę, aby to zrozumieć formatować tokeny - "%Y-%m-%d %H:%M:%S.%f" sprzed.

Każdy token reprezentuje inną część daty i godziny, np. dzień, miesiąc, rok, dzień miesiąca lub tygodnia itp. lista obsługiwanych tokenów jest wystarczająco obszerny, aby umożliwić różne formatowanie. Niektóre z powszechnie używanych, z których również korzystaliśmy wcześniej, to:

  • %Y: Rok (4 cyfry)
  • %m: Miesiąc
  • %d: Dzień miesiąca
  • %H: Godzina (24 godziny)
  • %M: Minuty
  • %S: Sekundy
  • %f: Mikrosekundy

Uwaga: Oczekuje się, że wszystkie te tokeny, z wyjątkiem roku, będą wypełnione zerami (tzn. sierpień jest ósmym miesiącem i są wypełnione zerami, aby 08).

Używanie tokenów formatu strptime() do konwersji ciągu znaków na inny format daty i godziny

Jeśli format łańcucha jest znany, można go łatwo przeanalizować do a datetime obiekt używający strptime(). Rzućmy okiem na nietrywialny przykład, który tłumaczy z jednego formatu na inny:

import datetime

date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')

print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)

Ciąg wejściowy miał jeden format – „17 lipca 2022 r. 9:20”. Znając ten format, zmapowaliśmy elementy składowe do formatu ISO 8601 i przekonwertowaliśmy go na format a datetime obiekt:

Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00

Oto krótka lista typowych dat i godzin w formacie łańcuchowym oraz odpowiadających im formatów dla strptime():

"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"

Możesz analizować ciąg daty i godziny w dowolnym formacie — pod warunkiem, że używasz poprawnego ciągu tokenów formatu dla otrzymywanych danych wejściowych.

Konwertuj ciąg znaków na datę i godzinę ze strefami czasowymi

Obsługa dat i godzin staje się bardziej złożona w przypadku stref czasowych. Wszystkie powyższe przykłady do tej pory są naiwne w stosunku do strefy czasowej. Są to tzw naiwne obiekty datetime.

Jednakże datetime obiekty zawierają pole dokładnie do przechowywania danych związanych ze strefą czasową – tzinfo:

import datetime as dt
dtime = dt.datetime.now()

print(dtime) 
print(dtime.tzinfo) 

Połączenia tzinfo pole ma być a datetime.timezone obiekt, oznaczający informacje o strefie czasowej. Jego None domyślnie i oznacza, że ​​obiekt datetime jest naiwny w strefie czasowej. Bardzo popularną zewnętrzną biblioteką do obsługi stref czasowych jest pytz. Możesz ustawić PyTz obiekty jako tzinfo pole też.

Jeśli jeszcze go nie masz – zainstaluj poprzez:

$ pip install pytz

Korzystając z PyTz, możemy utworzyć kotwicę dla dat i godzin uwzględniających strefę czasową, takich jak UTC:

import datetime as dt
import pytz

dtime = dt.datetime.now(pytz.utc)

print(dtime)
print(dtime.tzinfo)

Wyjście:

2022-12-01 02:07:41.960920+00:00
UTC

Nie jest już 11:2, ale XNUMX:XNUMX, ponieważ przesunęliśmy strefę czasową o kilka godzin wstecz! Ten zmienia strefę czasową daty i godziny.

+00:00 jest różnicą między wyświetlanym czasem a czasem UTC jako globalną kotwicą koordynacji. Ustawiliśmy czas na UTC, więc przesunięcie jest takie 00:00. Jest obiekt rozpoznający strefę czasową.

Podobnie możemy przełączać interpretację tej samej daty i godziny między strefami czasowymi. Przekonwertujmy ciąg, taki jak „2022-06-29 17:08:00” na datę i godzinę, a następnie zlokalizować ustaw go na strefę czasową „America/New_York”:

import datetime as dt
import pytz

date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')

timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)

print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)

Uwaga: Localization zamienia naiwną strefę czasową datetime na datetime uwzględniającą strefę czasową i traktuje strefę czasową jako lokalną. Więc datetime pozostaje taka sama, ale biorąc pod uwagę inną strefę czasową, nie reprezentuje już tego samego punktu w czasie niezwiązanego ze strefami czasowymi.

Dostajemy to samo wartość daty i godziny, przesunięte o -04: 00 w porównaniu do czasu UTC:

2022-06-29 17:08:00-04:00
America/New_York

17:08 w Tokio nie jest w tym samym momencie co 17:08 w Nowym Jorku. 17:08 w Tokio to 3:08 w Nowym Jorku.

Jak znaleźć wszystkie kody/aliasy stref czasowych?

Aby znaleźć wszystkie dostępne strefy czasowe, sprawdź all_timezones pole, które jest listą wszystkich dostępnych stref czasowych:

print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
   print(time_zone)

Zapoznaj się z naszym praktycznym, praktycznym przewodnikiem dotyczącym nauki Git, zawierającym najlepsze praktyki, standardy przyjęte w branży i dołączoną ściągawkę. Zatrzymaj polecenia Google Git, a właściwie uczyć się to!

There are 594 timezones in PyTz

Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...

Zmień strefę czasową Datetime

Możemy przekonwertować strefę czasową uwzględniającą strefę czasową datetime obiekt z jednego regionu do drugiego, zamiast lokalizować naiwną strefę czasową datetime przez pryzmat jakiejś strefy czasowej.

Różni się to od lokalizacji, ponieważ lokalizacja reprezentuje inny punkt w czasie, ale przekształcenie strefy czasowej obiektu reprezentuje ten sam punkt w czasie, z innej perspektywy:

import datetime as dt
import pytz

timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)

timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)


print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)

Najpierw stworzyliśmy jeden obiekt datetime z bieżącym czasem i ustawiliśmy go jako strefę czasową „America/New_York”. Następnie za pomocą astimezone() metoda, przekonwertowaliśmy to datetime do strefy czasowej „Europa/Londyn”. Obydwa datetimes wydrukuje różne wartości, używając przesunięcia UTC jako łącza odniesienia między nimi:

America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00

2:24 następnego dnia w Londynie is ten sam punkt w czasie, co 21:24 poprzedniego dnia w Nowym Jorku ponieważ Londyn jest 5 godzin do przodu.

Zgodnie z oczekiwaniami daty i godziny są różne, ponieważ dzieli je około 5 godzin.

Konwertuj ciąg znaków na datę i godzinę przy użyciu bibliotek stron trzecich

Pythona datetime moduł może konwertować wszystkie różne typy ciągów znaków do formatu datetime obiekt. Ale głównym problemem jest to, że aby to zrobić, musisz utworzyć odpowiedni ciąg kodu formatowania strptime() móc zrozumieć. Utworzenie tego ciągu zajmuje trochę czasu i utrudnia odczytanie kodu.

Zamiast tego możemy użyć innych bibliotek innych firm, aby to ułatwić.

W niektórych przypadkach te biblioteki innych firm mają również lepszą wbudowaną obsługę manipulowania i porównywania dat i godzin, a niektóre mają nawet wbudowane strefy czasowe, więc nie trzeba dołączać dodatkowego pakietu PyTz.

Przyjrzyjmy się kilku z tych bibliotek w poniższych sekcjach.

Konwertuj ciąg na Datetime za pomocą dateutil

Połączenia moduł dateutil jest rozszerzeniem do datetime moduł. Jedną z zalet jest to, że nie musimy przekazywać żadnego kodu analizującego, aby przeanalizować ciąg znaków!

Aby automatycznie przekonwertować ciąg na datetime bez tokena formatu przy użyciu języka Python dateutil:

from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')

print(datetime)

To zdjęcie parse funkcja automatycznie przeanalizuje ciąg znaków! Nie musisz dołączać żadnego ciągu formatującego. Spróbujmy przeanalizować różne typy łańcuchów przy użyciu dateutil:

from dateutil.parser import parse

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = parse(date)
    print(dt.date())
    print(dt.time())
    print(dt.tzinfo)
    print('n')

Wyjście:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None

Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None

Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None

Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None

Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None

Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None

Jak widać, prawie każdy typ łańcucha można łatwo przeanalizować za pomocą metody dateutil moduł.

Chociaż jest to wygodne, pamiętaj, że przewidywanie formatu znacznie spowalnia kod, więc jeśli kod wymaga wysokiej wydajności, może to nie być właściwe podejście do Twojej aplikacji.

Konwertuj ciąg znaków na datę i godzinę za pomocą programu Maya

Maya sprawia również, że bardzo łatwo jest analizować łańcuch i zmieniać strefy czasowe. Aby łatwo przekonwertować ciąg znaków za pomocą Pythona Maya:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Wyjście:

2018-04-29
17:45:25
UTC

Aby przekonwertować czas na inną strefę czasową:

import maya

dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Wyjście:

2018-04-29
13:45:25
America/New_York

Czy to nie jest łatwe w użyciu? spróbujmy maya z tym samym zestawem strun, z którym korzystaliśmy dateutil:

import maya

date_array = [
    '2018-06-29 08:15:27.243860',
    'Jun 28 2018 7:40AM',
    'Jun 28 2018 at 7:40AM',
    'September 18, 2017, 22:19:55',
    'Sun, 05/12/1999, 12:30PM',
    'Mon, 21 March, 2015',
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    'Tuesday , 6th September, 2017 at 4:30pm'
]

for date in date_array:
    print('Parsing: ' + date)
    dt = maya.parse(date).datetime()
    print(dt)
    
    
    
    

Wyjście:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00

Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00

Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00

Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00

Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00

Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00

Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00

Jak widać, wszystkie formaty dat zostały pomyślnie przeanalizowane!

Jeśli nie podamy informacji o strefie czasowej, automatycznie przekonwertuje ją na UTC. Warto więc zauważyć, że my musi zapewnić to_timezone i naive parametry, jeśli czas nie jest w formacie UTC.

Konwertuj ciąg znaków na datę i godzinę za pomocą strzałki

Strzałka to kolejna biblioteka do obsługi datetime w Pythonie. I jak poprzednio z maya, automatycznie określa również format daty i godziny. Po zinterpretowaniu zwraca Pythona datetime obiekt z arrow obiekt.

Aby łatwo przekonwertować ciąg na datetime za pomocą Pythona arrow:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)

Wyjście:

2018-04-29
17:45:25
tzutc()

A oto jak możesz użyć arrow do konwersji stref czasowych za pomocą to() metoda:

import arrow

dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())

Wyjście:

2018-04-29T13:45:25-04:00
2018-04-29
13:45:25

Jak widać ciąg daty i godziny jest konwertowany na region „America/New_York”.

Teraz ponownie użyjmy tego samego zestawu ciągów znaków, którego użyliśmy powyżej:

import arrow

date_array = [
    '2018-06-29 08:15:27.243860',
    
    
    
    
    
    '2018-03-12T10:12:45Z',
    '2018-06-29 17:08:00.586525+00:00',
    '2018-06-29 17:08:00.586525+05:00',
    
]

for date in date_array:
    dt = arrow.get(date)
    print('Parsing: ' + date)
    print(dt)
    
    
    
    

Ten kod zakończy się niepowodzeniem dla ciągów daty i godziny, które zostały wykomentowane, co stanowi ponad połowę naszych przykładów. Dane wyjściowe dla innych ciągów będą następujące:

Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00

Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00

Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00

Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00

Aby poprawnie przeanalizować ciągi daty i godziny, które są skomentowane, musisz przekazać odpowiednie formatować tokeny dać bibliotekom wskazówki, jak je analizować.

Wnioski

W tym artykule pokazaliśmy różne sposoby parsowania łańcucha na a datetime obiekt w Pythonie. Możesz wybrać domyślny Python datetime biblioteka lub dowolna z bibliotek stron trzecich wymienionych w tym artykule, wśród wielu innych.

Główny problem z domyślnym datetime pakiet polega na tym, że musimy ręcznie określić kod parsowania dla prawie wszystkich formatów ciągów daty i godziny. Tak więc, jeśli format łańcucha zmieni się w przyszłości, prawdopodobnie będziesz musiał również zmienić swój kod. Ale wiele bibliotek innych firm, takich jak te wymienione tutaj, obsługuje to automatycznie.

Jeszcze jeden problem, przed którym stoimy, dotyczy stref czasowych. Najlepszym sposobem radzenia sobie z nimi jest zawsze przechowywanie czasu w bazie danych w formacie UTC, a następnie w razie potrzeby przekonwertowanie go na lokalną strefę czasową użytkownika.

Biblioteki te są nie tylko dobre do analizowania ciągów znaków, ale mogą być używane do wielu różnych typów operacji związanych z datą i godziną. Zachęcam do przejrzenia dokumentów w celu szczegółowego poznania funkcjonalności.

Znak czasu:

Więcej z Nadużycie stosu