Conversia șirurilor de caractere în datetime în Python

Introducere

Datele pot fi reprezentate în diferite forme – și un mod convenabil de a reprezenta datele și orele sunt siruri. Cu toate acestea, pentru a lucra cu aceste date și ore într-un mod aritmetic (cum ar fi calcularea diferențelor de timp, adăugarea sau eliminarea timpului etc.) - trebuie să le convertim într-un datetime obiect.

Una dintre cele mai comune surse de date și ore formatate în șir sunt API-uri REST care returnează șiruri agnostice, pe care apoi le putem converti în alte formate.

În plus, fusurile orare sunt o durere de cap obișnuită atunci când vine vorba de lucrul cu obiecte datetime, așa că va trebui să ne gândim și la asta în timpul conversiei.

În acest ghid, vom arunca o privire la cum să convertim un șir de date/ora în a datetime obiect în Python, folosind încorporat datetime modul, dar și module terțe precum dateutil, arrow și Maya, ținând cont de fusurile orare.

Conversia șirurilor de caractere folosind datetime

datetime modulul constă din trei tipuri diferite de obiecte: date, time, și datetime. date obiectul deține data, time ține timpul și datetime păstrează atât data, cât și ora!

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

Rularea acestui cod ar avea ca rezultat:

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

Când nu se oferă nicio formatare personalizată, este utilizat formatul implicit de șir, adică formatul pentru „2022-12-01 10:27:03.929149” este în ISO 8601 format (AAAA-LL-ZZA:LL:SS.mmmmmm). Dacă șirul nostru de intrare pentru a crea un datetime obiectul este în același format ISO 8601 sau dacă cunoașteți formatul pe care îl veți primi în avans, îl putem analiza cu ușurință într-un datetime obiect:

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)

Rularea acestuia va imprima data, ora și data-ora:

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

Aici, folosim strptime() metoda, care acceptă două argumente:

  • Data formatată în șir
  • Formatul primului argument

Specificarea formatului astfel face analizarea mult mai rapidă de atunci datetime nu trebuie să încerce să interpreteze formatul singur, ceea ce este mult mai costisitor din punct de vedere computațional. Valoarea returnată este de tipul datetime.

În exemplul nostru, "2022-12-01 10:27:03.929149" este șirul de intrare și "%Y-%m-%d %H:%M:%S.%f" este formatul șirului nostru de date. Cei întors datetime valoarea este stocată ca date_time_obj.

Deoarece acesta este un datetime obiect, putem numi date() și time() metode direct pe ea. După cum puteți vedea din rezultat, imprimă partea „data” și „ora” a șirului de intrare!

Formatați jetoane

Merită să luați un moment pentru a înțelege jetoane de format - "%Y-%m-%d %H:%M:%S.%f" dinainte.

Fiecare simbol reprezintă o parte diferită a datei-ora, cum ar fi ziua, luna, anul, ziua lunii sau a săptămânii etc. lista de jetoane acceptate este suficient de extins pentru a permite diverse formatări. Unele dintre cele utilizate în mod obișnuit, pe care le-am folosit și mai devreme sunt:

  • %Y: An (4 cifre)
  • %m: Luna
  • %d: Ziua lunii
  • %H: oră (24 de ore)
  • %M: Minute
  • %S: Secunde
  • %f: Microsecunde

Notă: Toate aceste jetoane, cu excepția anului, sunt de așteptat să fie cu zero (adică august este a 8-a lună și este cu zero pentru 08).

Utilizarea jetoanelor de format strptime() pentru a converti șirul într-un format de dată și oră diferit

Dacă formatul unui șir este cunoscut, acesta poate fi ușor analizat la a datetime obiect folosind strptime(). Să aruncăm o privire la un exemplu non-trivial care se traduce dintr-un format în altul:

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)

Șirul de intrare avea un singur format – „17 iulie 2022 9:20”. Cunoscând acest format, am mapat elementele constitutive la formatul ISO 8601 și l-am convertit într-un datetime obiect:

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

Iată o listă scurtă de date obișnuite formatate în șir și formatele corespunzătoare pentru 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"

Puteți analiza un șir dată-oră de orice format – atâta timp cât utilizați șirul corect de simboluri de format pentru intrarea pe care o primiți.

