Karakterláncok konvertálása dátumidővé Pythonban

Bevezetés

Az adatok különböző formákban jeleníthetők meg – a dátumok és időpontok kényelmes ábrázolásának módja húrok. Ahhoz azonban, hogy ezekkel a dátumokkal és időpontokkal aritmetikai módon dolgozhassunk (mint például az időeltérések kiszámítása, az idő hozzáadása vagy eltávolítása stb.) – át kell alakítanunk őket egy datetime tárgy.

Az egyik leggyakoribb forrás a karakterlánc-formátumú dátumidő REST API-k, amelyek agnosztikus karakterláncokat adnak vissza, amelyeket aztán konvertálhatunk más formátumokba.

Ezenkívül – az időzónák gyakori fejfájást okoznak a dátumidő objektumokkal való munka során, ezért a konvertálás során is gondolnunk kell erre.

Ebben az útmutatóban megnézzük, hogyan lehet egy karakterlánc dátumot/időt a datetime objektum Pythonban, a beépített segítségével datetime modul, hanem harmadik féltől származó modulok is, mint pl dateutil, arrow és Maya, figyelembe véve az időzónákat.

Karakterláncok konvertálása datetime használatával

A dátum idő A modul három különböző objektumtípusból áll: date, timeés datetime Az date az objektum tartalmazza a dátumot, time tartja az időt, és datetime dátumot és időt is tartalmaz!

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

A kód futtatása a következőket eredményezné:

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

Ha nincs megadva egyéni formázás, a rendszer az alapértelmezett karakterlánc-formátumot használja, azaz a „2022-12-01 10:27:03.929149” formátum ISO 8601 formátum (ÉÉÉÉ-HH-NNTHH:PP:SS.mmmmmm). Ha a bemeneti karakterláncunk létrehozásához a datetime az objektum ugyanabban az ISO 8601 formátumban van, vagy ha előre tudja, hogy milyen formátumot fog kapni, könnyen elemezhetjük egy datetime tárgy:

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)

Futtatása kinyomtatja a dátumot, az időt és a dátum-időt:

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

Itt használjuk a strptime() módszer, amely két érvet fogad el:

  • A karakterlánc-formátumú dátum
  • Az első argumentum formátuma

A formátum ilyen megadása sokkal gyorsabbá teszi az elemzést, mivel datetime nem kell önállóan próbálkoznia a formátum értelmezésével, ami számításilag sokkal drágább. A visszatérési érték a következő típusú datetime.

A mi példánkban "2022-12-01 10:27:03.929149" a bemeneti karakterlánc és "%Y-%m-%d %H:%M:%S.%f" a dátum karakterláncunk formátuma. A visszatért datetime értékét a rendszer tárolja date_time_obj.

Mivel ez egy datetime objektum, nevezhetjük a date() és a time() módszerek közvetlenül rajta. Amint a kimenetből látható, kiírja a bemeneti karakterlánc „dátum” és „idő” részét!

Formátum tokenek

Érdemes egy percet szánni a megértésre formátumú tokenek - A "%Y-%m-%d %H:%M:%S.%f" ezelőttről.

Mindegyik token a dátum-idő különböző részét jelöli, mint például a nap, a hónap, az év, a hónap vagy a hét napja stb. támogatott tokenek listája elég kiterjedt ahhoz, hogy lehetővé tegye a különféle formázásokat. Néhány gyakran használt, amit korábban is használtunk:

  • %Y: Év (4 számjegy)
  • %m: Hónap
  • %d: A hónap napja
  • %H: óra (24 óra)
  • %M: Percek
  • %S: Másodpercek
  • %f: Mikroszekundum

Jegyzet: Az év kivételével ezek a zsetonok várhatóan nullázottak (azaz augusztus a 8. hónap, és nullázva van 08).

Az strptime() formátum tokenek használata a karakterlánc különböző dátum-idő formátummá alakításához

Ha egy karakterlánc formátuma ismert, könnyen értelmezhető a-ba datetime objektum használatával strptime(). Vessünk egy pillantást egy nem triviális példára, amely egyik formátumról a másikra fordítható:

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)

A beviteli karakterlánc egy formátumú volt – „17. július 2022. 9:20”. Ennek a formátumnak a ismeretében az alkotóelemeket leképeztük az ISO 8601 formátumra és átalakítottuk egy datetime tárgy:

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

Íme egy rövid lista az általánosan használt karakterlánc-formátumú dátumokról és a hozzájuk tartozó formátumokról 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"

Bármilyen formátumú dátum-idő karakterláncot elemezhet – mindaddig, amíg a kapott bemenethez a megfelelő formátumjogkivonatokat használja.

