Konvertera strängar till datumtid i Python

Beskrivning

Data kan representeras i olika former – och ett bekvämt sätt att representera datum och tider är strängar. Men för att arbeta med dessa datum och tider på ett aritmetiskt sätt (som att beräkna tidsskillnader, lägga till eller ta bort tid, etc.) – måste vi konvertera dem till en datetime objekt.

En av de vanligaste källorna till strängformaterade datumtider är REST API:er som returnerar agnostiska strängar, som vi sedan kan konvertera till andra format.

Dessutom – tidszoner är en vanlig huvudvärk när det gäller att arbeta med datetime-objekt, så vi måste tänka på det när vi konverterar också.

I den här guiden tar vi en titt på hur man konverterar ett strängdatum/-tid till ett datetime objekt i Python, med den inbyggda datetime modul, men även tredjepartsmoduler som t.ex dateutil, arrow och Maya, som står för tidszoner.

Konvertera strängar med datumtid

Smakämnen datum Tid Modulen består av tre olika objekttyper: date, timeoch datetime. De date objektet håller datumet, time håller tiden, och datetime håller både datum och tid!

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

Att köra den här koden skulle resultera i:

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

När ingen anpassad formatering anges används standardsträngformatet, dvs formatet för "2022-12-01 10:27:03.929149" är i ISO 8601 format (ÅÅÅÅ-MM-DDTHH:MM:SS.mmmmmm). Om vår inmatningssträng för att skapa en datetime objektet är i samma ISO 8601-format eller om du vet vilket format du kommer att få i förväg kan vi enkelt analysera det till 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)

Om du kör det kommer att skriva ut datum, tid och datum-tid:

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

Här använder vi strptime() metod, som accepterar två argument:

  • Det strängformaterade datumet
  • Formatet för det första argumentet

Att specificera formatet på det här sättet gör analysen mycket snabbare sedan dess datetime behöver inte försöka tolka formatet på egen hand, vilket är mycket dyrare beräkningsmässigt. Returvärdet är av typen datetime.

I vårt exempel, "2022-12-01 10:27:03.929149" är inmatningssträngen och "%Y-%m-%d %H:%M:%S.%f" är formatet på vår datumsträng. Den återvände datetime värde lagras som date_time_obj.

Eftersom detta är en datetime objekt kan vi kalla date() och time() metoder direkt på den. Som du kan se från utdata, skriver den ut "datum" och "tid" delen av inmatningssträngen!

Formatera tokens

Det är värt att ta en stund att förstå formatera tokens - Den "%Y-%m-%d %H:%M:%S.%f" från tidigare.

Varje token representerar en annan del av datum-tid, som dag, månad, år, dag i månaden eller veckan, etc. lista över tokens som stöds är tillräckligt omfattande för att möjliggöra olika formatering. Några av de vanligaste som vi också har använt tidigare är:

  • %Y: År (4 siffror)
  • %m: Månad
  • %d: Dag i månaden
  • %H: timme (24 timmar)
  • %M: Minuter
  • %S: Sekunder
  • %f: Mikrosekunder

Notera: Alla dessa polletter, förutom året, förväntas vara nollstoppade (dvs. augusti är den 8:e månaden och är nollstoppad till 08).

Använda strptime() Format Tokens för att konvertera sträng till ett annat Datetime Format

Om formatet för en sträng är känt kan den enkelt tolkas till en datetime objekt med strptime(). Låt oss ta en titt på ett icke-trivialt exempel som översätts från ett format till ett annat:

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)

Inmatningssträngen hade ett format – "17 juli 2022 9:20 AM". Genom att känna till detta format mappade vi de ingående elementen till ISO 8601-formatet och konverterade det till en datetime objekt:

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

Här är en kort lista över vanliga strängformaterade datumtider och deras motsvarande format för 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 analysera en datum-tid-sträng av vilket format som helst – så länge du använder rätt sträng med formattokens för den inmatning du tar emot.

Konvertera sträng till datumtid med tidszoner

