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 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í.