Datum a čas v Javě pomocí třídy Calendar

Java Objektově orientované programování Datum a čas v Javě pomocí třídy Calendar

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Upozornění: Tento článek je na síti umístěn pouze pro účely pochopení starších aplikací. Od Javy 8 je k dispozici nové API pro práci s časem. Více se o něm dočtete v článku Datum a čas v Javě 8.

Calendar

S datem a časem se v Javě dříve pracovalo pomocí třídy Date. Ta však byla označena za zastaralou a nyní se využívá třída Calendar. Pokud se v nějakých meteriálech setkáte s třídou Date, nepoužívejte ji. Název může Calendar může být poněkud matoucí, jedná se v podstatě o kalendář v paměti počítače, který si nastavíme na určitý datum a čas. Tímto způsobem se v Javě datum a čas ukládá. kalendář vždy obsahuje i čas, ten můžeme a nemusíme používat (např. ho nebudeme ani zadávat ani vypisovat, ale fyzicky tam bude přítomný).

Vytvoření instance s aktuálním datem a časem

Začněme tím, jak lze instanci Calendar vytvořit. Vytvoříme si projekt s názvem DatumACas. Do balíčku si přidáme import java.util.Calendar. V Javě je to s datem a časem trochu zamotané. Když chceme vytvořit novou instanci kalendáře, zavoláme na třídě Calendar statickou metodu getInstance():

Calendar kalendar = Calendar.getInstance();

Nyní naše proměnná kalendar obsahuje kalendář, nastavený na aktuální datum a čas. Pojďme si ho vypsat. Pokud napíšeme:

System.out.println(kalendar);

Vypíše se pouze ošklivá textová reprezentace objektu. Jakmile chceme instanci Calendar vypisovat, potřebujeme k tomu tzv. formatter. Přidáme import java.text.Sim­pleDateFormat a po vytvoření kalendáře vytvoříme formatter s následujícím formátem:

DateFormat formatData = new SimpleDateFormat("d.MMMM yyyy H:mm");

A vypíšeme:

System.out.println(formatData.format(kalendar.getTime()));

Výsledek:

Výpis aktuálního data a času v Javě

Úprava hodnoty

K existujícímu kalendáři můžeme přičítat určitý počet dní, hodin a podobně. Slouží k tomu metoda add(), která bere jako 1. parametr konstantu políčka kalendáře a jako druhý počet jednotek, které chceme přidat. Konstanty nalezneme na třídě Calendar, označují co chceme přidávat.

Zkusme si to a přidejme našemu kalendáři 3 dny v týdnu:

kalendar.add(Calendar.DAY_OF_MONTH, 3);

Výsledek:

4.duben 2013 18:45

Pokud bychom zadali zápornou hodnotu, dny bychom ubrali. V prvním parametru metody můžete použít mnoho konstant, budou to zejména:

  • DAY_OF_MONTH - Den v měsíci
  • HOUR_OF_DAY - Hodina
  • MILLISECOND - Milisekunda
  • MINUTE - Minuta
  • MONTH - Měsíc
  • YEAR - Rok

Nastavení hodnoty

Hodnotu kalendáře můžeme jednoduše nastavit pomocí metody set(). Má stejné parametry jako metoda add(), jen hodnoty nastavuje místo toho, aby je přičítala k existujícím. Zkusme si nastavit kalendář na programátorské vánoce, tedy na Halloween (ano, protože 31 OCT = 25 DEC).

kalendar.set(Calendar.DAY_OF_MONTH, 31);
kalendar.set(Calendar.MONTH, 9);
kalendar.set(Calendar.YEAR, 2013);

Výsledek:

31.říjen 2013 18:48

Může být matoucí, že měsíce začínají od nuly. Leden je tedy nultý a říjen je deváty! Pro jistotu můžeme při nastavování hodnoty použít konstantu OCTOBER (říjen):

kalendar.set(Calendar.MONTH, Calendar.OCTOBER);

Čtení hodnoty

