Date & time API (java.time)
LocalDate, LocalDateTime, ZonedDateTime, Instant, Duration, Period and formatting/parsing.
Dates and times are deceptively hard: leap years, months of different lengths, time zones, daylight saving changes, and formatting for different countries. Java's old java.util.Date and Calendar classes were mutable, confusing (January was month 0!) and not thread-safe. Since Java 8, the java.time package provides a clean, immutable and precise API. Always use it in new code.
The main classes#
All of them are immutable and thread-safe. "Modifying" methods return new objects.
Creating dates and times#
Invalid values fail fast: LocalDate.of(2026, 2, 30) throws DateTimeException: Invalid date 'FEBRUARY 30'.
Date arithmetic#
Because dates are immutable, d.plusDays(10) on its own line does nothing useful. Assign the result: d = d.plusDays(10);.
Period and Duration#
Formatting and parsing#
DateTimeFormatter converts between dates and text. Patterns use letters like dd (day), MM (month number), MMM (short month name), yyyy (year), HH (24-hour), hh (12-hour), mm (minutes), a (AM/PM):
Beware
MM(month) vsmm(minutes), andyyyy(year) vsYYYY(week-based year, which gives wrong results around New Year). Formatters are immutable and thread-safe, so store them instatic finalconstants.
Time zones: ZonedDateTime and Instant#
LocalDateTime has no zone, so "2026-10-02 09:00" means different moments in Mumbai and London. When the actual moment matters (meetings across countries, flights, logs), use zones:
Best practice for applications:
- Store and transmit
Instants (UTC): in databases, APIs and logs. - Convert to
ZonedDateTimeat the edges, for display in the user's zone. - Use region IDs like
Asia/Kolkata, not fixed offsets like+05:30, so daylight-saving rules are handled. - Use
LocalDatefor things that are genuinely zone-independent, such as birthdays and holidays.
Measuring elapsed time#
For timing code, don't use wall-clock dates; use System.nanoTime() or Instant with Duration:
Testable code with Clock#
LocalDate.now() makes code hard to test, because the answer changes every day. Accept a Clock instead:
Converting legacy types#
You'll still meet java.util.Date in older libraries and java.sql.Timestamp in old JDBC code:
Modern JDBC drivers (and JPA) map LocalDate, LocalDateTime and Instant directly, so you rarely need these conversions.
Common mistakes#
- Using
Date/Calendar/SimpleDateFormatin new code (SimpleDateFormatis not thread-safe). - Ignoring the return value of
plusDaysand friends. - Using
LocalDateTimefor moments that span time zones; useInstantorZonedDateTime. - Mixing up
mm/MMandyyyy/YYYYin patterns. - Calling
now()all over business logic instead of injecting aClock.
What's next#
Next we put data on disk and read it back: file I/O with java.nio.
Check your understanding
Quick quiz
1.Which class represents a date without a time or time zone, such as a birthday?
2.What does
LocalDate.of(2026, 1, 31).plusMonths(1)return?3.What is the difference between
PeriodandDuration?
Finished reading?
Mark this lesson complete to track your progress.