Convertiți șirul în date și oră cu fusuri orare

Gestionarea date-orelor devine mai complexă în timp ce vă ocupați de fusurile orare. Toate exemplele de mai sus de până acum sunt naive față de fusul orar. Acestea sunt cunoscute ca obiecte datetime naive.

Cu toate acestea, datetime obiectele conțin un câmp exact pentru stocarea datelor legate de fusul orar – tzinfo:

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

print(dtime) 
print(dtime.tzinfo) 

tzinfo câmpul este menit să fie a datetime.timezone obiect, indicând informațiile despre fusul orar. este None implicit și indică faptul că obiectul datetime este naiv pentru fusul orar. O bibliotecă externă foarte comună pentru gestionarea fusurilor orare este pytz. Puteți seta PyTz obiecte ca tzinfo câmpul de asemenea.

Dacă nu îl aveți deja - instalați-l prin:

$ pip install pytz

Folosind PyTz, putem crea o ancoră pentru date care țin cont de fusul orar, cum ar fi UTC:

import datetime as dt
import pytz

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

print(dtime)
print(dtime.tzinfo)

ieșire:

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

Nu mai este 11:2, ci XNUMX:XNUMX, pentru că am setat fusul orar cu câteva ore în urmă! Acest schimbă fusul orar a datei ora.

+00:00 este diferența dintre ora afișată și ora UTC ca ancoră de coordonare globală. Am setat ora să fie în UTC, deci decalajul este 00:00. Aceasta este o obiect care știe fusul orar.

În mod similar, putem schimba interpretarea aceleiași date și ore între fusurile orare. Să convertim un șir, cum ar fi „2022-06-29 17:08:00” într-o dată și apoi localiza la fusul orar „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)

Notă: Localizare transformă o dată-oră naiv pentru fusul orar într-o dată-oră care ține cont de fusul orar și tratează fusul orar ca pe cel local. Astfel, cel data ora rămâne aceeași, dar având în vedere fusul orar diferit, acesta nu mai reprezintă același moment în timp nelegat de fusul orar.

Primim la fel valoarea datetime, compensat cu -04: 00 comparativ cu ora UTC:

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

17:08 la Tokyo nu este același punct în timp ca 17:08 în New York. 17:08 în Tokyo este 3:08 în New York.

Cum să găsiți toate codurile/alias-urile fusului orar?

Pentru a găsi toate fusurile orare disponibile, inspectați all_timezones câmp, care este o listă cu toate fusurile orare disponibile:

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

Consultați ghidul nostru practic și practic pentru a învăța Git, cu cele mai bune practici, standarde acceptate de industrie și fisa de cheat incluse. Opriți căutarea pe Google a comenzilor Git și de fapt învăţa aceasta!

There are 594 timezones in PyTz

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

Schimbați fusul orar al datei și orei

Putem converti fusul orar al unui fus orar conștient datetime obiect dintr-o regiune în alta, în loc de a localiza un fus orar naiv datetime prin prisma unui fus orar.

Acest lucru este diferit de localizare, deoarece localizarea reprezintă un moment diferit în timp, dar conversia fusului orar al unui obiect reprezintă același moment în timp, printr-o lentilă diferită:

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)

Mai întâi, am creat un obiect datetime cu ora curentă și l-am setat ca fus orar „America/New_York”. Apoi, folosind astimezone() metoda, am convertit aceasta datetime la fusul orar „Europa/Londra”. Ambii datetimes va imprima valori diferite, folosind offset-ul UTC ca legătură de referință între ele:

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 a doua zi la Londra is același moment ca ora 21:24 din ziua precedentă la New York deoarece Londra este cu 5h înainte.

După cum era de așteptat, datele și orele sunt diferite, deoarece sunt la aproximativ 5 ore între ele.

Convertiți șirul în date și oră folosind biblioteci terțe

Python's datetime modulul poate converti toate tipurile diferite de șiruri în a datetime obiect. Dar principala problemă este că, pentru a face acest lucru, trebuie să creați șirul de cod de formatare adecvat care strptime() pot intelege. Crearea acestui șir necesită timp și face codul mai greu de citit.

În schimb, putem folosi alte biblioteci terțe pentru a face acest lucru mai ușor.

