Java Datum a čas

⚡ Chytré shrnutí

Java Zpracování data a času kombinuje starší třídy java.util.Date a SimpleDateFormat s moderním rozhraním API java.time, které bylo představeno v roce Java 8, což vývojářům poskytuje neměnné, vláknově bezpečné typy pro přesnou práci s kalendářem.

  • 🕒 Datum vydání: Třída java.util.Date ukládá okamžitý údaj v milisekundách a pomocí metody toString vypíše výchozí řetězec.
  • 🔤 Vzorová písmena: SimpleDateFormat používá písmena jako rrrr, MM, dd, HH, mm, ss a zzz k definování vlastních výstupních formátů.
  • 🇧🇷 Srovnání: Metoda compareTo vrací záporné, nulové nebo kladné celé číslo pro chronologické seřazení dvou instancí třídy Date.
  • 🆕 Moderní API: Objekty LocalDate, LocalDateTime, ZonedDateTime a Instant v souboru java.time nahrazují objekty Date a Calendar neměnnými objekty.
  • 🧵 Bezpečnost vlákna: DateTimeFormatter je neměnný a bezpečný pro sdílení, zatímco SimpleDateFormat vyžaduje synchronizaci nebo obalový objekt ThreadLocal.
  • 🔁 Interoperabilita: Převádějte mezi starým a novým API pomocí pomocných funkcí Date.toInstant, Date.from a Calendar.toInstant.

Java Datum a čas

Zpracování dat a časů v Java je rutinní součástí vytváření plánovací logiky, časových razítek protokolů, reportů a auditních záznamů. Před napsáním jakéhokoli kódu je užitečné znát parametry, které tvoří datum:

  • Jedno rok (ve dvou nebo čtyřech číslicích).
  • Jedno měsíc (jako dvě číslice, jako první tři písmena měsíce nebo jako celý název měsíce).
  • Jedno datum (skutečné číslo dne v měsíci).
  • Jedno den (název dne v daném datu, například Ne, Po, Út).

Java zpřístupňuje mnoho dalších parametrů, které popisují okamžik na časové ose, včetně éry, týdne v roce, časového pásma a posunu. Následující části se zabývají každým z nich s příklady, které lze spustit.

Jak používat Date in Java

Zobrazit datum v Java

Java poskytuje Date třídy v java.util balíček. Třída ukládá specifický okamžik v čase s přesností na milisekundy a nabízí pomocné metody pro tisk, porovnání a formátování tohoto okamžiku. Chcete-li získat aktuální datum a čas, vytvořte instanci třídy s jejím výchozím konstruktorem:

import java.util.Date;

class Date_Ex1 {
    public static void main(String args[]) {
        // Instantiate a Date object by invoking its constructor
        Date objDate = new Date();
        // Display the Date and Time using toString()
        System.out.println(objDate.toString());
    }
}

Výstup:

Wed Nov 29 06:36:22 UTC 2017

Příklad vytiskne datum ve výchozím formátu toString. Chcete-li zobrazit stejný okamžik v jiném vzoru, musíte nejprve porozumět formátovacím písmenům, která Java použití.

SimpleDateFormat: Analýza a formátování dat

Jedno SimpleDateFormat třída v java.text převádí Date objekt do formátovaného řetězce a analyzuje formátovaný řetězec zpět do DatePoužívá vzorová písmena, která se mapují na komponentu data nebo času. V následující tabulce jsou uvedena všechna podporovaná písmena:

DopisSložka data nebo časuPříklad
GOznačení éryAD
yRok výroby2026
MMěsíc v rocečervence nebo července nebo 07
wTýden v roce27
WTýden v měsíci2
DDen v roce189
dDen v měsíci10
FDen v týdnu v měsíci2
ENázev dne v týdnuúterý nebo úterý
uČíslo dne v týdnu (1 = Monday, 7 = neděle)1
aZnačka AM nebo PMPM
HHodina za den (0-23)0
kHodina za den (1-24)24
KHodina v AM nebo PM (0–11)0
hHodina v AM nebo PM (1–12)12
mMinuta za hodinu30
sDruhý za minutu55
SMilisekunda978
zČasové pásmo (název)tichomořský standardní čas; PST; GMT-08:00
ZČasové pásmo (posun dle RFC 822)-0800
XČasové pásmo (posun ISO 8601)-08 nebo -0800 nebo -08:00

Nemusíte si pamatovat celou tabulku. Prohlédněte si ji vždy, když vytváříte nový vzor.

Jak používat SimpleDateFormat

SimpleDateFormat je podtřídou DateFormat který umožňuje formátovat a analyzovat data pomocí výše uvedených vzorových písmen. Spojte písmena a popište přesný řetězec, který chcete vytvořit nebo přečíst.

