IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

15. diel - Dátum a čas v Pythone druhýkrát - Knižnica datetime

V minulej lekcii, Dátum a čas v Pythone , sme si predstavili knižnice time a calendar.

V nasledujúcom tutoriále objektovo orientovaného programovania v Pythone sa pozrieme na prácu s modulom datetime, ktorý sa vedľa modulov time a calendar používa pre prácu s dátumom a časom a podporuje príjemnejší, objektový prístup. Oproti knižnici time je datetime oveľa bohatší a ponúka širšiu paletu funkcií a vlastností. Súčasne ale tiež platí, že mnoho funkcií (metód) majú obe knižnice buď priamo spoločných (názvom, syntaxou aj výstupom), alebo sa len veľmi mierne líšia. V lekcii ich teda nebudeme opakovať a viac sa zameriame viac na objektový prístup k dátumu a času.

Knižnica datetime

Knižnica datetime pracuje s vlastnými špecializovanými datetime objektmi. To nám ľahko umožní od seba jednotlivé dáta napríklad odčítať alebo ich navzájom porovnávať bez nutnosti zaoberania sa počtom sekúnd od roku 1970 alebo indexmi vo výstupe vo forme tuple. Teraz si ukážeme, ako sa tieto objekty zakladajú a ako s nimi budeme ďalej pracovať v jednotlivých moduloch.

Trieda datetime

Veľmi významnou triedou v tejto knižnici je rovnomenná trieda datetime a jej opäť rovnomenná:-) metóda datetime(). Tú budeme v praxi používať na vytváranie inštancií, s ktorými budeme ďalej pracovať. Tiež poskytuje užitočné metódy, ktoré budeme hojne využívať.

Bežnou konvenciou, ktorú dodržiavame aj v našich tutoriáloch, je pomenovanie triedy veľkým písmenom, a teda by sme mali triedu pomenovať Datetime. Vývojári Pythona bohužiaľ na konvencie v názvoch modulov a tried často príliš neberú ohľad. Aby náš text lekcie zodpovedal skutočnému kódu, budeme na triedu odkazovať ako na datetime s malým počiatočným písmenom. Inak by sa text lekcie od kódu líšil a bolo by to mätúce.

Metódy triedy datetime

Pozrime sa teraz na dôležité metódy, ktoré nám trieda datetime poskytuje. Ako sme už spomenuli v úvode lekcie, mnoho metód je rovnakých alebo veľmi podobných s funkciami modulu time.

Metóda datetime()

Metóda datetime() prijíma ako argumenty v danom poradí údaje: rok, mesiac, deň, hodina, minúta, sekunda a mikrosekunda. Vytvorme si inštanciu dátumu a času z určitého roku, mesiaca a dňa:

from datetime import datetime   #  Pro jednodušší kód si importujeme rovnou třídu Datetime.
                                #  Vyhneme se tím opakovaným zápisům datetime.datetime(...).
datum = datetime(2023, 10, 23)
print(datum)
Metóda now()

Metóda now() nám jednoducho umožní získať aktuálny dátum a čas:

from datetime import datetime

dnes = datetime.now()
print(dnes)

Metóda vytvorí inštanciu triedy datetime, v ktorej sú uložené aktuálne informácie k dátumu. K jednotlivým údajom sa dostaneme veľmi ľahko a to pomocou atribútov year, month, day, hour, minute a second:

from datetime import datetime

dnes = datetime.now()

print("Datum:")
print(f"Rok: {dnes.year}")
print(f"Měsíc: {dnes.month}")
print(f"Den: {dnes.day}")
print(f"Čas: {dnes.hour}:{dnes.minute}:{dnes.second}")

Metóda weekday()

Metóda, ktorú voláme na inštanciu triedy datetime, nám zistí deň v týždni, ku ktorému táto inštancia patrí. Skúsme si ju zavolať na aktuálnom dátume a čase:

from datetime import datetime

dnes = datetime.now()

# Seznam dnů v týdnu
dny_v_tydnu = ["pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", "neděle"]

den = dny_v_tydnu[dnes.weekday()]
print(f"Dnes je {den}.")

V tejto metóde sa pre nás ukrýva mnoho možností, a je iba na nás, aký formát na získavanie dátumu a času si zvolíme.

