Java Data i czas
⚡ Inteligentne podsumowanie
Java Obsługa daty i godziny łączy starsze klasy java.util.Date i SimpleDateFormat z nowoczesnym interfejsem API java.time wprowadzonym w Java 8, zapewniając deweloperom niezmienne, bezpieczne wątkowo typy do dokładnej pracy z kalendarzem.
Obsługa dat i godzin w Java to rutynowy element tworzenia logiki harmonogramowania, rejestrowania znaczników czasu, raportów i ścieżek audytu. Przed napisaniem jakiegokolwiek kodu warto poznać parametry składające się na datę:
- rok (dwu- lub czterocyfrowy).
- miesiąc (jako dwie cyfry, jako pierwsze trzy litery miesiąca lub jako pełna nazwa miesiąca).
- dane (faktyczny numer dnia miesiąca).
- dzień (nazwa dnia w danej dacie, np. niedz., pon., wt.).
Java Ujawnia wiele innych parametrów opisujących moment na osi czasu, w tym erę, tydzień w roku, strefę czasową i przesunięcie. Poniższe sekcje omawiają każdy z nich wraz z przykładami do uruchomienia.
Wyświetl datę w Java
Java zapewnia Date klasa w java.util Pakiet. Klasa przechowuje konkretny moment z dokładnością do milisekundy i oferuje metody pomocnicze do drukowania, porównywania i formatowania tego momentu. Aby uzyskać aktualną datę i godzinę, utwórz instancję klasy za pomocą jej domyślnego konstruktora:
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()); } }
Wyjście:
Wed Nov 29 06:36:22 UTC 2017
Przykład drukuje datę w domyślnym formacie toString. Aby wyświetlić ten sam moment w innym wzorcu, najpierw musisz zrozumieć litery formatujące, które… Java używa.
SimpleDateFormat: analizuj i formatuj daty
SimpleDateFormat klasa w java.text konwertuje Date obiekt do sformatowanego ciągu i analizuje sformatowany ciąg z powrotem do DateUżywa liter wzorcowych, które odpowiadają składowej daty lub godziny. Poniższa tabela zawiera listę wszystkich obsługiwanych liter:
| List | Składnik daty lub godziny | Przykład |
|---|---|---|
| G | Oznaczenie epoki | AD |
| y | Rok | 2026 |
| M | Miesiąc w roku | Lipiec lub lipiec lub 07 |
| w | Tydzień w roku | 27 |
| W | Tydzień w miesiącu | 2 |
| D | Dzień w roku | 189 |
| d | Dzień w miesiącu | 10 |
| F | Dzień tygodnia w miesiącu | 2 |
| E | Nazwa dnia w tygodniu | wtorek lub wtorek |
| u | Numer dnia tygodnia (1 = Monday, 7 = niedziela) | 1 |
| a | Znak AM lub PM | PM |
| H | Godzina w dniu (0-23) | 0 |
| k | Godzina w dniu (1-24) | 24 |
| K | Godzina w AM lub PM (0-11) | 0 |
| h | Godzina w AM lub PM (1-12) | 12 |
| m | Minuta w godzinie | 30 |
| s | Drugi w ciągu minuty | 55 |
| S | Milisekunda | 978 |
| z | Strefa czasowa (nazwa) | Czas pacyficzny; PST; GMT-08:00 |
| Z | Strefa czasowa (przesunięcie RFC 822) | -0800 |
| X | Strefa czasowa (przesunięcie ISO 8601) | -08 lub -0800 lub -08:00 |
Nie musisz pamiętać całej tabeli. Sięgaj do niej za każdym razem, gdy tworzysz nowy wzór.
Jak korzystać z SimpleDateFormat
SimpleDateFormat jest podklasą DateFormat Umożliwia formatowanie i analizowanie dat za pomocą liter wzorca powyżej. Połącz litery, aby opisać dokładnie ciąg znaków, który chcesz wygenerować lub odczytać.
Na przykład:
- Wymagany format daty: 2012.10.23, 20:20:45 czasu PST. Odpowiedni wzór formatu to
yyyy.MM.dd HH:mm:ss zzz. - Wymagany format daty: 09:30:00 AM 23-May-2012. Odpowiedni wzór formatu to
hh:mm:ss a dd-MMM-yyyy.
Wskazówka: Uważaj na wielkość liter. Wielkie litery M miesiąc, mała litera m jest minuta. Wielka litera H jest zegarem 24-godzinnym, małymi literami h to zegar 12-godzinny. Pomieszanie ich daje po cichu błędne wyniki.
Poniższy program drukuje bieżącą datę dwukrotnie – raz w formacie domyślnym i raz za pomocą wzorca 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)); } }
Wyjście:
Wed Nov 29 06:31:41 UTC 2017 06:31:41 AM 29-Nov-2017
Przykład porównania dat
Najbardziej niezawodny sposób na zamówienie dwóch Date obiekty to jest compareTo() Metoda. Zwraca ujemną liczbę całkowitą, gdy obiekt wywołujący jest wcześniejszy, zero, gdy obie instancje są równe, oraz dodatnią liczbę całkowitą, gdy obiekt wywołujący jest późniejszy. Poniższy fragment kodu analizuje dwa ciągi dat i wyświetla ich względną kolejność:
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"); } } }
Wyjście:
Date1 : 20-08-1981 Date2 : 12-10-2012 Date 1 occurs before Date 2
Uwaga: Oryginalny kod używał wzorca dd-mm-yyyy. Małe litery mm Litera oznacza minutę, a nie miesiąc, więc parser po cichu wygenerował błędną wartość miesiąca. Powyższa poprawka używa wielkich liter. MM dla miesiąca, co jest poprawnym wzorem literowym.
Java 8 Nowoczesne API daty i czasu (java.time)
Java 8 wprowadził java.time package, przeprojektowane API inspirowane biblioteką Joda-Time. Nowe klasy są niezmienne, bezpieczne dla wątków i oddzielają kalendarz ludzki od osi czasu maszyny. Najpopularniejsze typy to:
LocalDatena datę bez określonej godziny ani strefy czasowej (na przykład urodziny).LocalTimedla czasu na zegarze ściennym bez daty i strefy czasowej.LocalDateTimedla daty i godziny bez strefy czasowej.ZonedDateTimedla daty i godziny w określonej strefie czasowej.OffsetDateTimedla daty i godziny z przesunięciem UTC, ale bez nazwanej strefy.Instantdla znacznika czasu maszyny mierzonego od epoki UNIX.DurationorazPerioddla kwot opartych na czasie i dacie.
Poniższy przykład drukuje bieżącą datę, godzinę, znacznik czasu i strefę czasową za pomocą nowoczesnego interfejsu 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żdy typ ma metody fabryczne (now, of, parse) i operacje niezmienne (plusDays, minusHours, withYear) zwracające nową wartość zamiast mutować oryginalny obiekt.
DateTimeFormatter: Formatowanie dat w nowoczesnym formacie Java
DateTimeFormatter in java.time.format Zastępuje SimpleDateFormat. Używa tego samego stylu liter wzorcowych, jest niezmienna i można ją bezpiecznie udostępniać między wątkami bez dodatkowej synchronizacji. Klasa udostępnia również gotowe stałe, takie jak ISO_LOCAL_DATE oraz ISO_ZONED_DATE_TIME dla formatów standardowych.
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); } }
Aby porównać dwie daty w nowoczesnym API, wywołaj isBefore, isAfterlub isEqual. Te metody są bardziej przejrzyste niż compareTo i pracować z każdym java.time class.
Bezpieczeństwo wątków i najlepsze praktyki Java Data i czas
Obie java.util.Date oraz SimpleDateFormat poprzedzają współczesną współczesność Java, a każda z nich ma swoje pułapki. Postępuj zgodnie z poniższymi praktykami, aby zapewnić poprawną obsługę dat w kodzie produkcyjnym:
- Preferuj java.time zamiast Date i Calendar. Nowe typy są niezmienne i bezpieczne pod kątem wątków, a także dokładniej modelują domenę (daty bez czasu, czasy bez stref itd.).
- Nie udostępniaj SimpleDateFormat pomiędzy wątkami. Klasa przechowuje wewnętrzny stan analizy i nie jest bezpieczna dla wątków. Zawiń ją w
ThreadLocal, zsynchronizuj na instancji lub przełącz się naDateTimeFormatter. - Zawsze określaj ustawienia regionalne. Nazwy miesięcy i dni zmieniają się wraz z domyślną lokalizacją JVM, co powoduje, że wzorce takie jak
MMMorazEEEnieprzenośny. Przekaż ustawienia regionalne jawnie (na przykład,Locale.ENGLISH). - Podaj dokładne informacje o strefach czasowych.
LocalDateTimenie ma strefy, więc przekształć naZonedDateTimeorInstantzawsze, gdy liczy się konkretny moment, zwłaszcza w przypadku dzienników, kolumn bazy danych i obciążeń sieciowych. - Należy zachować ostrożność podczas konwersji pomiędzy obydwoma interfejsami API. Zastosowanie
date.toInstant(),Date.from(instant),calendar.toInstant().atZone(zone)na granicy między kodem starym i nowoczesnym. - Przechowuj znaczniki czasu w formacie UTC. Wytrwaj i transmit daty w formacie UTC (
Instantlub ciąg ISO 8601) i konwertować do strefy użytkownika tylko podczas wyświetlania.



