Introduktion
Data kan repræsenteres i forskellige former - og en praktisk måde at repræsentere datoer og klokkeslæt er strygere. Men for at arbejde med disse datoer og tidspunkter på en aritmetisk måde (såsom beregning af tidsforskelle, tilføjelse eller fjernelse af tid osv.) – skal vi konvertere dem til en datetime
objekt.
En af de mest almindelige kilder til strengformaterede datotider er REST API'er, der returnerer agnostiske strenge, som vi så kan konvertere til andre formater.
Derudover – tidszoner er en almindelig hovedpine, når det kommer til at arbejde med datetime-objekter, så vi bliver nødt til at tænke på det, mens vi konverterer.
I denne vejledning – vi tager et kig på, hvordan man konverterer en strengdato/tid til en
datetime
objekt i Python ved hjælp af den indbyggededatetime
modul, men også tredjepartsmoduler som f.eksdateutil
,arrow
og Maya, der tager højde for tidszoner.
Konvertering af strenge ved hjælp af datetime
dato tid Modulet består af tre forskellige objekttyper: date
, time
og datetime
. Det date
objektet holder datoen, time
holder tiden, og datetime
holder både dato og klokkeslæt!
import datetime
print(f'Current date/time: {datetime.datetime.now()}')
Kørsel af denne kode vil resultere i:
Current date/time: 2022-12-01 10:27:03.929149
Når der ikke er angivet nogen brugerdefineret formatering, bruges standardstrengformatet, dvs. formatet for "2022-12-01 10:27:03.929149" er i ISO 8601 format (ÅÅÅÅ-MM-DDTHH:MM:SS.mmmmmm). Hvis vores inputstreng til at skabe en datetime
objektet er i det samme ISO 8601-format, eller hvis du kender det format, du vil modtage på forhånd, kan vi nemt analysere det til en datetime
objekt:
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)
Når du kører det, udskrives dato, klokkeslæt og dato-klokkeslæt:
Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149
Her bruger vi strptime()
metode, som accepterer to argumenter:
- Den strengformaterede dato
- Formatet af det første argument
Angivelse af formatet som dette gør parsingen meget hurtigere siden datetime
behøver ikke at prøve at fortolke formatet på egen hånd, hvilket er meget dyrere beregningsmæssigt. Returværdien er af typen datetime
.
I vores eksempel, "2022-12-01 10:27:03.929149"
er inputstrengen og "%Y-%m-%d %H:%M:%S.%f"
er formatet på vores datostreng. Den vendte tilbage datetime
værdi gemmes som date_time_obj
.
Da dette er en datetime
objekt, kan vi kalde date()
, time()
metoder direkte på det. Som du kan se på outputtet, udskriver den 'dato' og 'klokkeslæt'-delen af inputstrengen!
Formater tokens
Det er værd at bruge et øjeblik på at forstå formatere tokens - det "%Y-%m-%d %H:%M:%S.%f"
fra før.
Hvert token repræsenterer en anden del af dato-klokkeslæt, som dag, måned, år, dag i måneden eller ugen osv. liste over understøttede tokens er omfattende nok til at muliggøre forskellige formateringer. Nogle af de almindeligt anvendte, som vi også har brugt tidligere, er:
%Y
: År (4 cifre)%m
: Måned%d
: Dag i måneden%H
: Time (24 timer)%M
: Minutter%S
: Sekunder%f
: Mikrosekunder
Bemærk: Alle disse tokens, undtagen året, forventes at være nulpolstret (dvs. august er den 8. måned og er nulpolstret til 08
).
Brug af strptime()-formattokens til at konvertere streng til et andet Datetime-format
Hvis formatet af en streng er kendt, kan den let parses til en datetime
objekt ved hjælp af strptime()
. Lad os tage et kig på et ikke-trivielt eksempel, der oversættes fra et format til et andet:
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)
Indtastningsstrengen havde ét format – "17. juli 2022 9:20 AM". Da vi kendte dette format, kortlagde vi de indgående elementer til ISO 8601-formatet og konverterede det til et datetime
objekt:
Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00
Her er en kort liste over almindelige strengformaterede datotider og deres tilsvarende formater for 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"
Du kan parse en dato-tid-streng af ethvert format – så længe du bruger den korrekte streng af format-tokens til det input, du modtager.
Konverter streng til datotid med tidszoner
Håndtering af dato-tider bliver mere kompleks, mens man håndterer tidszoner. Alle ovenstående eksempler indtil videre er naive i forhold til tidszonen. Disse er kendt som naive datetime-objekter.
Imidlertid datetime
objekter indeholder et felt nøjagtigt til lagring af tidszone-relaterede data – tzinfo
:
import datetime as dt
dtime = dt.datetime.now()
print(dtime)
print(dtime.tzinfo)
tzinfo
felt er beregnet til at være en datetime.timezone
objekt, der angiver tidszoneinformationen. Det er None
som standard og angiver, at datetime-objektet er tidszone-naivt. Et meget almindeligt eksternt bibliotek til håndtering af tidszoner er pytz
. Du kan indstille PyTz genstande som tzinfo
felt også.
Hvis du ikke allerede har det – installer det via:
$ pip install pytz
Ved hjælp af PyTz kan vi oprette et anker til tidszonebevidste datotider, såsom 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
Klokken er ikke længere 11:2, men XNUMX:XNUMX, fordi vi har sat tidszonen et par timer tilbage! Det her ændrer tidszonen af datoen.
+00:00
er forskellen mellem den viste tid og UTC-tiden som det globale koordinationsanker. Vi har indstillet tiden til at være i UTC, så forskydningen er 00:00
. Dette er et tidszone-bevidst objekt.
På samme måde kan vi skifte den samme dato og klokkeslæts fortolkning mellem tidszoner. Lad os konvertere en streng, f.eks. "2022-06-29 17:08:00" til et dato-klokkeslæt og derefter lokaliser det til "America/New_York" tidszonen:
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)
Bemærk: Lokalisering forvandler en tidszone-naiv datetime til en tidszone-bevidst datetime og behandler tidszonen som den lokale. Således dato og klokkeslæt forbliver den samme, men givet den forskellige tidszone, repræsenterer den ikke længere det samme tidspunkt ubundet fra tidszoner.
Vi får det samme datetime værdi, opvejet af -04: 00 sammenlignet med UTC-tiden:
2022-06-29 17:08:00-04:00
America/New_York
17:08 i Tokyo er ikke samme tidspunkt som 17:08 i New York. 17:08 i Tokyo er 3:08 i New York.
Hvordan finder jeg alle tidszonekoder/aliasser?
For at finde alle de tilgængelige tidszoner skal du inspicere all_timezones
felt, som er en liste over alle tilgængelige tidszoner:
print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
print(time_zone)
Tjek vores praktiske, praktiske guide til at lære Git, med bedste praksis, brancheaccepterede standarder og inkluderet snydeark. Stop med at google Git-kommandoer og faktisk lærer det!
There are 594 timezones in PyTz
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...
Skift Datetimes tidszone
Vi kan konvertere tidszone af en tidszone-bevidst datetime
objekt fra en region til en anden, i stedet for at lokalisere en tidszone-naiv datetime gennem linsen af en tidszone.
Dette er forskelligt fra lokalisering, da lokalisering repræsenterer et andet tidspunkt, men konvertering af et objekts tidszone repræsenterer det samme tidspunkt gennem en anden linse:
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)
Først oprettede vi et datetime-objekt med det aktuelle klokkeslæt og indstillede det som "America/New_York"-tidszonen. Brug derefter astimezone()
metode, har vi konverteret denne datetime
til tidszonen "Europa/London". Begge datetime
s vil udskrive forskellige værdier ved at bruge UTC offset som referencelink mellem dem:
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 dagen efter i London is samme tidspunkt som 21:24 dagen før i New York da London er 5 timer foran.
Som forventet er dato-tider anderledes, da de er omkring 5 timers mellemrum.
Konverter streng til datotid ved hjælp af tredjepartsbiblioteker
Pythons datetime
modul kan konvertere alle forskellige typer strenge til en datetime
objekt. Men hovedproblemet er, at for at gøre dette skal du oprette den passende formateringskodestreng strptime()
kan forstå. Det tager tid at oprette denne streng, og det gør koden sværere at læse.
I stedet kan vi bruge andre tredjepartsbiblioteker for at gøre det nemmere.
I nogle tilfælde har disse tredjepartsbiblioteker også bedre indbygget understøttelse til at manipulere og sammenligne dato-tider, og nogle har endda tidszoner indbygget, så du ikke behøver at inkludere en ekstra PyTz-pakke.
Lad os tage et kig på nogle af disse biblioteker i de følgende afsnit.
Konverter streng til Datetime med dateutil
dateutil modul er en udvidelse til datetime
modul. En fordel er, at vi ikke behøver at sende nogen parsing-kode for at parse en streng!
For automatisk at konvertere en streng til datetime uden et formattoken ved hjælp af Python's dateutil
:
from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')
print(datetime)
Denne parse
funktion vil parse strengen automatisk! Du behøver ikke at inkludere en formatstreng. Lad os prøve at analysere forskellige typer strenge vha 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
Du kan se, at næsten enhver type streng let kan parses ved hjælp af dateutil
modul.
Selvom dette er praktisk, så husk fra tidligere, at det at skulle forudsige formatet gør koden meget langsommere, så hvis din kode kræver høj ydeevne, er dette måske ikke den rigtige tilgang til din applikation.
Konverter streng til Datetime med Maya
Maya gør det også meget nemt at parse en streng og ændre tidszoner. For nemt at konvertere en streng med Pythons Maya:
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
For at konvertere tiden til en anden tidszone:
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
Er det nu ikke så nemt at bruge? Lad os prøve maya
med det samme sæt strenge, som vi har brugt med 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
Som du kan se, blev alle datoformater analyseret med succes!
Hvis vi ikke giver tidszoneoplysningerne, konverterer den automatisk til UTC. Så det er vigtigt at bemærke, at vi skal give to_timezone
, naive
parametre, hvis tiden ikke er i UTC.
Konverter streng til datotid med pil
Arrow er et andet bibliotek til at håndtere datetime i Python. Og som før med maya
, finder den også automatisk dato- og tidsformatet ud. Når den er fortolket, returnerer den en Python datetime
genstand fra arrow
objekt.
For nemt at konvertere en streng til datetime ved hjælp af Python's 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()
Og her er hvordan du kan bruge arrow
at konvertere tidszoner ved hjælp af to()
metode:
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
Som du kan se, er dato-tidsstrengen konverteret til regionen "America/New_York".
Lad os nu igen bruge det samme sæt strenge, som vi har brugt ovenfor:
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)
Denne kode vil mislykkes for de dato- og klokkeslætsstrenge, der er blevet kommenteret ud, hvilket er over halvdelen af vores eksempler. Outputtet for andre strenge vil være:
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
For at kunne parse de dato- og klokkeslætstrenge, der er kommenteret ud korrekt, skal du videregive de tilsvarende formatere tokens for at give biblioteket ledetråde til, hvordan det analyseres.
Konklusion
I denne artikel har vi vist forskellige måder at parse en streng til en datetime
objekt i Python. Du kan enten vælge standard Python datetime
biblioteket eller et af de tredjepartsbiblioteker, der er nævnt i denne artikel, blandt mange andre.
Det største problem med standarden datetime
pakken er, at vi skal specificere parsingkoden manuelt for næsten alle dato- og tidsstrengformater. Så hvis dit strengformat ændres i fremtiden, bliver du sandsynligvis også nødt til at ændre din kode. Men mange tredjepartsbiblioteker, som dem, der er nævnt her, håndterer det automatisk.
Et andet problem, vi står over for, er at håndtere tidszoner. Den bedste måde at håndtere dem på er altid at gemme tiden i din database som UTC-format og derefter konvertere den til brugerens lokale tidszone, når det er nødvendigt.
Disse biblioteker er ikke kun gode til at parse strenge, men de kan bruges til en masse forskellige typer dato-tidsrelaterede operationer. Jeg vil opfordre dig til at gennemgå dokumenterne for at lære funktionaliteterne i detaljer.