Knižnica datetime okrem iného obsahuje napríklad metódy strftime() a strptime(). Tieto metódy (a ďalšie) sú prakticky identické s rovnomennými funkciami z modulu time, ktorými sme sa zaoberali v lekcii Dátum a čas v Pythone. Na porovnanie je najlepšie nahliadnuť do oficiálnej dokumentácie knižnice datetime.

Práca s dátumom

Práca s dátami je jednou z najčastejších úloh v programovaní. Či už potrebujeme porovnať dve dáta alebo spočítať počet dní medzi nimi, knižnica datetime nám ponúka efektívne nástroje na tieto úlohy. Výhodou knižnice datetime je jej objektový prístup k reprezentácii času a dátumu. Vďaka tomu, že všetky dáta ukladáme ako inštancie tej istej triedy, máme teda možnosť vykonávať s dátami rôzne aritmetické operácie, ako je sčítanie a odčítanie, alebo porovnávať dáta medzi sebou. V tejto kapitole sa pozrieme na niekoľko základných operácií a funkcií, ktoré nám datetime ponúka na prácu s dátami, a ukážeme si, ako ich efektívne využiť v praxi.

Aritmetické operácie s dátumom

Najprv sa zameriame na základné matematické operácie ako sú sčítanie a odčítanie:

from datetime import datetime

dnes = datetime.now()            #  založíme aktuální datum
tehdy = datetime(2000, 1, 1)     #  založíme datum 1.1.2000

ubehly_cas = dnes - tehdy        #  odečteme data od sebe
print(ubehly_cas)

V tomto prípade premenná ubehly_cas obsahuje počet dní, hodín, minút a sekúnd, ktoré ubehli od začiatku 3. tisícročia do dnešného dňa. Za podobným účelom máme ešte k dispozícii metódu total_seconds(), ktorá vráti počet sekúnd ubehnutých v danom intervale.

Porovnávanie

Dve dáta môžeme medzi sebou aj porovnávať a to obyčajnými operátormi, ktoré používame pri porovnávaní čísel:

from datetime import datetime

dnes = datetime.now()
tehdy = datetime(2000, 1, 1)

print(dnes > tehdy)            # vrátí True
print(dnes == tehdy)           # vrátí False

Zmena vytvoreného dátumu

Ak potrebujeme rýchlo a ľahko zmeniť už vytvorený dátum, použijeme metódu replace(). Zvýšime si rok a deň na objekte datetime o 1:

from datetime import datetime

dnes = datetime.now()

zmena_roku = dnes.replace(year = dnes.year + 1)
zmena_dne = dnes.replace(day =  dnes.day + 1)

print(f"Přidáme rok navíc a budeme mít rok {zmena_roku.year}.")
print(f"Přidáme den navíc a budeme mí {zmena_dne.day}.{dnes.month}.")

Metóda replace() funguje na akomkoľvek časovom objekte – len v nej musíme presne špecifikovať, čo chceme meniť na akú hodnotu. Ide iba o zmenu hodnoty už založenej premennej.

Ak je dnes.day posledný deň mesiaca (napr. 31. januára alebo 30. apríla), pridanie jedného dňa spôsobí ValueError.

Podobné problémy však rieši trieda timedelta. Pozrime sa na ňu.

Trieda timedelta

Pre ďalšie možnosti práce s časom je tu trieda timedelta. Trieda timedelta nám umožňuje vyjadriť časový interval, čo môže zahŕňať dni, sekundy, mikrosekundy a podobne. S inštanciami timedelta je možné podobne ako v prípade triedy datetime vykonávať rôzne aritmetické operácie, napríklad pridávať ich k inštanciám datetime alebo odčítať ich od seba. Pokiaľ od seba dve dáta napríklad odčítame, získame inštanciu triedy timedelta, čo nie je konkrétny dátum, ale interval (rozdiel) medzi nejakými dvoma dátami. Tento objekt si založíme a ľahko zistíme, aký deň bude o 10 dní:

from datetime import datetime
from datetime import timedelta

dnes = datetime.now()

deset_dnu = timedelta(10)      # vytvoříme objekt timedelta s posunem o 10 dní

za_10_dni = dnes + deset_dnu
pred_10_dny = dnes - deset_dnu

print(f"Dnes je: {dnes}")
print(f"Za 10 dní bude: {za_10_dni}")
print(f"Před 10 dny bylo: {pred_10_dny}")

