On this page
java.time API
The java.time package (since Java 8, JSR-310) replaces the legacy java.util.Date and Calendar with an immutable, thread-safe, and intuitive date/time API.
Why java.time?
| Problem with old API | java.time Solution |
|---|---|
Mutable (Date.setTime()) |
Immutable objects |
| Not thread-safe | Thread-safe by design |
| Poor API design | Clear, fluent API |
| No timezone support in Date | Explicit timezone types |
Core Classes
| Class | Purpose | Example |
|---|---|---|
LocalDate |
Date without time | 2024-06-15 |
LocalTime |
Time without date | 14:30:00 |
LocalDateTime |
Date and time, no timezone | 2024-06-15T14:30 |
ZonedDateTime |
Date, time, and timezone | 2024-06-15T14:30+08:00[Asia/Shanghai] |
Instant |
UTC timestamp | 2024-06-15T06:30:00Z |
Duration |
Time-based amount | 2 hours, 30 minutes |
Period |
Date-based amount | 1 year, 3 months |
Creating Date/Time Objects
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1990, 5, 20);
LocalDate parsed = LocalDate.parse("2024-06-15");
LocalTime now = LocalTime.now();
LocalTime meeting = LocalTime.of(14, 30, 0);
LocalDateTime dateTime = LocalDateTime.now();
LocalDateTime event = LocalDateTime.of(2024, 6, 15, 14, 30);
Instant timestamp = Instant.now();
Instant epoch = Instant.ofEpochSecond(1_700_000_000);
Arithmetic
LocalDate nextWeek = today.plusDays(7);
LocalDate lastMonth = today.minusMonths(1);
LocalDate nextYear = today.plusYears(1);
LocalDateTime later = dateTime.plusHours(3).plusMinutes(30);
Duration twoHours = Duration.ofHours(2);
Duration between = Duration.between(startTime, endTime);
Period threeMonths = Period.ofMonths(3);
Period age = Period.between(birthday, today);
System.out.println(age.getYears() + " years old");
Comparison
LocalDate d1 = LocalDate.of(2024, 1, 1);
LocalDate d2 = LocalDate.of(2024, 6, 15);
System.out.println(d1.isBefore(d2)); // true
System.out.println(d1.isAfter(d2)); // false
System.out.println(d1.equals(d2)); // false
// Extract fields
System.out.println(d2.getYear()); // 2024
System.out.println(d2.getMonth()); // JUNE
System.out.println(d2.getDayOfWeek()); // SATURDAY
Timezones
ZoneId shanghai = ZoneId.of("Asia/Shanghai");
ZoneId utc = ZoneId.of("UTC");
ZonedDateTime zdt = ZonedDateTime.now(shanghai);
ZonedDateTime converted = zdt.withZoneSameInstant(ZoneId.of("America/New_York"));
// All ZoneIds
ZoneId.getAvailableZoneIds().forEach(System.out::println);
Instant — Machine Timestamp
Instant now = Instant.now();
Instant later = now.plusSeconds(3600);
long epochMilli = now.toEpochMilli();
Instant fromEpoch = Instant.ofEpochMilli(epochMilli);
Best for storing timestamps in databases and APIs (always UTC).
Converting Legacy Date
// Date → Instant → LocalDateTime
Date oldDate = new Date();
Instant instant = oldDate.toInstant();
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// LocalDateTime → Instant → Date
Instant inst = ldt.atZone(ZoneId.systemDefault()).toInstant();
Date converted = Date.from(inst);
Best Practices
- Use
LocalDate/LocalDateTimefor business logic without timezone - Use
ZonedDateTimewhen timezone matters (user-facing times) - Use
Instantfor storage and API timestamps (UTC) - Use
Durationfor time intervals,Periodfor calendar intervals - Never use
java.util.DateorCalendarin new code