IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 15 - Datum a čas v Pythonu podruhé - Knihovna datetime

V minulé lekci, Datum a čas v Pythonu, jsme si představili knihovny time a calendar.

V následujícím tutoriálu objektově orientovaného programování v Pythonu se podíváme na práci s modulem datetime, který se vedle modulů time a calendar používá pro práci s datem a časem a podporuje příjemnější, objektový přístup. Oproti knihovně time je datetime mnohem bohatší a nabízí širší paletu funkcí a vlastností. Současně ale také platí, že mnoho funkcí (metod) mají obě knihovny buď přímo společných (názvem, syntaxí i výstupem), nebo se jen velmi mírně liší. V lekci je tedy nebudeme opakovat a více se zaměříme více na objektový přístup k datu a času.

Knihovna datetime

Knihovna datetime pracuje s vlastními specializovanými datetime objekty. To nám snadno umožní od sebe jednotlivá data například odečítat nebo je navzájem porovnávat bez nutnosti zaobírání se počtem sekund od roku 1970 nebo indexy ve výstupu ve formě tuple. Nyní si ukážeme, jak se tyto objekty zakládají a jak s nimi budeme dál pracovat v jednotlivých modulech.

Třída datetime

Velmi významnou třídou v této knihovně je stejnojmenná třída datetime a její opět stejnojmenná :-) metoda datetime(). Tu budeme v praxi používat pro vytváření instancí, se kterými budeme dále pracovat. Také poskytuje užitečné metody, které budeme hojně využívat.

Běžnou konvencí, kterou dodržujeme i v našich tutoriálech, je pojmenování třídy velkým písmenem, a tedy bychom měli třídu pojmenovat Datetime. Vývojáři Pythonu bohužel na konvence v názvech modulů a tříd často příliš neberou ohled. Aby náš text lekce odpovídal skutečnému kódu, budeme na třídu odkazovat jako na datetime s malým počátečním písmenem. Jinak by se text lekce od kódu lišil a bylo by to matoucí.

Metody třídy datetime

Podívejme se nyní na důležité metody, které nám třída datetime poskytuje. Jak už jsme zmínili v úvodu lekce, mnoho metod je stejných nebo velmi podobných s funkcemi modulu time.

Metoda datetime()

Metoda datetime() přijímá jako argumenty v daném pořadí údaje: rok, měsíc, den, hodina, minuta, sekunda a mikrosekunda. Vytvořme si instanci data a času z určitého roku, měsíce a dne:

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)
Metoda now()

Metoda now() nám jednoduše umožní získat aktuální datum a čas:

from datetime import datetime

dnes = datetime.now()
print(dnes)

Metoda vytvoří instanci třídy datetime, ve které jsou uloženy aktuální informace k datu. K jednotlivým údajům se dostaneme velmi lehce a to pomocí atributů 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}")

Metoda weekday()

Metoda, kterou voláme na instanci třídy datetime, nám zjistí den v týdnu, ke kterému tato instance patří. Zkusme si ji zavolat na aktuálním datu a času:

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 této metodě se pro nás ukrývá mnoho možností, a je pouze na nás, jaký formát pro získávání data a času si zvolíme.

Knihovna datetime dále mimo jiné obsahuje také například metody strftime() a strptime(). Tyto metody (a další) jsou prakticky identické se stejnojmennými funkcemi z modulu time, kterými jsme se zabývali v lekci Datum a čas v Pythonu. Ke srovnání je nejlepší nahlédnout do oficiální dokumentace knihovny datetime.

Práce s datem

Práce s daty je jedním z nejčastějších úkolů v programování. Ať už potřebujeme porovnat dvě data nebo spočítat počet dní mezi nimi, knihovna datetime nám nabízí efektivní nástroje pro tyto úkoly. Výhodou knihovny datetime je její objektový přístup k reprezentaci času a data. Díky tomu, že všechna data ukládáme jako instance té samé třídy, máme tedy možnost provádět s daty různé aritmetické operace, jako je sčítání a odčítání, nebo porovnávat data mezi sebou. V této kapitole se podíváme na několik základních operací a funkcí, které nám datetime nabízí pro práci s daty, a ukážeme si, jak je efektivně využít v praxi.

Aritmetické operace s datem

Nejprve se zaměříme na základní matematické operace jako jsou sčítání a odčítání:

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 případě proměnná ubehly_cas obsahuje počet dnů, hodin, minut a sekund, které uběhly od začátku 3. tisíciletí do dnešního dne. Za podobným účelem máme ještě k dispozici metodu total_seconds(), která vrátí počet sekund uběhlých v daném intervalu.

Porovnávání

Dvě data můžeme mezi sebou i porovnávat a to obyčejnými operátory, které používáme při porovnávání čí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

Změna vytvořeného data