Trieda timedelta tiež rieši problém s prechodom z mesiaca na mesiac. Ak interval presiahne plný (alebo minimálny) počet dní v danom mesiaci, trieda automaticky prejde na ďalší (predchádzajúci) mesiac v poradí.

Konštruktor timedelta() nemusíme vždy použiť s celými dňami. Pokiaľ chceme pracovať s inou hodnotou, máme tú možnosť. Pri zakladaní objektu timedelta máme možnosť navoliť mnoho argumentov. Ak explicitne neuvedieme názvy argumentov, tak v uvedenom poradí:

  • days,
  • seconds,
  • microseconds,
  • milliseconds,
  • minutes,
  • hours,
  • weeks.
Čakali by sme, že najväčšie jednotky (ako týždne alebo dni) budú v argumentoch uvedené ako prvé, nasledované menšími jednotkami (hodiny, minúty atď.). Prečo je poradie argumentov také podivné? To je otázka, na ktorú nie je jednoznačná odpoveď. Je možné, že to je historická záležitosť alebo dizajnová voľba vývojárov Pythona, ktorá môže byť založená na internom spracovaní alebo iných aspektoch implementácie. Alebo sa skrátka niekto naozaj zle vyspal:-D V každom prípade, keď vytvárame inštanciu timedelta, je dobré si zvyknúť explicitne uvádzať mená argumentov. Zvýšime tým čitateľnosť kódu a eliminujeme potenciálny zmätok:
interval = timedelta(weeks=2, days=3, hours=1)

Trieda timedelta bohužiaľ nemá v argumentoch dostupný počet rokov a mesiacov, pretože rok ani mesiac nie sú plnohodnotné časové jednotky a nemajú pevne daný počet dní (niektoré roky sú prestupné).

Orezanie dátumu o čas

Všetky metódy, ktoré sme si doteraz spomenuli, pracujú s objektmi datetime (dátum a čas). Ak by sme chceli využívať iba dátum, je vhodné namiesto tohto použiť objekt date. Ten nenesie informáciu o čase, ktorý by nám inak mohol znepríjemňovať potrebné porovnávanie. Objekt date získame z triedy datetime pomocou metódy date():

from datetime import date
from datetime import timedelta

dnes = date.today()

print(f"Dnešní datum: {dnes}")

print(f"Za 10 dní bude: {dnes + timedelta(10)}")
print(f"Před 10 dny bylo: {dnes - timedelta(10)}")

Nie je na tom nič zložité. Jediná zmena od datetime je v použití metódy today(), ktorá priamo nahrádza now(). Všetky metódy používané vyššie v lekcii sú s týmto formátom úplne kompatibilné. Pokiaľ teda vo svojich programoch nepotrebujeme časové informácie, môžeme ich pomerne ľahko vynechať.

Súbežné použitie time a datetime

Pokiaľ sa rozhodneme v jednom programe využívať súčasne moduly time a datetime, na prvý pohľad nám to prinesie určité výhody. Najmä širokú škálu funkcií a metód oboch modulov. Avšak je tu jedno veľké „ale“.

Oba moduly majú, ako sme už spomenuli, mnoho funkcií a metód s rovnakým názvom, napríklad strftime(). Pokiaľ oba moduly naimportujeme kompletne pomocou import time a import datetime, budeme musieť uvádzať, z ktorého modulu chceme danú funkciu alebo metódu používať. Napríklad takto - time.strftime() alebo datetime.datetime.strftime(). To povedie k veľmi neprehľadnému kódu a pravdepodobne aj k zbytočným chybám. Preto je veľmi vhodné pri importoch použiť aliasy alebo triedy importovať priamo:

from datetime import datetime as dt
from datetime import timedelta

Vďaka tomu si budeme istí, akú funkciu či metódu z akého modulu skutočne voláme.

V nasledujúcom kvíze, Kvíz - Dátum a čas v Pythone, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Dátum a čas v Pythone
Všetky články v sekcii
Objektovo orientované programovanie v Pythone
Preskočiť článok
(neodporúčame)
Kvíz - Dátum a čas v Pythone
Článok pre vás napísal Marek Bečvář
Avatar
Užívateľské hodnotenie:
2 hlasov
Marek Bečvář
Aktivity