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?
| Klasė | Ką vaizduoja? | Būsena | Rekomendacija |
|---|---|---|---|
java.util.Date | Laiko momentą milisekundėmis nuo Unix epochos | Keičiama, senasis API | Naudok tik integracijai su senu kodu |
java.util.Calendar | Datą ir kalendoriaus laukų skaičiavimus | Keičiama, sudėtingas senasis API | Naujam kodui venk |
LocalDate | Datą be laiko ir laiko zonos | Nekintama, moderni | Gimtadieniams, šventėms, terminų datoms |
ZonedDateTime | Datą, laiką ir konkrečią laiko zoną | Nekintama, moderni | Žmonėms rodomam laikui skirtingose zonose |
Instant | Tikslią UTC laiko juostos akimirką | Nekintama, moderni | Įvykių žymoms, žurnalams ir sistemų mainams |
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());0
1970-01-01T00:00:00Z
new Date(0)sukuria pačią Unix epochos pradžią.getTime()parodo nuo epochos praėjusias milisekundes – šiuo atveju nulį.toInstant()tą pačią akimirką pateikia moderniuInstanttipu.
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));2026
8
21
- Nustatome 2026 m. rugpjūčio 14 d.
add(..., 7)prideda septynias dienas ir gauna rugpjūčio 21 d.Calendar.MONTHskaičiuojamas nuo nulio, todėl spausdindami pridedame1.
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());2012-04-18
2012-04-25
2012
of(2012, 4, 18)sukuria aiškiai nurodytą datą.plusDays(7)nekeičia pradinio objekto – grąžina naują datą.- Tai yra nekintama (immutable) klasė, todėl jos objektus saugu bendrinti.
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")
));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());2026-08-14T07:30:00Z
2026-08-14T08:15:00Z
45
- Raidė
Zreiškia UTC. - Pridedame 45 minučių trukmę ir gauname naują
Instant. 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);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);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. DateirCalendarpalik 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/Vilniustipo identifikatorių. - Nekurk bendro
SimpleDateFormatkelioms gijoms. - Nepriklausyk nuo kompiuterio numatytosios laiko zonos, kai verslo taisyklė reikalauja konkrečios zonos.
- Nepainiok
java.util.Datesujava.sql.Date.

