Java Date and Time API (java.time): LocalDate, ZonedDateTime, Period & Duration

โ˜• Java 21 LTS ๐ŸŸข Lesson 51 ๐Ÿ“‚ Phase 20: Date & Time (java.time) ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this in-depth guide: Old Date class limitations ยท LocalDate ยท LocalTime ยท LocalDateTime ยท ZonedDateTime ยท DateTimeFormatter (Formatting & Parsing) ยท Date Arithmetic (+/-) ยท isBefore / isAfter ยท Period vs Duration ยท Time Zones (ZoneId)

Welcome to Phase 20: Java Date and Time API (java.time) Masterclass! Prior to Java 8, handling dates and times in Java using legacy java.util.Date and java.util.Calendar was notoriously error-prone, mutable, and thread-unsafe. Java 8 introduced the modern JSR-310 java.time package, designed from the ground up to be immutable, thread-safe, domain-driven, and ISO-8601 compliant. In this comprehensive in-depth guide, you will master LocalDate, LocalTime, LocalDateTime, ZonedDateTime, DateTimeFormatter for formatting and parsing, date math, date comparisons, the crucial difference between Period and Duration, and global time zone conversions.

1Legacy Date Limitations (Why java.util.Date was Replaced)

โš ๏ธ The 4 Major Flaws of Legacy java.util.Date & Calendar:

1. Mutability (Thread-Unsafe): Date objects are mutable (e.g. date.setTime(...)). Two threads sharing a date object cause race conditions!
2. Confusing 0-Indexed Months: January is 0 and December is 11! (Passing 12 rolled over to January next year). Years started from 1900!
3. SimpleDateFormat is NOT Thread-Safe: Using a shared SimpleDateFormat in multi-threaded Spring Boot backends corrupted timestamps.
4. No Domain Separation: java.util.Date represented both Date and Time combined, even when only a date (e.g. Birthday) was needed.

Modern Class (java.time)Domain MeaningContains Timezone?Example Representation
LocalDateDate Only (Year, Month, Day)No2026-08-17 (Birthdays, Holidays)
LocalTimeTime Only (Hour, Min, Sec, Nano)No14:30:45.123 (Store opening hours)
LocalDateTimeDate + Time combinedNo2026-08-17T14:30:45 (Scheduled Meeting)
ZonedDateTimeDate + Time + ZoneIdYes2026-08-17T14:30:45+05:30[Asia/Kolkata]
InstantMachine Timestamp (Epoch Seconds)UTC2026-08-17T09:00:45Z (Database Audit Logs)
2LocalDate, LocalTime & LocalDateTime in Practice

Modern date-time classes provide clear factory constructors (now(), of()) and getter methods:

Java 21 โ€” Core java.time Creation & Inspection
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;

public class DateTimeBasicsDemo {
    public static void main(String[] args) {
        // 1. LocalDate (Date only)
        LocalDate today = LocalDate.now();
        LocalDate independenceDay = LocalDate.of(1947, Month.AUGUST, 15);
        System.out.println("Today's Date: " + today);
        System.out.println("Year: " + today.getYear() + " | Month: " + today.getMonth() + " | Day: " + today.getDayOfMonth());

        // 2. LocalTime (Time only)
        LocalTime currentTime = LocalTime.now();
        LocalTime meetingTime = LocalTime.of(10, 30, 0); // 10:30 AM
        System.out.println("Current Time: " + currentTime);

        // 3. LocalDateTime (Date + Time)
        LocalDateTime currentDateTime = LocalDateTime.now();
        LocalDateTime newYear2027 = LocalDateTime.of(2027, 1, 1, 0, 0, 0);
        System.out.println("New Year: " + newYear2027);
    }
}
3Formatting & Parsing Dates with DateTimeFormatter (Thread-Safe!)

DateTimeFormatter is completely immutable and thread-safe. It converts dates to custom formatted strings and parses input strings into date objects:

Java 21 โ€” Formatting & Parsing
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class FormattingAndParsingDemo {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();

        // 1. Formatting Date -> Custom String
        DateTimeFormatter customFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy hh:mm:ss a");
        String formattedOutput = now.format(customFormat);
        System.out.println("Formatted Indian Timestamp: " + formattedOutput);

        // 2. Parsing String -> LocalDate
        String userInputDate = "25/12/2026";
        DateTimeFormatter inputParser = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        LocalDate parsedChristmas = LocalDate.parse(userInputDate, inputParser);
        System.out.println("Parsed Date: " + parsedChristmas + " (Day of week: " + parsedChristmas.getDayOfWeek() + ")");
    }
}
4Date Arithmetic (plus/minus) & Date Comparisons

