Konvertering af strenge til datetime i Python

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 indbyggede datetime modul, men også tredjepartsmoduler som f.eks dateutil, 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, timeog 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 datetimes 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.

Tidsstempel:

Mere fra Stablemisbrug