Hantering av datum-tider blir mer komplex när man hanterar tidszoner. Alla ovanstående exempel hittills är naiva för tidszonen. Dessa är kända som naiva datetime-objekt.

Emellertid den datetime objekt innehåller ett fält exakt för att lagra tidszonrelaterad data – tzinfo:

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

print(dtime) 
print(dtime.tzinfo) 

Smakämnen tzinfo fältet är tänkt att vara en datetime.timezone objekt, som anger tidszonsinformationen. Dess None som standard och anger att datetime-objektet är tidszonsnaivt. Ett mycket vanligt externt bibliotek för hantering av tidszoner är pytz. Du kan ställa in PyTz föremål som tzinfo fält också.

Om du inte redan har det – installera det via:

$ pip install pytz

Med PyTz kan vi skapa ett ankare för tidszonsmedvetna datumtider, såsom UTC:

import datetime as dt
import pytz

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

print(dtime)
print(dtime.tzinfo)

Produktion:

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

Klockan är inte längre 11:2, utan XNUMX:XNUMX, eftersom vi har ställt in tidszonen några timmar tillbaka! Detta ändrar tidszonen av datum och tid.

+00:00 är skillnaden mellan den visade tiden och UTC-tiden som globalt koordinationsankare. Vi har ställt in tiden i UTC, så offset är det 00:00. Detta är en tidszonsmedvetet objekt.

På samma sätt kan vi byta tolkning av samma datum och tid mellan tidszoner. Låt oss konvertera en sträng, till exempel "2022-06-29 17:08:00" till en datumtid och sedan lokalisera det till "America/New_York" tidszon:

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)

Notera: Lokalisering förvandlar en tidszonsnaiv datetime till en tidszonsmedveten datetime och behandlar tidszonen som den lokala. Alltså datetime förblir detsamma, men med tanke på den olika tidszonen representerar den inte längre samma tidpunkt obunden från tidszoner.

Vi får samma sak datetime värde, kompenseras av -04: 00 jämfört med UTC-tiden:

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

17:08 i Tokyo är inte samma tidpunkt som 17:08 i New York. 17:08 i Tokyo är 3:08 i New York.

Hur hittar jag alla tidszonskoder/alias?

För att hitta alla tillgängliga tidszoner, inspektera all_timezones fältet, som är en lista över alla tillgängliga tidszoner:

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

Kolla in vår praktiska, praktiska guide för att lära dig Git, med bästa praxis, branschaccepterade standarder och medföljande fuskblad. Sluta googla Git-kommandon och faktiskt lära Det!

There are 594 timezones in PyTz

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

Ändra Datetimes tidszon

Vi kan konvertera tidszon för en tidszonsmedveten datetime objekt från en region till en annan, istället för att lokalisera en tidszon-naiv datetime genom linsen för någon tidszon.

Detta skiljer sig från lokalisering, eftersom lokalisering representerar en annan tidpunkt, men att konvertera ett objekts tidszon representerar samma tidpunkt, genom en annan lins:

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 skapade vi ett datetime-objekt med den aktuella tiden och ställde in det som tidszonen "America/New_York". Använd sedan astimezone() metod har vi konverterat detta datetime till tidszonen "Europa/London". Både datetimes kommer att skriva ut olika värden, med UTC-offset som referenslänk mellan 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 nästa dag i London is samma tidpunkt som 21:24 föregående dag i New York eftersom London ligger 5 timmar före.

Som väntat är datum-tiderna olika eftersom de skiljer sig cirka 5 timmar.

Konvertera sträng till datumtid med hjälp av tredjepartsbibliotek

Pythons datetime modul kan konvertera alla olika typer av strängar till en datetime objekt. Men huvudproblemet är att för att göra detta måste du skapa lämplig formateringskodsträng som strptime() kan förstå. Att skapa denna sträng tar tid och det gör koden svårare att läsa.

Istället kan vi använda andra tredjepartsbibliotek för att göra det enklare.

