Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

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áli 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 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   #  To simplify the code, we directly import the Datetime class.
                                #  This avoids repeated usage of datetime.datetime(...).
date = datetime(2023, 10, 23)
print(date)
Metóda now()

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

from datetime import datetime

today = datetime.now()
print(today)

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

today = datetime.now()

print("Date:")
print(f"Year: {today.year}")
print(f"Month: {today.month}")
print(f"Day: {today.day}")
print(f"Time: {today.hour}:{today.minute}:{today.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

today = datetime.now()

# List of days of the week
days_of_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

day = days_of_week[today.weekday()]
print(f"Today is {day}.")

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átumami je jednou z najčastejších úloh v programovaní. Či už potrebujeme porovnať dva dátumy 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átumy ukladáme ako inštancie tej istej triedy, máme teda možnosť vykonávať s dátumami rôzne aritmetické operácie, ako je sčítanie a odčítanie, alebo porovnávať dátumy 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átumami, 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

today = datetime.now()            #  create the current date
then = datetime(2000, 1, 1)       #  create the date 1.1.2000

elapsed_time = today - then       #  subtract the dates
print(elapsed_time)

V tomto prípade premenná elapsed_time 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

Dva dátumy 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

today = datetime.now()
then = datetime(2000, 1, 1)

print(today > then)            # returns True
print(today == then)           # returns 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

today = datetime.now()

year_changed = today.replace(year = today.year + 1)
day_changed = today.replace(day =  today.day + 1)

print(f"Adding an extra year will give us the year {year_changed.year}.")
print(f"Adding an extra day will give us {day_changed.day}.{today.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 today.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 dva dátumy 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átumami. Tento objekt si založíme a ľahko zistíme, aký deň bude o 10 dní:

from datetime import datetime
from datetime import timedelta

today = datetime.now()

ten_days = timedelta(10)      # create a timedelta object with an offset of 10 days

in_ten_days = today + ten_days
ten_days_ago = today - ten_days

print(f"Today is: {today}")
print(f"In 10 days it will be: {in_ten_days}")
print(f"10 days ago it was: {ten_days_ago}")

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

today = date.today()

print(f"Today's date: {today}")

print(f"In 10 days it will be: {today + timedelta(10)}")
print(f"10 days ago it was: {today - 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