JavaDate & Time API

Date & Time API

Since Java 8, working with dates and times means reaching for the java.time package. It was designed from scratch to replace the old java.util.Date and java.util.Calendar classes, which had earned a well-deserved reputation as one of the worst parts of the original Java API.

Why the old API had to go
`Date` and `Calendar` were mutable, so a date object could change underneath code that still held a reference to it. `Date` numbered months starting at 0 (January was `0`, December was `11`), a constant source of off-by-one bugs. Neither class was thread-safe, so sharing a `SimpleDateFormat` across threads could silently corrupt data. `java.time` fixes all three problems at once.
The Core Classes

java.time splits date and time concepts into focused, well-named classes instead of one do-everything Date class.

Class

Represents

LocalDate

A date with no time or time zone, e.g. 2026-07-08

LocalTime

A time with no date or time zone, e.g. 14:30:00

LocalDateTime

A date and time combined, still with no time zone

ZonedDateTime

A date and time attached to a specific time zone, e.g. Asia/Kolkata

Duration

An amount of time measured in seconds/nanoseconds — for time-based amounts

Period

An amount of time measured in years/months/days — for date-based amounts

Creating the core types

Java
import java.time.*;

public class DateTimeBasicsDemo {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        LocalDate birthday = LocalDate.of(1995, Month.JULY, 20);

        LocalTime now = LocalTime.now();
        LocalDateTime meeting = LocalDateTime.of(2026, 7, 8, 15, 30);

        ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));

        System.out.println("Today: " + today);
        System.out.println("Birthday: " + birthday);
        System.out.println("Meeting: " + meeting);
        System.out.println("Zoned: " + zoned);
    }
}
Everything in java.time Is Immutable

Just like String, every class in java.time is immutable. Methods such as .plusDays(), .minusMonths(), or .withYear() never modify the object they are called on — they always return a brand new instance representing the adjusted value, leaving the original untouched.

A broken example: ignoring the return value
This is one of the most common `java.time` mistakes, and it looks exactly like the old, mutable-`Date` habit of calling a method and moving on.

Bug: the return value is discarded

Java
import java.time.LocalDate;

public class BrokenDateDemo {
    public static void main(String[] args) {
        LocalDate deadline = LocalDate.of(2026, 7, 8);

        deadline.plusDays(7); // BUG: return value is thrown away!

        System.out.println(deadline); // still 2026-07-08 — unchanged
    }
}
2026-07-08

Fix: capture the returned instance

Java
import java.time.LocalDate;

public class FixedDateDemo {
    public static void main(String[] args) {
        LocalDate deadline = LocalDate.of(2026, 7, 8);

        deadline = deadline.plusDays(7); // reassign to the new instance

        System.out.println(deadline); // 2026-07-15
    }
}
2026-07-15
Formatting and Parsing

DateTimeFormatter converts between java.time objects and human readable text in both directions — formatting an object to a String, and parsing a String back into an object.

Formatting and parsing dates

Java
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateFormatDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2026, 7, 8);

        DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("dd-MM-yyyy");

        String formatted = date.format(formatter); // LocalDate -> String
        System.out.println(formatted);

        LocalDate parsed = LocalDate.parse("25-12-2026", formatter); // String -> LocalDate
        System.out.println(parsed);
    }
}
08-07-2026
2026-12-25
Measuring Amounts of Time

Use Period for date-based amounts (years, months, days) and Duration for time-based amounts (hours, minutes, seconds).

Period vs. Duration

Java
import java.time.*;

public class AmountsDemo {
    public static void main(String[] args) {
        LocalDate start = LocalDate.of(2026, 1, 1);
        LocalDate end = LocalDate.of(2026, 7, 8);
        Period gap = Period.between(start, end);
        System.out.println("Months apart: " + gap.getMonths());

        LocalTime open = LocalTime.of(9, 0);
        LocalTime close = LocalTime.of(17, 30);
        Duration shift = Duration.between(open, close);
        System.out.println("Shift hours: " + shift.toHours());
    }
}
Months apart: 6
Shift hours: 8
  • java.time (Java 8+) replaces the mutable, confusing Date/Calendar classes.

  • LocalDate, LocalTime, LocalDateTime and ZonedDateTime cover most everyday needs.

  • Every java.time type is immutable — always reassign the result of a .plusX()/.minusX() call.

  • DateTimeFormatter handles both formatting (object → text) and parsing (text → object).

  • Period measures date-based gaps; Duration measures time-based gaps.