I vissa fall har dessa tredjepartsbibliotek också bättre inbyggt stöd för att manipulera och jämföra datum-tider, och vissa har till och med tidszoner inbyggda, så du behöver inte inkludera ett extra PyTz-paket.

Låt oss ta en titt på några av dessa bibliotek i följande avsnitt.

Konvertera sträng till Datetime med dateutil

Smakämnen dateutil-modul är en förlängning av datetime modul. En fördel är att vi inte behöver skicka någon analyskod för att analysera en sträng!

För att automatiskt konvertera en sträng till datetime utan ett formattoken med Pythons dateutil:

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

print(datetime)

Denna parse funktion kommer att analysera strängen automatiskt! Du behöver inte inkludera någon formatsträng. Låt oss försöka analysera olika typer av strängar med hjälp av 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')

Produktion:

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 att nästan alla typer av strängar lätt kan analyseras med hjälp av dateutil modul.

Även om detta är bekvämt, kom ihåg från tidigare att att behöva förutsäga formatet gör koden mycket långsammare, så om din kod kräver hög prestanda så kanske detta inte är rätt tillvägagångssätt för din applikation.

Konvertera sträng till Datetime med Maya

maya gör det också mycket enkelt att analysera en sträng och ändra tidszoner. För att enkelt konvertera en sträng med Pythons Maya:

import maya

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

Produktion:

2018-04-29
17:45:25
UTC

För att konvertera tiden till en annan tidszon:

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)

Produktion:

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

Är det inte så lätt att använda nu? Låt oss prova maya med samma uppsättning strängar som vi har använt 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)
    
    
    
    

Produktion:

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, analyserades alla datumformat framgångsrikt!

Om vi ​​inte tillhandahåller tidszonsinformationen konverterar den automatiskt den till UTC. Så det är viktigt att notera att vi måste ge to_timezone och naive parametrar om tiden inte är i UTC.

Konvertera sträng till datumtid med pil

arrow är ett annat bibliotek för att hantera datetime i Python. Och som tidigare med maya, räknar den också ut datumformatet automatiskt. När den har tolkats returnerar den en Python datetime objekt från arrow objekt.

För att enkelt konvertera en sträng till datetime med Pythons arrow:

import arrow

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

Produktion:

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

Och här är hur du kan använda arrow för att konvertera tidszoner med hjälp av to() metod:

import arrow

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

Produktion:

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

Som du kan se konverteras datum-tid-strängen till regionen "America/New_York".

Nu, låt oss återigen använda samma uppsättning strängar som vi har använt ovan:

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)
    
    
    
    

Den här koden kommer att misslyckas för de datum-tid-strängar som har kommenterats bort, vilket är över hälften av våra exempel. Utdata för andra strängar kommer att vara:

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

För att korrekt analysera datum- och tidsträngarna som kommenteras ut måste du skicka motsvarande formatera tokens för att ge biblioteket ledtrådar om hur man analyserar det.

Slutsats

I den här artikeln har vi visat olika sätt att tolka en sträng till en datetime objekt i Python. Du kan antingen välja standard Python datetime biblioteket eller något av de tredjepartsbibliotek som nämns i den här artikeln, bland många andra.

Det största problemet med standarden datetime paketet är att vi måste specificera analyskoden manuellt för nästan alla datum-tid-strängformat. Så om ditt strängformat ändras i framtiden måste du troligen också ändra din kod. Men många tredjepartsbibliotek, som de som nämns här, hanterar det automatiskt.

Ytterligare ett problem vi står inför är att hantera tidszoner. Det bästa sättet att hantera dem är att alltid lagra tiden i din databas som UTC-format och sedan konvertera den till användarens lokala tidszon vid behov.

Dessa bibliotek är inte bara bra för att analysera strängar, utan de kan användas för många olika typer av datum-tid-relaterade operationer. Jag skulle uppmuntra dig att gå igenom dokumenten för att lära dig funktionerna i detalj.

Tidsstämpel:

Mer från Stackabuse