Chapter 23: Date & Time API (Java 8+)
Before Java 8, working with dates and times was painful:
- java.util.Date was mutable, confusing, and full of bugs
- java.util.Calendar was complex and error-prone
- Mixing them was a nightmare
In 2014, Java 8 gave us the new Date & Time API (java.time package) — modern, immutable, thread-safe, clear, and beautiful.
Today (January 23, 2026), this API is the standard — every serious Java developer uses it daily.
We’ll go super slowly, step by step, with lots of real-life analogies, complete runnable programs, detailed explanations, tables, common mistakes, and plenty of examples you can copy-paste and run right now.
Let’s dive in!
1. The Main Classes You Will Use Every Day
| Class | What it represents | Time Zone? | Use Case Example |
|---|---|---|---|
| LocalDate | Date only (year-month-day) | No | Birthday, event date, expiry date |
| LocalTime | Time only (hour-minute-second-nano) | No | Meeting time, opening hours |
| LocalDateTime | Date + Time (no zone) | No | Appointment, log timestamp (local time) |
| ZonedDateTime | Date + Time + Time Zone | Yes | Flight booking, international meeting |
| Instant | Point on timeline (UTC) | No | Machine timestamp, precise duration |
| Period | Date-based amount of time (years, months, days) | — | Age calculation, subscription duration |
| Duration | Time-based amount (hours, minutes, seconds) | — | Video length, processing time |
Important: All these classes are:
- Immutable (like String — safe to share)
- Thread-safe (perfect for multi-threaded apps)
- Human-readable (easy to understand)
2. Creating & Using LocalDate, LocalTime, LocalDateTime
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import java.time.*; import java.time.format.DateTimeFormatter; public class LocalDateTimeDemo { public static void main(String[] args) { // 1. Current date, time, datetime LocalDate today = LocalDate.now(); LocalTime now = LocalTime.now(); LocalDateTime current = LocalDateTime.now(); System.out.println("Today: " + today); // 2026-01-23 System.out.println("Now: " + now); // 19:45:12.345678901 System.out.println("Current: " + current); // 2026-01-23T19:45:12.345678901 // 2. Create specific date/time LocalDate birthday = LocalDate.of(1998, 8, 15); // 15 August 1998 LocalTime meetingTime = LocalTime.of(14, 30); // 2:30 PM LocalDateTime appointment = LocalDateTime.of(2026, 2, 10, 11, 0); System.out.println("My birthday: " + birthday); System.out.println("Meeting at: " + meetingTime); // 3. Parse from String (very common!) LocalDate parsedDate = LocalDate.parse("2026-01-23"); LocalDateTime parsedDateTime = LocalDateTime.parse("2026-01-23T19:45:00"); // 4. Formatting (custom patterns) DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMMM yyyy, EEEE"); System.out.println("Formatted birthday: " + birthday.format(formatter)); // Output: 15 August 1998, Saturday // 5. Extract parts System.out.println("Day of week: " + today.getDayOfWeek()); // FRIDAY System.out.println("Month: " + today.getMonth()); // JANUARY System.out.println("Year: " + today.getYear()); // 2026 } } |
3. ZonedDateTime – When Time Zones Matter
ZonedDateTime = LocalDateTime + ZoneId (time zone)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.time.*; public class ZonedDateTimeDemo { public static void main(String[] args) { // Current time in Mumbai ZonedDateTime mumbaiNow = ZonedDateTime.now(ZoneId.of("Asia/Kolkata")); System.out.println("Mumbai now: " + mumbaiNow); // Meeting in New York ZonedDateTime nyMeeting = ZonedDateTime.of( 2026, 2, 10, 11, 0, 0, 0, ZoneId.of("America/New_York") ); System.out.println("NY Meeting: " + nyMeeting); // Convert Mumbai time to London time ZonedDateTime londonTime = mumbaiNow.withZoneSameInstant(ZoneId.of("Europe/London")); System.out.println("Same instant in London: " + londonTime); // All available time zones System.out.println("Available zones: " + ZoneId.getAvailableZoneIds().size()); // ~600 } } |
Important Note: Use ZoneId (modern) instead of old TimeZone. Common IDs: Asia/Kolkata, America/New_York, Europe/London, UTC
4. Period & Duration – Measuring Time Differences
Period → date-based (years, months, days) Duration → time-based (hours, minutes, seconds, nanos)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import java.time.*; public class PeriodDurationDemo { public static void main(String[] args) { LocalDate birthday = LocalDate.of(1998, 8, 15); LocalDate today = LocalDate.now(); // Period: how many years, months, days old Period age = Period.between(birthday, today); System.out.println("Age: " + age.getYears() + " years, " + age.getMonths() + " months, " + age.getDays() + " days"); // Duration: time difference between two LocalDateTime LocalDateTime start = LocalDateTime.of(2026, 1, 23, 10, 0); LocalDateTime end = LocalDateTime.of(2026, 1, 23, 14, 45); Duration meetingDuration = Duration.between(start, end); System.out.println("Meeting duration: " + meetingDuration.toHours() + " hours " + meetingDuration.toMinutesPart() + " minutes"); // Add / subtract Period LocalDate afterOneYear = today.plus(Period.ofYears(1)); System.out.println("One year later: " + afterOneYear); // Add / subtract Duration LocalDateTime afterTwoHours = start.plus(Duration.ofHours(2)); System.out.println("After 2 hours: " + afterTwoHours); } } |
5. Common Formatting Patterns (Cheat Sheet)
| Pattern | Example Output (2026-01-23 19:45:12) | Meaning |
|---|---|---|
| dd-MM-yyyy | 23-01-2026 | Day-Month-Year |
| dd MMMM yyyy | 23 January 2026 | Full month name |
| dd MMM yyyy | 23 Jan 2026 | Short month |
| EEEE | Friday | Full day of week |
| HH:mm:ss | 19:45:12 | 24-hour time |
| hh:mm a | 07:45 PM | 12-hour with AM/PM |
| yyyy-MM-dd’T’HH:mm:ss | 2026-01-23T19:45:12 | ISO standard (common in JSON/APIs) |
6. Quick Recap Table (Your Cheat Sheet)
| Class | Represents | Time Zone? | Best For |
|---|---|---|---|
| LocalDate | Year-Month-Day | No | Birthdays, expiry dates |
| LocalTime | Hour-Minute-Second | No | Meeting times, opening hours |
| LocalDateTime | Date + Time | No | Local logs, appointments |
| ZonedDateTime | Date + Time + Zone | Yes | International events, flights |
| Period | Years-Months-Days | — | Age, subscription length |
| Duration | Hours-Minutes-Seconds-Nanos | — | Processing time, video length |
7. Common Mistakes & Fixes
| Mistake | Problem | Fix |
|---|---|---|
| Using old Date / Calendar | Bugs, mutable, confusing | Switch to java.time classes |
| Parsing wrong format | DateTimeParseException | Use correct DateTimeFormatter |
| Forgetting time zone in international apps | Wrong time shown | Use ZonedDateTime or ZoneId |
| Doing LocalDateTime.now() for global apps | Uses system default zone | Use ZonedDateTime.now(ZoneId.of(“UTC”)) |
| Not handling DateTimeException | Crashes on invalid input | Wrap in try-catch |
8. Homework for You (Very Practical!)
- Basic Create a program that prints today’s date in 5 different formats (dd-MM-yyyy, MMMM dd yyyy, etc.)
- Medium Calculate your age in years, months, days using Period.between()
- Advanced Take two flight times (e.g., Mumbai departure 2026-02-10 10:00 IST, arrival New York 2026-02-10 20:00 EST) → calculate actual flight duration using Duration
- Fun Make a program that generates a countdown timer to your next birthday
- Challenge Parse a string like “2026-01-23T19:45:00+05:30” into ZonedDateTime and convert it to UTC
You’re doing fantastic! The new Date & Time API is one of the most satisfying parts of modern Java — once you start using it, you’ll never go back to the old classes.