Například:

  1. Požadovaný formát data: 2012.10.23 20:20:45 PSTVhodný formátovací vzor je yyyy.MM.dd HH:mm:ss zzz.
  2. Požadovaný formát data: 09:30:00 AM 23-May-2012Vhodný formátovací vzor je hh:mm:ss a dd-MMM-yyyy.

Tip: Sledujte velká a malá písmena. Velká písmena M je měsíc, malými písmeny m je minuta. Velká písmena H je 24hodinový formát hodin, malými písmeny h je 12hodinový formát. Jejich záměna vede k tichému chybnému výstupu.

Následující program vytiskne aktuální datum dvakrát, jednou ve výchozím formátu a jednou pomocí vzoru SimpleDateFormat:

import java.text.SimpleDateFormat;
import java.util.Date;

class TestDates_Format {
    public static void main(String args[]) {
        // Current system date and time is assigned to objDate
        Date objDate = new Date();
        System.out.println(objDate);

        // Build the target pattern and format the date
        String strDateFormat = "hh:mm:ss a dd-MMM-yyyy";
        SimpleDateFormat objSDF = new SimpleDateFormat(strDateFormat);
        System.out.println(objSDF.format(objDate));
    }
}

Výstup:

Wed Nov 29 06:31:41 UTC 2017
06:31:41 AM 29-Nov-2017

Příklad porovnání dat

Příklad porovnání dat

Nejspolehlivější způsob, jak si objednat dva Date objekty jsou compareTo() Metoda. Vrací záporné celé číslo, když je volající dříve, nulu, když jsou oba okamžiky stejné, a kladné celé číslo, když je volající později. Úryvek kódu níže analyzuje dva řetězce data a vypisuje jejich relativní pořadí:

import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;

class TestDates_Compare {
    public static void main(String args[]) throws ParseException {

        SimpleDateFormat objSDF = new SimpleDateFormat("dd-MM-yyyy");
        Date dt_1 = objSDF.parse("20-08-1981");
        Date dt_2 = objSDF.parse("12-10-2012");

        System.out.println("Date1 : " + objSDF.format(dt_1));
        System.out.println("Date2 : " + objSDF.format(dt_2));

        // compareTo returns > 0 when dt_1 is after dt_2
        if (dt_1.compareTo(dt_2) > 0) {
            System.out.println("Date 1 occurs after Date 2");
        }
        // compareTo returns < 0 when dt_1 is before dt_2
        else if (dt_1.compareTo(dt_2) < 0) {
            System.out.println("Date 1 occurs before Date 2");
        }
        // compareTo returns 0 when both dates are equal
        else {
            System.out.println("Both are the same date");
        }
    }
}

Výstup:

Date1 : 20-08-1981
Date2 : 12-10-2012
Date 1 occurs before Date 2

Poznámka: Původní kód používal vzor dd-mm-yyyyMalá písmena mm písmeno je minuta, ne měsíc, takže analyzátor tiše vygeneroval nesprávnou hodnotu měsíce. Výše ​​uvedená oprava používá velká písmena. MM pro měsíc, což je správné vzorové písmeno.

Java 8 Moderní API pro datum a čas (java.time)

Java 8 představil java.time balíček, přepracované API inspirované knihovnou Joda-Time. Nové třídy jsou neměnné, bezpečné pro práci z více vláken a oddělují lidský kalendář od časové osy stroje. Nejběžnější typy jsou:

  • LocalDate pro datum bez časového pásma nebo časového údaje (například narozeniny).
  • LocalTime pro nástěnné hodiny bez data nebo pásma.
  • LocalDateTime pro datum a čas bez pásma.
  • ZonedDateTime pro datum a čas s konkrétním časovým pásmem.
  • OffsetDateTime pro datum a čas s posunem UTC, ale bez pojmenované zóny.
  • Instant pro časové razítko stroje měřené od epochy UNIXu.
  • Duration a Period pro částky založené na čase a datu.

Následující příklad vytiskne aktuální datum, čas, časové razítko a časové pásmo pomocí moderního API:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.Instant;
import java.time.ZoneId;

class ModernDateDemo {
    public static void main(String args[]) {
        LocalDate today = LocalDate.now();
        LocalDateTime now = LocalDateTime.now();
        ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
        Instant epoch = Instant.now();

        System.out.println("LocalDate     : " + today);
        System.out.println("LocalDateTime : " + now);
        System.out.println("ZonedDateTime : " + zoned);
        System.out.println("Instant       : " + epoch);
    }
}

Každý typ má tovární metody (now, of, parse) a neměnné operace (plusDays, minusHours, withYear), které vracejí novou hodnotu namísto mutace původního objektu.

DateTimeFormatter: Formátování data v moderním jazyce Java