În unele cazuri, aceste biblioteci terță parte au, de asemenea, un suport încorporat mai bun pentru manipularea și compararea date-orelor, iar unele au chiar și fusuri orare încorporate, deci nu trebuie să includeți un pachet PyTz suplimentar.

Să aruncăm o privire la câteva dintre aceste biblioteci în secțiunile următoare.

Convertiți String în Datetime cu dateutil

module dateutil este o extensie a datetime modul. Un avantaj este că nu trebuie să transmitem niciun cod de analiză pentru a analiza un șir!

Pentru a converti automat un șir în datetime fără un token de format folosind Python dateutil:

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

print(datetime)

Acest parse funcția va analiza automat șirul! Nu trebuie să includeți niciun șir de format. Să încercăm să analizăm diferite tipuri de șiruri folosind 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')

ieșire:

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

Puteți vedea că aproape orice tip de șir poate fi analizat cu ușurință folosind dateutil modul.

Deși acest lucru este convenabil, amintiți-vă de mai devreme că faptul că trebuie să preziceți formatul face ca codul să fie mult mai lent, așa că dacă codul dvs. necesită performanțe ridicate, aceasta ar putea să nu fie abordarea potrivită pentru aplicația dvs.

Convertiți String în Datetime cu Maya

maya de asemenea, face foarte ușor să analizați un șir și să schimbați fusurile orare. Pentru a converti cu ușurință un șir cu Maya lui Python:

import maya

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

ieșire:

2018-04-29
17:45:25
UTC

Pentru a converti ora într-un alt fus orar:

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)

ieșire:

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

Acum nu este atât de ușor de folosit? Să încercăm maya cu același set de șiruri cu care am folosit 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)
    
    
    
    

ieșire:

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

După cum puteți vedea, toate formatele de date au fost analizate cu succes!

Dacă nu furnizăm informațiile despre fusul orar, atunci le convertește automat în UTC. Deci, este important să rețineți că noi trebuie sa asigurarea to_timezone și naive parametri dacă ora nu este în UTC.

Convertiți șirul în date și oră cu săgeata

Săgeată este o altă bibliotecă pentru a se ocupa de data și ora în Python. Și ca înainte cu maya, de asemenea, descoperă automat formatul de dată și oră. Odată interpretat, returnează un Python datetime obiect din arrow obiect.

Pentru a converti cu ușurință un șir în datetime folosind Python arrow:

import arrow

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

ieșire:

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

Și iată cum poți folosi arrow pentru a converti fusurile orare folosind to() metodă:

import arrow

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

ieșire:

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

După cum puteți vedea, șirul dată-oră este convertit în regiunea „America/New_York”.

Acum, să folosim din nou același set de șiruri pe care l-am folosit mai sus:

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)
    
    
    
    

Acest cod va eșua pentru șirurile de dată-oră care au fost comentate, ceea ce reprezintă peste jumătate din exemplele noastre. Ieșirea pentru alte șiruri va fi:

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

Pentru a analiza corect șirurile de dată-oră care sunt comentate, va trebui să treceți jetoane de format pentru a oferi bibliotecii indicii despre cum să o analizeze.

Concluzie

În acest articol am arătat diferite moduri de a analiza un șir în a datetime obiect în Python. Puteți opta fie pentru Python implicit datetime bibliotecă sau oricare dintre bibliotecile terțe menționate în acest articol, printre multe altele.

Principala problemă cu implicit datetime pachetul este că trebuie să specificăm manual codul de analiză pentru aproape toate formatele de șir de date și oră. Deci, dacă formatul șirului dvs. de caractere se schimbă în viitor, probabil că va trebui să vă schimbați și codul. Dar multe biblioteci terțe, precum cele menționate aici, se ocupă automat.

Încă o problemă cu care ne confruntăm este să ne ocupăm de fusurile orare. Cel mai bun mod de a le gestiona este întotdeauna să stocați ora în baza de date în format UTC și apoi să o convertiți în fusul orar local al utilizatorului atunci când este necesar.

Aceste biblioteci nu sunt bune numai pentru analizarea șirurilor de caractere, dar pot fi folosite pentru o mulțime de tipuri diferite de operațiuni legate de dată și oră. Vă încurajez să parcurgeți documentele pentru a afla funcționalitățile în detaliu.

Timestamp-ul:

Mai mult de la Stackabuse