16. diel - Dátum a čas v Pythone druhýkrát - Knižnica datetime
V predchádzajúcej 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 vytvárajú 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 Pythonu 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. Ak 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. Ak 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é zvláštne? 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 Pythonu, ktorá môže byť
založená na internom spracovaní alebo iných aspektoch implementácie. Alebo
sa skrátka niekto naozaj zle vyspal
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é. Ak teda vo svojich programoch nepotrebujeme
časové informácie, môžeme ich pomerne ľahko vynechať.
Súbežné použitie
time a datetime
Ak 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(). Ak 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í.