DateTimeFormatter in java.time.format nahrazuje SimpleDateFormatPoužívá stejný styl vzorových písmen, je neměnný a lze jej bezpečně sdílet napříč vlákny bez nutnosti další synchronizace. Třída také nabízí hotové konstanty, jako například ISO_LOCAL_DATE a ISO_ZONED_DATE_TIME pro standardní formáty.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

class FormatterDemo {
    public static void main(String args[]) {
        LocalDateTime now = LocalDateTime.now();

        DateTimeFormatter iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter human = DateTimeFormatter.ofPattern("hh:mm:ss a dd-MMM-yyyy");

        System.out.println(now.format(iso));
        System.out.println(now.format(human));

        LocalDateTime parsed = LocalDateTime.parse("2026-07-04T09:30:00", iso);
        System.out.println("Parsed back : " + parsed);
    }
}

Chcete-li porovnat dvě data v moderním API, zavolejte isBefore, isAfternebo isEqualTyto metody se čtou jasněji než compareTo a pracovat s každým java.time třída.

Bezpečnost vláken a osvědčené postupy pro Java Datum a čas

Oba java.util.Date a SimpleDateFormat předcházely modernímu souběžnému Javaa každý z nich má známá úskalí. Pro zajištění správného zpracování dat v produkčním kódu dodržujte níže uvedené postupy:

  • Upřednostněte java.time před datem a kalendářem. Nové typy jsou neměnné a bezpečné pro práci z více vláken a přesněji modelují doménu (data bez časů, časy bez pásem atd.).
  • Nesdílejte SimpleDateFormat napříč vlákny. Třída ukládá interní stav parsování a není bezpečná pro vlákna. Zabalte ji do ThreadLocal, synchronizovat v instanci nebo přepnout na DateTimeFormatter.
  • Vždy zadejte národní prostředí. Názvy měsíců a dnů se mění v závislosti na výchozím národním prostředí JVM, což vytváří vzory jako MMM a EEE nepřenosné. Explicitně předejte locale (například Locale.ENGLISH).
  • Buďte explicitní ohledně časových pásem. LocalDateTime nemá žádnou zónu, takže převeďte na ZonedDateTime or Instant kdykoli je důležitý přesný okamžik, zejména u protokolů, sloupců databáze a síťových dat.
  • Pečlivě převádějte mezi těmito dvěma API. Použijte date.toInstant(), Date.from(instant), a calendar.toInstant().atZone(zone) na hranici mezi starším a moderním kódem.
  • Ukládat časová razítka v UTC. Vytrvejte a transmit data jako UTC ( Instant nebo řetězec ISO 8601) a převést do uživatelské zóny pouze při zobrazení.

Nejčastější dotazy

Pro datum a čas v systémové zóně zavolejte LocalDateTime.now() z balíčku java.time nebo LocalDate.now() pouze pro datum. Na starších verzích Java, použijte new java.util.Date() k získání aktuálního okamžiku.

java.util.Date představuje okamžik v milisekundách od epochy a je měnitelný. LocalDate modeluje kalendářní datum bez času nebo pásma, je neměnný a bezpečný pro více vláken a nabízí přehlednější metody, jako například plusDays a isBefore.

Ne. SimpleDateFormat udržuje proměnlivý stav parsování a při sdílení napříč vlákny produkuje nesprávné výsledky. Zabalte ho do ThreadLocal, synchronizujte v instanci nebo přepněte na DateTimeFormatter, který je neměnný a bezpečný.

Zadejte přesný řetězec „rrrr-MM-dd“. Velká písmena MM označují měsíc, malá písmena mm minuty. Pro úplné datum a čas použijte „rrrr-MM-dd HH:mm:ss“. Vždy zadejte národní prostředí, aby názvy měsíců zůstaly reprodukovatelné.

U staršího data použijte metodu compareTo, která vrací záporné, nulové nebo kladné celé číslo. U java.time volejte metodu isBefore, isAfter nebo isEqual pro LocalDate nebo Instant. Oba přístupy respektují chronologické pořadí.

Zavolejte date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(). Pro návrat použijte Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()). Vyberte zónu explicitně, kdykoli je důležitý přesný okamžik.

Modely umělé inteligence trénované na korpusech protokolů a dokumentů odvozují pravděpodobný vzorec z ukázkových řetězců a vracejí odpovídající vzor DateTimeFormatter. Klasifikátory strojového učení také označují nejednoznačná pole, jako je pořadí měsíc-den versus den-měsíc.

Ano. GitHub Copilot navrhuje vzory DateTimeFormatter, konverze ZonedDateTime a JUnit testy pro výstup citlivý na místní nastavení. RevPřed potvrzením si prohlédněte každý návrh, zda obsahuje správná písmena vzoru, národní prostředí a časové pásmo.

Shrňte tento příspěvek takto: