1.4 Date and Time APIs (java.time)
Key Takeaways
- The java.time API classes (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Instant) are immutable and thread-safe, returning new temporal instances upon modification.
- Period represents date-based units (years, months, days) while Duration represents time-based units (hours, minutes, seconds, nanos); they cannot be used interchangeably.
- DateTimeFormatter formats and parses dates, times, and zones, throwing an UnsupportedTemporalTypeException when formatting fields missing from the target temporal object.
- Daylight Saving Time transitions adjust wall-clock times in ZonedDateTime calculations, where adding a Period preserves local time while adding a Duration computes exact elapsed hours.
Date and Time APIs (java.time)
Java's Date-Time API (java.time, JSR-310) provides a comprehensive, immutable, and thread-safe framework for date and time manipulation. The 1Z0-830 exam heavily tests temporal class distinctions, immutability pitfalls, Period vs. Duration arithmetic, DateTimeFormatter patterns, and Daylight Saving Time (DST) zone adjustments.
1. Core Temporal Types and Architecture
+-------------------------------------------------------------------------+
| java.time Framework |
| |
| +--------------------+ +--------------------+ |
| | LocalDate | | LocalTime | |
| | (2026-09-02) | | (14:30:45.123) | |
| +---------+----------+ +---------+----------+ |
| | | |
| +----------+------------+ |
| | |
| +---------v----------+ |
| | LocalDateTime | |
| | (2026-09-02T14:30) | |
| +---------+----------+ |
| | + ZoneId ("America/New_York") |
| +---------v----------+ +-------------------------+ |
| | ZonedDateTime | ------> | Instant | |
| | (Date+Time+ZoneId) | | (Epoch Timestamp in UTC)| |
| +--------------------+ +-------------------------+ |
+-------------------------------------------------------------------------+
Primary Temporal Classes
| Class | Represents | Sample Output | Typical Factory Methods |
|---|---|---|---|
LocalDate | Date without time or zone | 2026-09-02 | LocalDate.of(2026, 9, 2), LocalDate.parse("2026-09-02") |
LocalTime | Time without date or zone | 14:30:15.999 | LocalTime.of(14, 30), LocalTime.parse("14:30:15") |
LocalDateTime | Date and time without zone | 2026-09-02T14:30:15 | LocalDateTime.of(date, time), LocalDateTime.now() |
ZonedDateTime | Date and time with full timezone rules | 2026-09-02T14:30:15-04:00[America/New_York] | ZonedDateTime.of(dt, zoneId), ZonedDateTime.now() |
OffsetDateTime | Date and time with fixed UTC offset | 2026-09-02T14:30:15-04:00 | OffsetDateTime.of(dt, zoneOffset) |
Instant | Instantaneous point on time-line (UTC epoch) | 2026-09-02T18:30:15.999Z | Instant.now(), Instant.ofEpochMilli(ms) |
[!NOTE] Month values in
java.timeare 1-indexed (1 = January, 12 = December), or referenced via thejava.time.Monthenum (Month.SEPTEMBER). Attempting to construct an invalid date (e.g.,LocalDate.of(2026, 2, 29)) immediately throws a runtimejava.time.DateTimeException.
2. Immutability and Temporal Arithmetic
All core classes in java.time are immutable. Methods that alter dates or times (plusDays(), minusHours(), withYear()) return a new object without modifying the original instance.
LocalDate date = LocalDate.of(2026, 1, 15);
date.plusDays(10); // RETURN VALUE IGNORED!
System.out.println(date); // Prints 2026-01-15 (Unchanged!)
// Correct usage:
date = date.plusDays(10);
System.out.println(date); // Prints 2026-01-25
Fluent Adjustment Methods
plusYears(long),plusMonths(long),plusWeeks(long),plusDays(long)minusHours(long),minusMinutes(long),minusSeconds(long),minusNanos(long)withMonth(int),withDayOfMonth(int),withHour(int)(replaces specific field)
3. Period vs. Duration
Java strictly separates date-based amounts (Period) from time-based amounts (Duration):
| Feature | Period | Duration |
|---|---|---|
| Unit Focus | Years, Months, Days (Date-based) | Days, Hours, Minutes, Seconds, Nanos (Time-based) |
| Compatible Types | LocalDate, LocalDateTime, ZonedDateTime | LocalTime, LocalDateTime, ZonedDateTime, Instant |
| Incompatible Types | LocalTime, Instant (Throws UnsupportedTemporalTypeException) | LocalDate (Throws UnsupportedTemporalTypeException) |
| Factory Creation | Period.of(1, 2, 15), Period.ofDays(10) | Duration.ofHours(5), Duration.ofMinutes(30) |
| Between Method | Period.between(localDate1, localDate2) | Duration.between(temporal1, temporal2) |
// The Static Factory Chaining Trap
Period p = Period.ofYears(1).ofMonths(6).ofDays(3);
// WARNING: ofXXX() are STATIC methods. Chaining does not combine them!
// The variable 'p' contains only Period.ofDays(3)!
// Correct combination:
Period correctPeriod = Period.of(1, 6, 3);
// Type Mismatch Exceptions
LocalTime time = LocalTime.of(10, 0);
// time.plus(Period.ofDays(1)); // RUNTIME ERROR: UnsupportedTemporalTypeException!
LocalDate day = LocalDate.of(2026, 5, 1);
// Duration.between(day, day.plusDays(1)); // RUNTIME ERROR: UnsupportedTemporalTypeException!
4. DateTimeFormatter Parsing and Formatting
DateTimeFormatter in java.time.format provides thread-safe formatting and parsing.
Common Pattern Letters
y/yyyy: Year (e.g.,2026)M/MM: Month as number (9,09)MMM/MMMM: Month name (Sep,September)d/dd: Day of month (2,02)H/HH: Hour of day in 24-hour format (0-23)h/hh: Hour in 12-hour format (1-12) witha(am/pm)m/mm: Minute (00-59)s/ss: Second (00-59)z/zzzz: Time zone name (e.g.,EDT,Eastern Daylight Time)Z/XXXXX: Time zone offset (e.g.,-0400,-04:00)
LocalDate date = LocalDate.of(2026, 9, 2);
LocalTime time = LocalTime.of(14, 30, 0);
LocalDateTime dateTime = LocalDateTime.of(date, time);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm");
System.out.println(dateTime.format(formatter)); // "09/02/2026 14:30"
// Parsing
LocalDate parsedDate = LocalDate.parse("2026-09-02", DateTimeFormatter.ISO_LOCAL_DATE);
[!IMPORTANT] Missing Temporal Field Trap: If you attempt to format a temporal object using a pattern requiring fields the object does not have (e.g., formatting a
LocalDatewith pattern"yyyy-MM-dd HH:mm"), a runtimeUnsupportedTemporalTypeExceptionis thrown.
5. Daylight Saving Time (DST) Transitions
When calculating time across DST boundaries with ZonedDateTime, Java automatically adjusts the wall clock or UTC offset:
1. Spring Forward Transition (Skipped Hour)
In March (US Eastern Time), wall-clock time jumps from 01:59:59 directly to 03:00:00. The hour 02:00 to 02:59 does not exist.
- Creating
ZonedDateTime.of(LocalDate.of(2026, 3, 8), LocalTime.of(2, 30), ZoneId.of("America/New_York"))automatically adjusts forward to03:30:00-04:00.
2. Fall Back Transition (Repeated Hour)
In November (US Eastern Time), wall-clock time transitions from daylight time (-04:00) to standard time (-05:00), repeating the hour from 01:00 to 01:59.
3. Period vs. Duration on DST Transitions
- Adding a
Period(e.g.,Period.ofDays(1)): Adds one conceptual calendar day, preserving local wall-clock time regardless of whether the day has 23 or 25 actual hours. - Adding a
Duration(e.g.,Duration.ofDays(1)orDuration.ofHours(24)): Adds exactly 24 elapsed hours, which may shift the local wall-clock time by 1 hour across a DST transition.
ZoneId ny = ZoneId.of("America/New_York");
// Spring transition day: March 8, 2026 (23-hour day)
ZonedDateTime before = ZonedDateTime.of(LocalDate.of(2026, 3, 7), LocalTime.of(10, 0), ny);
ZonedDateTime addPeriod = before.plus(Period.ofDays(1));
System.out.println(addPeriod); // 2026-03-08T10:00-04:00[America/New_York] (Wall clock unchanged)
ZonedDateTime addDuration = before.plus(Duration.ofDays(1));
System.out.println(addDuration); // 2026-03-08T11:00-04:00[America/New_York] (Exact 24h shifts clock!)
What is the output of the following Java program? import java.time.*; public class DateCalc { public static void main(String[] args) { LocalDate date = LocalDate.of(2026, Month.MAY, 10); Period period = Period.ofYears(2).ofMonths(3).ofDays(5); date.plus(period); date = date.plusDays(2); System.out.println(date); } }
What happens when executing the following code snippet? LocalDate ld = LocalDate.of(2026, 9, 2); DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); String formatted = ld.format(dtf); System.out.println(formatted);
In the United States, Eastern Daylight Time (EDT) begins on Sunday, March 8, 2026, when local clocks skip from 02:00 to 03:00 (a 23-hour day). Consider this code: ZoneId zone = ZoneId.of("America/New_York"); ZonedDateTime start = ZonedDateTime.of(LocalDate.of(2026, 3, 7), LocalTime.of(9, 0), zone); ZonedDateTime pDay = start.plus(Period.ofDays(1)); ZonedDateTime dDay = start.plus(Duration.ofDays(1)); System.out.println(pDay.getHour() + " " + dDay.getHour());
Which of the following operations between temporal objects will execute successfully without throwing an exception?