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.time are 1-indexed (1 = January, 12 = December), or referenced via the java.time.Month enum (Month.SEPTEMBER). Attempting to construct an invalid date (e.g., LocalDate.of(2026, 2, 29)) immediately throws a runtime java.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 LocalDate with pattern "yyyy-MM-dd HH:mm"), a runtime UnsupportedTemporalTypeException is 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); } }
2028-08-17
2026-05-17
2026-05-12
2028-08-12
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);
Outputs '2026-09-02 00:00'
Outputs '2026-09-02'
Throws DateTimeParseException at runtime
Throws UnsupportedTemporalTypeException at runtime
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());
9 10
9 9
10 9
10 10
Which of the following operations between temporal objects will execute successfully without throwing an exception?
Period.between(LocalTime.of(9, 0), LocalTime.of(17, 0))
Duration.between(Instant.now(), Instant.now().plus(Duration.ofMinutes(5)))
Duration.between(LocalDate.now(), LocalDate.now().plusDays(1))
Instant.now().plus(Period.ofDays(1))
Sections you finish are checked off in the contents.