Karakterlánc konvertálása dátum-idővé az időzónákkal

A dátum-idő kezelése bonyolultabbá válik az időzónák kezelésekor. Az összes fenti példa eddig naiv az időzónához képest. Ezek az úgynevezett naiv dátumidő objektumok.

Azonban a datetime az objektumok pontosan tartalmaznak egy mezőt az időzónához kapcsolódó adatok tárolására – tzinfo:

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

print(dtime) 
print(dtime.tzinfo) 

A tzinfo mező célja, hogy a datetime.timezone objektum, amely az időzóna információt jelöli. ez van None alapértelmezés szerint, és azt jelzi, hogy a datetime objektum időzóna-naiv. Az időzónák kezelésére nagyon gyakori külső könyvtár pytz. Beállíthatja PyTz tárgyakat, mint a tzinfo mező is.

Ha még nincs meg, telepítse az alábbi módon:

$ pip install pytz

A PyTz használatával horgonyt hozhatunk létre az időzóna-tudatos dátumokhoz, például UTC:

import datetime as dt
import pytz

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

print(dtime)
print(dtime.tzinfo)

output:

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

Már nem 11 óra van, hanem hajnali 2 óra, mert néhány órával korábban állítottuk be az időzónát! Ez megváltoztatja az időzónát a dátum és idő.

+00:00 a különbség a megjelenített idő és az UTC idő között, mint globális koordinációs horgony. Az időt UTC-re állítottuk be, tehát az eltolás az 00:00. Ez egy időzóna-tudatos objektum.

Hasonlóképpen válthatjuk ugyanazt a dátumidő-értelmezést az időzónák között. Alakítsunk át egy karakterláncot, például „2022-06-29 17:08:00” dátum-idővé, majd lokalizálni az „Amerika/New_York” időzónához:

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)

Jegyzet: Honosítás az időzóna-naiv dátumidőt időzóna-tudatos dátumidővé változtatja, és az időzónát helyiként kezeli. Így a dátum és idő változatlan marad, de a különböző időzónák miatt már nem ugyanazt az időpontot jelenti, az időzónákhoz nem kötve.

Ugyanazt kapjuk dátum és idő érték, ellensúlyozza -04: 00 UTC időhöz képest:

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

17:08 Tokióban nem ugyanabban az időpontban, mint 17:08-kor New Yorkban. 17:08 Tokióban és 3:08 New Yorkban.

Hogyan lehet megtalálni az összes időzóna kódot/álnevet?

Az összes elérhető időzóna megtalálásához ellenőrizze a all_timezones mező, amely az összes elérhető időzóna listája:

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

Tekintse meg gyakorlatias, gyakorlati útmutatónkat a Git tanulásához, amely tartalmazza a bevált gyakorlatokat, az iparág által elfogadott szabványokat és a mellékelt csalólapot. Hagyd abba a guglizást a Git parancsokkal, és valójában tanulni meg!

There are 594 timezones in PyTz

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

Módosítsa a dátum és idő időzónáját

Átalakíthatjuk egy időzóna időzónáját datetime objektumot egyik régióból a másikba, ahelyett, hogy egy időzóna-naiv dátumidőt lokalizálna egy időzóna lencséjén keresztül.

Ez különbözik a lokalizációtól, mivel a lokalizáció egy másik időpontot jelent, de egy objektum időzónájának konvertálása ugyanazt az időpontot ábrázolja, más lencsén keresztül:

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)

Először létrehoztunk egy datetime objektumot az aktuális idővel, és beállítottuk „Amerika/New_York” időzónának. Ezután a astimezone() módszerrel, ezt konvertáltuk datetime az „Európa/London” időzónához. Mindkét datetimeAz s különböző értékeket fog kiírni, az UTC-eltolást referenciaként használva közöttük:

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 másnap Londonban is ugyanabban az időpontban, mint előző nap 21:24-kor New Yorkban mivel London 5 órával előrébb van.

Ahogy az várható volt, a dátumok és időpontok eltérőek, mivel körülbelül 5 óra különbség van közöttük.

Karakterlánc konvertálása dátumidővé harmadik féltől származó könyvtárak használatával

Pythoné datetime modul képes az összes különböző típusú karakterláncot a datetime tárgy. De a fő probléma az, hogy ehhez létre kell hozni a megfelelő formázási kódot strptime() képes megérteni. Ennek a karakterláncnak a létrehozása időt vesz igénybe, és megnehezíti a kód olvasását.

Ehelyett más, harmadik féltől származó könyvtárakat is használhatunk, hogy megkönnyítsük.

