Skip to content
Date and Time API
step 1/6

Reading — step 1 of 6

Learn

~2 min readFiles and I/O

Java's modern java.time API (Java 8+) replaces the broken Date and Calendar classes. Use it for everything date/time-related in new code — never reach for the old ones.

The core types

import java.time.*;

LocalDate date = LocalDate.now();              // 2026-05-08 (no time, no zone)
LocalTime time = LocalTime.now();              // 14:30:42.123 (no date, no zone)
LocalDateTime dt = LocalDateTime.now();        // 2026-05-08T14:30:42.123 (no zone)
ZonedDateTime zdt = ZonedDateTime.now();       // 2026-05-08T14:30:42.123-05:00[America/New_York]
Instant now = Instant.now();                    // 2026-05-08T19:30:42.123Z (a moment in UTC)
Duration d = Duration.ofMinutes(15);            // amount of time
Period p = Period.ofMonths(3);                  // amount of dates

Pick the right type:

  • LocalDate — a date (no time): 2026-05-08
  • LocalTime — a time of day: 14:30:42
  • LocalDateTime — both, but no zone — for local clocks
  • ZonedDateTime — both with zone (handles DST)
  • Instant — a moment on the timeline (always UTC) — for timestamps, ordering events
  • Duration — measured in seconds/nanos — for LocalTime differences
  • Period — measured in years/months/days — for LocalDate differences

Construction

LocalDate d = LocalDate.of(2026, 5, 8);
LocalTime t = LocalTime.of(14, 30, 0);
LocalDateTime dt = LocalDateTime.of(d, t);

LocalDate parsed = LocalDate.parse("2026-05-08");
LocalDate fromCustom = LocalDate.parse("08/05/2026",
    DateTimeFormatter.ofPattern("dd/MM/yyyy"));

Arithmetic — all time types are immutable

LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
LocalDate inAYear = today.plusYears(1).minusMonths(2);
LocalDate end = today.with(TemporalAdjusters.lastDayOfMonth());

Duration between = Duration.between(
    LocalTime.of(9, 0),
    LocalTime.of(17, 30)
);                                              // PT8H30M
long minutes = between.toMinutes();             // 510

Methods like plusDays, withYear, minusMonths return NEW objects — the original is untouched.

Formatting and parsing

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy");
LocalDate.now().format(fmt);                    // "Friday, May 8, 2026"

LocalDate.parse("2026-05-08");                   // ISO format — default

Time zones — when they matter

// User says "meet at 3pm New York time":
ZonedDateTime meeting = ZonedDateTime.of(
    LocalDateTime.of(2026, 5, 8, 15, 0),
    ZoneId.of("America/New_York")
);

// Convert to user's zone:
ZonedDateTime inLondon = meeting.withZoneSameInstant(ZoneId.of("Europe/London"));
// 8pm London time — same moment, different display

Comparing

LocalDate a = LocalDate.of(2026, 5, 8);
LocalDate b = LocalDate.of(2026, 6, 1);
a.isBefore(b);          // true
a.isAfter(b);           // false
a.equals(b);            // false
ChronoUnit.DAYS.between(a, b);  // 24 days

Common mistakes

  • Using java.util.Date in new code — outdated, mutable, confusing. Use java.time.
  • Mixing Instant and LocalDateTime — they represent different things. Instant is a UTC moment; LocalDateTime is wall-clock without zone.
  • Forgetting zones for global apps — store UTC (Instant) in DB, convert to user's local zone for display.
  • Trying to mutate — all java.time types are immutable. .plusDays(1) returns a new instance.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…