Pro čtení určité hodnoty slouží opět konstanty, NetBeans vám jich v nabídce nabídne opravdu mnoho. Čtení probíhá metodou get(), která opět bere v parametru konstantu políčka. Ke konstantám, co jsem zmínil výše, můžeme přidat ještě:

  • DAY_OF_WEEK - Vrátí den v týdnu
  • WEEK_OF_YEAR - Týden v roce. Můžeme tak např. zjistit, zda je sudý nebo lichý týden.
  • HOUR - Hodina ve formátu 1-12. Jestli je 0 odpoledne nebo poledne označuje hodnota konstanty AM_PM.
  • AM_PM - Pokud je zde hodnota AM, hodnota v HOUR znamená před polednem. Hodnota PM označuje po poledni.

Zkusme si vypsat nějakou vlastnost našeho kalendáře:

System.out.printf("Hodina: %s\n", kalendar.get(Calendar.HOUR_OF_DAY));

Výstup:

Hodina: 5

Parsování data a času

Asi se nám bude často stávat, že budeme chtít po uživateli zadat nějaké datum, případně i čas. Formatter data nám k těmto účelům nabízí metodu parse(). Nechme uživatele zadat datum v textové podobě a poté ho převeďme do objektu Calendar a vypišme.

Scanner sc = new Scanner(System.in, "Windows-1250");

Calendar kalendar = Calendar.getInstance();

System.out.print("Zadej datum ve formátu 1.1.2000 13:14:");
formatData = new SimpleDateFormat("d.M.yyyy H:mm");
try {
    kalendar.setTime(formatData.parse(sc.nextLine()));
    System.out.println("Zadal jsi datum: " + formatData.format(kalendar.getTime()));
} catch (ParseException ex) {
    Logger.getLogger(DatumACas.class.getName()).log(Level.SEVERE, null, ex);
}

Výsledek:

Parsování data a času v Javě

Parsování musíme obalit blokem try a přidat blok catch, NetBeans nám tuto úpravu nabídne a udělá ji za nás. K výjimkám (try a catch) se v seriálu dostaneme později. Parsování musí být v try bloku z toho důvodu, že uživatel může zadat nesprávný formát. Parsování se potom nepovede a program pokračuje v bloku catch, kde na chybu zareagujeme.

Bude potřeba přidat importy java.text.Par­seException a několik dalších k loggeru, NetBeans by to měl udělat za vás nebo použijte Fix Imports.

Tabulka jednotlivých znaků, které v řetězci formatteru můžeme použít a jejich význam je poněkud vyčerpávající, zájemce odkáži na oficiální dokumentaci, kde jsou vysvětleny jednotlivé složky patternu: http://docs.oracle.com/…eFormat.html

Jednotlivé kalendáře můžeme porovnávat pomocí metody compareTo(). Hotový projekt se vším, co jsme v článku dělali, naleznete jako vždy v příloze.


 

Stáhnout

Staženo 553x (16.67 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
7 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (3)

 

 

Komentáře
Zobrazit starší komentáře (29)

Avatar
Tom Barbořík:26.7.2014 23:35

Čau,
teď je v Java 8 nové api pro práci s časem a datem.
http://docs.oracle.com/…summary.html
Přišlo mi dobré to zmínit.

 
Odpovědět 26.7.2014 23:35
Avatar
Petr.Matras
Člen
Avatar
Petr.Matras:25.4.2015 2:24

Navazuju na dotaz Matěje Kripnera - jaký je smysl ukládání objektu podtřídy SimpleDateFormat do reference typu jeho abstraktního předka DateFormat?

DateFormat formatData = new SimpleDateFormat("d.MMMM yyyy H:mm");

Chápu, že to dědičnost umožnuje, ale plynou z toho v tomto případě nějaké výhody pro další práci s tímto objektem? Odpověď na Matějův dotaz, že až bude umět víc OOP, tak to pochopí, se mi jeví lehce nedostačující :)
A jak bylo zmíněno, v textu lekce by bylo potřeba doplnit informaci, že je potřeba naimportovat také java.text.Date­Format, když už se používá reference tohoto typu.

Editováno 25.4.2015 2:26
Odpovědět  +2 25.4.2015 2:24
Sometimes you just do things. - Scott Jurek
Avatar
Marcel Smolik:11.7.2015 1:00