Pokud potřebujeme rychle a snadno změnit již vytvořené datum, použijeme metodu replace(). Zvyšme si rok a den na objektu 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}.")

Metoda replace() funguje na jakémkoliv časovém objektu - jen v ní musíme přesně specifikovat, co chceme měnit na jakou hodnotu. Jde pouze o změnu hodnoty již založené proměnné.

Pokud je dnes.day poslední den měsíce (např. 31. ledna nebo 30. dubna), přidání jednoho dne způsobí ValueError.

Podobné problémy nicméně řeší třída timedelta. Podívejme se na ni.

Třída timedelta

Pro další možnosti práce s časem je zde třída timedelta. Třída timedelta nám umožňuje vyjádřit časový interval, což může zahrnovat dny, sekundy, mikrosekundy a podobně. S instancemi timedelta lze podobně jako v případě třídy datetime provádět různé aritmetické operace, například přidávat je k instancím datetime nebo odečítat je od sebe. Pokud od sebe dvě data například odečteme, získáme instanci třídy timedelta, což není konkrétní datum, ale interval (rozdíl) mezi nějakými dvěma daty. Tento objekt si založíme a snadno zjistíme, jaký den bude za 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}")

Třída timedelta také řeší problém s přechodem z měsíce na měsíc. Pokud interval přesáhne plný (nebo minimální) počet dní v daném měsíci, třída automaticky přejde na další (předchozí) měsíc v pořadí.

Konstruktor timedelta() nemusíme vždy použít s celými dny. Pokud chceme pracovat s jinou hodnotou, máme tu možnost. Při zakládání objektu timedelta máme možnost navolit mnoho argumentů. Pokud explicitně neuvedeme názvy argumentů, tak v uvedeném pořadí:

  • days,
  • seconds,
  • microseconds,
  • milliseconds,
  • minutes,
  • hours,
  • weeks.

Čekali bychom, že největší jednotky (jako týdny nebo dny) budou v argumentech uvedeny jako první, následované menšími jednotkami (hodiny, minuty atd.). Proč je pořadí argumentů takto podivné? To je otázka, na kterou není jednoznačná odpověď. Je možné, že to je historická záležitost nebo designová volba vývojářů Pythonu, která může být založena na interním zpracování nebo jiných aspektech implementace. Nebo se zkrátka někdo opravdu špatně vyspal :-D V každém případě, když vytváříme instanci timedelta, je dobré si zvyknout explicitně uvádět jména argumentů. Zvýšíme tím čitelnost kódu a eliminujeme potenciální zmatek:

interval = timedelta(weeks=2, days=3, hours=1)

Třída timedelta bohužel nemá v argumentech dostupný počet let a měsíců, protože rok ani měsíc nejsou plnohodnotné časové jednotky a nemají pevně daný počet dní (některé roky jsou přestupné).

Ořezání data o čas

Všechny metody, které jsme si dosud zmínili, pracují s objekty datetime (datum a čas). Pokud bychom chtěli využívat pouze datum, je vhodné místo tohoto použít objekt date. Ten nenese informaci o času, která by nám jinak mohla znepříjemňovat třeba porovnávání. Objekt date získáme z třídy datetime pomocí metody 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)}")

Není na tom nic složitého. Jediná změna od datetime je v použití metody today(), která přímo nahrazuje now(). Veškeré metody používané výše v lekci jsou s tímto formátem naprosto kompatibilní. Pokud tedy ve svých programech nepotřebujeme časové informace, můžeme je poměrně snadno vynechat.

Souběžné použití time a datetime

Pokud se rozhodneme v jednom programu využívat současně moduly time a datetime, na první pohled nám to přinese určité výhody. Zejména širokou škálu funkcí a metod obou modulů. Avšak je zde jedno velké "ale".

Oba moduly mají, jak už jsme si zmínili, mnoho funkcí a metod se stejným názvem, například strftime(). Pokud oba moduly naimportujeme kompletně pomocí import time a import datetime, budeme muset uvádět, z kterého modulu chceme danou funkci nebo metodu používat. Třeba takto - time.strftime() nebo datetime.datetime.strftime(). To povede k velmi nepřehlednému kódu a pravděpodobně také ke zbytečným chybám. Proto je velmi vhodné při importech použít aliasy nebo třídy importovat přímo:

from datetime import datetime as dt
from datetime import timedelta

Díky tomu si budeme jistí, jakou funkci či metodu z jakého modulu skutečně voláme.

V následujícím kvízu, Kvíz - Datum a čas v Pythonu, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Datum a čas v Pythonu
Všechny články v sekci
Objektově orientované programování v Pythonu
Přeskočit článek
(nedoporučujeme)
Kvíz - Datum a čas v Pythonu
Článek pro vás napsal Marek Bečvář
Avatar
Uživatelské hodnocení:
349 hlasů
Marek Bečvář
Aktivity