Egyes esetekben ezek a harmadik féltől származó könyvtárak jobb beépített támogatással is rendelkeznek a dátum-idő manipulálásához és összehasonlításához, sőt néhányban beépített időzónák is vannak, így nincs szükség további PyTz-csomag beépítésére.

Nézzünk meg néhány ilyen könyvtárat a következő szakaszokban.

Konvertálja a karakterláncot Datetime-re a dateutil segítségével

A dateutil modul kiterjesztése a datetime modul. Egyik előnye, hogy nem kell értelmező kódot átadnunk egy karakterlánc elemzéséhez!

Karakterlánc automatikus konvertálása dátum-idővé formátumjogkivonat nélkül a Python segítségével dateutil:

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

print(datetime)

Ezt parse függvény automatikusan elemzi a karakterláncot! Nem kell megadnia semmilyen formátumú karakterláncot. Próbáljunk meg különböző típusú karakterláncokat elemezni a használatával 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')

output:

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

Látható, hogy szinte bármilyen típusú karakterlánc könnyen értelmezhető a dateutil modult.

Bár ez kényelmes, emlékezzen a korábbiakra, hogy a formátum előrejelzése sokkal lassítja a kódot, így ha a kód nagy teljesítményt igényel, akkor lehet, hogy ez nem a megfelelő megközelítés az alkalmazás számára.

Konvertálja a karakterláncot Datetime-re Mayával

Maya emellett nagyon egyszerűvé teszi a karakterláncok elemzését és az időzónák megváltoztatását. Egy karakterlánc egyszerű konvertálása Python Mayával:

import maya

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

output:

2018-04-29
17:45:25
UTC

Az idő más időzónára való konvertálásához:

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)

output:

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

Most nem olyan könnyű használni? Próbáljuk ki maya ugyanazzal a karakterlánc-készlettel, amelyet mi is használtunk 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)
    
    
    
    

output:

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

Amint láthatja, az összes dátumformátum elemzése sikeresen megtörtént!

Ha nem adjuk meg az időzóna adatait, akkor automatikusan UTC-re konvertálja. Fontos tehát megjegyezni, hogy mi kell biztosítja a to_timezone és a naive paramétereket, ha az idő nem UTC-ben van.

Konvertálja a karakterláncot dátum-idővé a nyíl segítségével

nyíl egy másik könyvtár a dátumidő kezeléséhez Pythonban. És mint korábban vele maya, a dátum és idő formátumát is automatikusan kitalálja. Az értelmezés után Pythont ad vissza datetime tárgy a arrow tárgy.

Egy karakterlánc egyszerű konvertálása dátum-idővé Python segítségével arrow:

import arrow

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

output:

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

És itt van, hogyan használhatja arrow az időzónák konvertálásához a to() eljárás:

import arrow

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

output:

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

Amint láthatja, a dátum-idő karakterlánc az „Amerika/New_York” régióra konvertálódik.

Most ismét használjuk ugyanazt a karakterlánc-készletet, amelyet fentebb használtunk:

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)
    
    
    
    

Ez a kód sikertelen lesz a megjegyzésben szereplő dátum-idő karakterláncoknál, ami a példáink több mint fele. A többi karakterlánc kimenete a következő lesz:

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

A megjegyzésben szereplő dátum-idő karakterláncok helyes elemzéséhez át kell adnia a megfelelőt formátumú tokenek hogy a könyvtár támpontokat adjon az elemzéséhez.

Következtetés

Ebben a cikkben különböző módokat mutattunk be egy karakterlánc a-ba történő elemzésére datetime objektum Pythonban. Választhatja az alapértelmezett Pythont datetime könyvtárat vagy az ebben a cikkben említett harmadik féltől származó könyvtárakat, sok más mellett.

A fő probléma az alapértelmezett datetime csomag lényege, hogy szinte minden dátum-idő karakterlánc formátumhoz kézzel kell megadnunk az elemző kódot. Tehát, ha a karakterlánc formátuma a jövőben megváltozik, valószínűleg módosítania kell a kódot is. De sok harmadik féltől származó könyvtár, mint például az itt említettek, automatikusan kezeli.

Még egy probléma, amellyel szembesülünk, az időzónák kezelése. A kezelés legjobb módja az, ha az időt UTC formátumban tárolja az adatbázisában, majd szükség esetén konvertálja a felhasználó helyi időzónájába.

Ezek a könyvtárak nem csak a karakterláncok elemzésére alkalmasak, hanem számos különböző típusú dátum-időhöz kapcsolódó művelethez is használhatók. Azt javaslom, hogy nézze át a dokumentumokat, hogy részletesen megismerje a funkciókat.

Időbélyeg:

Még több Stackabus