Jsem zmaten mam se ucit celendr nebo API abych to nečet zbytečně.

 
Odpovědět 11.7.2015 1:00
Avatar
Odpovídá na Marcel Smolik
Marcel Smolik:11.7.2015 1:02

Pardon oprava mam číst tento článek nebo ten nový se zaměřením na datum a čas.

 
Odpovědět 11.7.2015 1:02
Avatar
secretcode
Člen
Avatar
secretcode:3.3.2016 16:09

Chyba v riadku

formatData = new SimpleDateFormat("d.M.yyyy H:mm");

Chyba tam typ deklaracie premennej formatData

SimpleDateFormat formatData = new SimpleDateFormat("d.M.yyyy H:mm");
Editováno 3.3.2016 16:09
 
Odpovědět 3.3.2016 16:09
Avatar
Debrax
Člen
Avatar
Debrax:26.4.2016 12:17

Menší preklep v úvode
Název může Calendar může být poněkud matoucí...

..a pozerám, že chyba formatData.. už bola spomenutá :)

 
Odpovědět 26.4.2016 12:17
Avatar
Pavel Habžanský:27.5.2016 14:39

Naštěstí inteligentnější IDE jako IntelliJ (nevím, jak NetBeans) to sami naimportujou, jakmile se pokusíš vytvořit instanci třídy, ke které potřebuješ daný balíček :-)

Odpovědět 27.5.2016 14:39
Čím větší výzva, tím větší zkušenost
Avatar
Roman Duchoň:27.9.2016 16:55

No... ač mi fungují, zatím nerozumím příkazům try a catch. Takový složitě vypadají příkazy a oni neumí ošetřit, když zadám něco špatně? Mlčím. Třeba jen má neznalost.

A co to odčítá datumů (zde na stránkách schválně použit tento tvar)?
Zkusil jsem něco jako:

public int porovnej()    {
        ted.set(Calendar.MILLISECOND, 0);
        ted.set(Calendar.SECOND, 0);
        ted.set(Calendar.MINUTE, 0);
        ted.set(Calendar.HOUR_OF_DAY, 0);
        bude.set(Calendar.MILLISECOND, 0);
        bude.set(Calendar.SECOND, 0);
        bude.set(Calendar.MINUTE, 0);
        bude.set(Calendar.HOUR_OF_DAY, 0);
        long tedMili = ted.getTimeInMillis();
        long budeMili = bude.getTimeInMillis();
        long rozdilMili = budeMili - tedMili;
        long denMili = 86400000;
        int dnu = (int) (rozdilMili / denMili);
        return dnu;
}

Opravdu to nejde jednodušeji? A co když budu chtít zapojit měsíce? Roky? Hodiny? A abych se nedostal do záporných hodnot?
Možná je to zbytečný dotaz, jen mě to trochu zarazilo. Občas jsem se i divil, jak jde něco jednoduše. Něco, co si dokáže člověk normálně představit programovací jazyk dokázal vystihnout líp, ale tohle...

Odpovědět 27.9.2016 16:55
RD
Avatar
Atrament
Člen
Avatar
Odpovídá na Roman Duchoň
Atrament:28.9.2016 11:07

Tento článek už není příliš aktuální, je to uvedeno přímo v úvodu článku. Od Javy 8 je k dispozici komplet nové API na práci s časem, na zjištění počtu dní mezi dvěma datumy se dá použít ChronoUnit

LocalDate ted = LocalDate.now();
LocalDate potom = LocalDate.of(2016, 11, 19);
ChronoUnit.DAYS.between(ted, potom);
 
Odpovědět  +3 28.9.2016 11:07
Avatar
Odpovídá na Atrament
Roman Duchoň:29.9.2016 12:23

Úžasné! :) Dík.

Pozn. pro budoucí čtenáře:

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

edit: Měl jsem si přečíst ten článek, na který se odkazuje na začátku.
Ono asi neplatí, že když se učím základy, neměl bych řešit novinky...

Editováno 29.9.2016 12:26
Odpovědět 29.9.2016 12:23
RD
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 39. Zobrazit vše