Because java.time objects are immutable, math operations return a new updated instance without modifying the original:

Java 21 โ€” Date Arithmetic & Comparisons
import java.time.LocalDate;

public class DateArithmeticDemo {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();

        // 1. Adding and Subtracting
        LocalDate nextWeek = today.plusDays(7);
        LocalDate threeMonthsAgo = today.minusMonths(3);
        LocalDate nextYear = today.plusYears(1);

        System.out.println("Today: " + today);
        System.out.println("1 Week Later: " + nextWeek);
        System.out.println("3 Months Ago: " + threeMonthsAgo);

        // 2. Comparing Dates (isBefore, isAfter, isEqual)
        LocalDate expiryDate = LocalDate.of(2026, 12, 31);
        if (today.isBefore(expiryDate)) {
            System.out.println("โœ… Product license is ACTIVE.");
        } else {
            System.out.println("โŒ Product license has EXPIRED.");
        }
    }
}
5Period vs Duration (Critical Difference โญ)

๐Ÿ’ก Period vs Duration โ€” Must-Know Interview Distinction

โ€ข Period (Date-Based): Measures difference in Years, Months, and Days (e.g. Age calculation between two LocalDate instances).
โ€ข Duration (Time-Based): Measures difference in Seconds, Milliseconds, and Nanoseconds (e.g. Measuring execution time benchmark between two LocalTime or Instant instances).

Java 21 โ€” Period & Duration in Action
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.Period;
import java.time.Duration;

public class PeriodDurationDemo {
    public static void main(String[] args) {
        // 1. Period: Age Calculator
        LocalDate birthDate = LocalDate.of(2000, 5, 15);
        LocalDate today = LocalDate.now();
        Period age = Period.between(birthDate, today);
        System.out.println("Exact Age: " + age.getYears() + " Years, " + 
                           age.getMonths() + " Months, and " + age.getDays() + " Days.");

        // 2. Duration: Benchmark Execution Time
        LocalTime startTime = LocalTime.of(10, 15, 30);
        LocalTime endTime = LocalTime.of(12, 45, 50);
        Duration taskDuration = Duration.between(startTime, endTime);
        System.out.println("Task Duration: " + taskDuration.toHours() + " hours and " + 
                           (taskDuration.toMinutes() % 60) + " minutes (" + taskDuration.toSeconds() + " total seconds).");
    }
}
6ZonedDateTime & Global Time Zone Conversions

International applications and flight ticketing systems require exact time zone awareness via ZoneId:

Java 21 โ€” Time Zone Conversion Engine
import java.time.ZonedDateTime;
import java.time.ZoneId;

public class TimeZoneDemo {
    public static void main(String[] args) {
        // Current Time in India (IST)
        ZoneId istZone = ZoneId.of("Asia/Kolkata");
        ZonedDateTime indiaTime = ZonedDateTime.now(istZone);
        System.out.println("India Time (IST): " + indiaTime);

        // Convert Same Instant to New York (EST) & Tokyo (JST)
        ZonedDateTime newYorkTime = indiaTime.withZoneSameInstant(ZoneId.of("America/New_York"));
        ZonedDateTime tokyoTime = indiaTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));

        System.out.println("New York Time (EST): " + newYorkTime);
        System.out.println("Tokyo Time (JST):    " + tokyoTime);
    }
}
๐Ÿ’ป Try It Yourself โ€” Test in Live Java 21 Compiler

Run this complete date and time formatter in our online Java compiler:

import java.time.LocalDate;
import java.time.Period;

public class Main {
    public static void main(String[] args) {
        LocalDate start = LocalDate.of(2024, 1, 1);
        LocalDate current = LocalDate.now();

        Period period = Period.between(start, current);
        System.out.println("Time elapsed since Jan 1, 2024: " + 
            period.getYears() + " years, " + period.getMonths() + " months, " + period.getDays() + " days.");
    }
}
Open in Online Java Compiler โ†’
OC
Written and reviewed by Our Compiler Technical Team ยท Updated for Java 21 LTS (2026 Edition)