JAVA PAGRINDAI DETALIAU

Java datos ir laikas

Java turi senąsias Date bei Calendar klases ir modernų java.time API. Naujam kodui dažniausiai rinkis java.time, nes jo klasės aiškesnės, nekintamos ir saugios naudoti keliose gijose.

Kurią klasę rinktis?

Pagrindinės Java datos ir laiko klasės
KlasėKą vaizduoja?BūsenaRekomendacija
java.util.DateLaiko momentą milisekundėmis nuo Unix epochosKeičiama, senasis APINaudok tik integracijai su senu kodu
java.util.CalendarDatą ir kalendoriaus laukų skaičiavimusKeičiama, sudėtingas senasis APINaujam kodui venk
LocalDateDatą be laiko ir laiko zonosNekintama, moderniGimtadieniams, šventėms, terminų datoms
ZonedDateTimeDatą, laiką ir konkrečią laiko zonąNekintama, moderniŽmonėms rodomam laikui skirtingose zonose
InstantTikslią UTC laiko juostos akimirkąNekintama, moderniĮvykių žymoms, žurnalams ir sistemų mainams
Svarbus tikslumas

Date ir Calendar klasės nėra visiškai pašalintos ar visa apimtimi pažymėtos deprecated. Jos laikomos senuoju (legacy) API, o dalis Date konstruktorių ir metodų yra pažymėti deprecated. Naujam kodui rekomenduojamas java.time.

1. java.util.Date

Date saugo vieną laiko momentą kaip milisekundžių skaičių nuo 1970 m. sausio 1 d. 00:00:00 UTC. Pavadinimas klaidina: klasė vaizduoja ne vien kalendorinę datą, bet konkrečią akimirką.

import java.util.Date;

Date pradzia = new Date(0);

System.out.println(pradzia.getTime());
System.out.println(pradzia.toInstant());
Konsolės rezultatas

0
1970-01-01T00:00:00Z

  1. new Date(0) sukuria pačią Unix epochos pradžią.
  2. getTime() parodo nuo epochos praėjusias milisekundes – šiuo atveju nulį.
  3. toInstant() tą pačią akimirką pateikia moderniu Instant tipu.

Venk: senų konstruktorių, kuriuose tiesiogiai perduodami metai, mėnuo ir diena. Jų taisyklės painios, o daugelis pažymėti deprecated.

2. java.util.Calendar

Calendar buvo sukurta patogesniam datos laukų keitimui, laiko zonoms ir lokalėms. Ji vis dar veikia, tačiau yra keičiama, plati ir turi netikėtų taisyklių.

import java.util.Calendar;

Calendar kalendorius = Calendar.getInstance();
kalendorius.set(2026, Calendar.AUGUST, 14);
kalendorius.add(Calendar.DAY_OF_MONTH, 7);

System.out.println(kalendorius.get(Calendar.YEAR));
System.out.println(kalendorius.get(Calendar.MONTH) + 1);
System.out.println(kalendorius.get(Calendar.DAY_OF_MONTH));
Konsolės rezultatas

2026
8
21

  1. Nustatome 2026 m. rugpjūčio 14 d.
  2. add(..., 7) prideda septynias dienas ir gauna rugpjūčio 21 d.
  3. Calendar.MONTH skaičiuojamas nuo nulio, todėl spausdindami pridedame 1.

Rekomendacija: naujame kode vietoje Calendar naudok LocalDate, ZonedDateTime ar kitą tinkamą java.time klasę.

3. java.time.LocalDate

LocalDate saugo tik metus, mėnesį ir dieną. Ji neturi valandų ir nežino laiko zonos, todėl puikiai tinka gimtadieniui, atostogų dienai ar sąskaitos terminui.

import java.time.LocalDate;

LocalDate gimtadienis = LocalDate.of(2012, 4, 18);
LocalDate poSavaites = gimtadienis.plusDays(7);

System.out.println(gimtadienis);
System.out.println(poSavaites);
System.out.println(gimtadienis.getYear());
Konsolės rezultatas

2012-04-18
2012-04-25
2012

  1. of(2012, 4, 18) sukuria aiškiai nurodytą datą.
  2. plusDays(7) nekeičia pradinio objekto – grąžina naują datą.
  3. Tai yra nekintama (immutable) klasė, todėl jos objektus saugu bendrinti.
Nenaudok LocalDate tiksliai akimirkai.

„2026-08-14“ nepasako, kurią valandą ir kurioje pasaulio vietoje įvykis nutiko.

4. java.time.ZonedDateTime

ZonedDateTime sujungia datą, laiką ir tikrą zonos identifikatorių, pavyzdžiui, Europe/Vilnius. Ji pati pritaiko vasaros bei žiemos laiko taisykles.

import java.time.ZoneId;
import java.time.ZonedDateTime;

ZoneId vilnius = ZoneId.of("Europe/Vilnius");
ZonedDateTime susitikimas = ZonedDateTime.of(
    2026, 8, 14, 10, 30, 0, 0, vilnius
);

System.out.println(susitikimas);
System.out.println(susitikimas.withZoneSameInstant(
    ZoneId.of("America/New_York")
));
Konsolės rezultatas

2026-08-14T10:30+03:00[Europe/Vilnius]
2026-08-14T03:30-04:00[America/New_York]

Abiejose eilutėse rodoma ta pati pasaulinė akimirka, tačiau vietinis sieninio laikrodžio laikas skiriasi. Metodas withZoneSameInstant() išsaugo akimirką ir pakeičia tik jos pateikimo zoną.

5. java.time.Instant

Instant žymi tikslią akimirką UTC laiko skalėje ir tinka mašinų tarpusavio duomenims, įvykių laikui, audito įrašams bei laiko matavimams saugoti.

import java.time.Duration;
import java.time.Instant;

Instant pradzia = Instant.parse("2026-08-14T07:30:00Z");
Instant pabaiga = pradzia.plus(Duration.ofMinutes(45));

System.out.println(pradzia);
System.out.println(pabaiga);
System.out.println(Duration.between(pradzia, pabaiga).toMinutes());
Konsolės rezultatas

2026-08-14T07:30:00Z
2026-08-14T08:15:00Z
45

  1. Raidė Z reiškia UTC.
  2. Pridedame 45 minučių trukmę ir gauname naują Instant.
  3. Duration.between() apskaičiuoja tikslų skirtumą tarp akimirkų.

Datos formatavimas ir teksto nuskaitymas

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

LocalDate data = LocalDate.of(2026, 8, 14);
DateTimeFormatter formatas = DateTimeFormatter.ofPattern("yyyy-MM-dd");

String tekstas = data.format(formatas);
LocalDate atkurtaData = LocalDate.parse(tekstas, formatas);

System.out.println(tekstas);
System.out.println(atkurtaData);
Konsolės rezultatas

2026-08-14
2026-08-14

DateTimeFormatter yra nekintamas ir saugus naudoti keliose gijose. Senasis SimpleDateFormat yra keičiamas ir nėra saugus bendrinti tarp gijų, todėl naujame kode jo geriau vengti.

Kaip susieti seną ir naują API?

import java.time.Instant;
import java.util.Date;

Instant akimirka = Instant.parse("2026-08-14T07:30:00Z");
Date senaData = Date.from(akimirka);
Instant velAkimirka = senaData.toInstant();

System.out.println(velAkimirka);
Konsolės rezultatas

2026-08-14T07:30:00Z

Integruojantis su sena biblioteka galima laikinai konvertuoti Instant į Date ir atgal. Likusioje naujos programos dalyje patogiau išlaikyti java.time tipus.

Praktinės pasirinkimo taisyklės

  • Vien data be laiko – LocalDate.
  • Vietinis laikas be zonos – LocalDateTime, bet tik kai zona iš tiesų nesvarbi arba saugoma atskirai.
  • Žmonėms rodomas laikas konkrečioje pasaulio vietoje – ZonedDateTime.
  • Tiksli sisteminė akimirka – Instant.
  • Laiko tarpas – Duration; kalendorinis metų, mėnesių ar dienų skirtumas – Period.
  • Date ir Calendar palik senų sistemų suderinamumui.

Ko vengti?

  • Nesaugok gimtadienio kaip Instant, jei valanda ir zona neturi prasmės.
  • Nesaugok pasaulinio įvykio tik kaip LocalDateTime – be zonos jis nėra vienareikšmis.
  • Nenaudok trijų raidžių zonų, pavyzdžiui, CST; rinkis aiškų Europe/Vilnius tipo identifikatorių.
  • Nekurk bendro SimpleDateFormat kelioms gijoms.
  • Nepriklausyk nuo kompiuterio numatytosios laiko zonos, kai verslo taisyklė reikalauja konkrečios zonos.
  • Nepainiok java.util.Date su java.sql.Date.