Java Dates and Times

Work with dates and times using java.time: LocalDate, LocalTime and LocalDateTime, formatting and parsing, adding periods, measuring gaps and time zones.

Lesson 77 of 127Intermediate17 min read

Dates are everywhere in real applications: when an order was placed, when a subscription renews, how many days are left until an event, which shift starts at 9:00 in London but 10:00 in Paris. They're also surprisingly hard to get right, with months of different lengths, leap years, daylight saving changes and different date formats around the world.

Java's java.time package, added in Java 8, handles all of this with clear, reliable classes. Every object is immutable, so adding a day gives you a new date rather than changing the old one, and the names say exactly what each class holds: a date, a time, or both, with or without a time zone.

In this lesson you'll create dates and times, format them for people and parse them from text, add and subtract periods, measure the gap between two dates, and see how time zones and instants fit in. If you've used the older Date or Calendar classes, this is their much friendlier replacement.

The main classes

ClassHoldsExample
LocalDateA date2024-07-05
LocalTimeA time of day14:30
LocalDateTimeDate and time, no zone2024-07-05T14:30
ZonedDateTimeDate, time and time zone2024-07-05T14:30+01:00[Europe/London]
InstantAn exact moment, in UTC2024-07-05T13:30:00Z

Create them with now() for the current value or of() for a specific one: LocalDate.of(2024, 7, 5). Months are numbered 1 to 12, so July really is 7. Printing a value gives the international ISO format.

Formatting and parsing

A DateTimeFormatter turns dates into text, and text back into dates, using a pattern:

PatternMeaningExample
dd / dDay, two digits / as needed05 / 5
MM / MMM / MMMMMonth number / short / full name07 / Jul / July
yyyyYear2024
EEE / EEEEWeekday short / fullFri / Friday
HH:mm24-hour time14:30
h:mm a12-hour time2:30 PM
Java
var fmt = DateTimeFormatter.ofPattern("d MMMM yyyy");
String text = date.format(fmt);                     // "5 July 2024"
LocalDate back = LocalDate.parse("5 July 2024", fmt);

Names like July come from your computer's language setting; pass Locale.UK to ofPattern to fix the language. Invalid text throws DateTimeParseException.

Adding time and measuring gaps

Because dates are immutable, methods like plusDays return a new date:

Java
LocalDate due = borrowed.plusWeeks(3);
LocalDate lastMonth = today.minusMonths(1);

To measure a gap:

  • ChronoUnit.DAYS.between(a, b) gives the total number of days (or weeks, months, hours with other units).
  • Period.between(a, b) gives years, months and days separately, which is ideal for ages.
  • Duration.between(t1, t2) measures time-based gaps in hours, minutes and seconds.

Compare dates with isBefore(), isAfter() and isEqual(). Adding a month to 31 January gives 29 February in a leap year: Java picks the last valid day.

Time zones and instants

A LocalDateTime has no zone, so "9:00" could mean any 9:00 on Earth. For events that involve real moments in different places, attach a zone with atZone(ZoneId.of("Europe/London")) to get a ZonedDateTime, and convert with withZoneSameInstant(ZoneId.of("Asia/Tokyo")).

An Instant is a single point on the timeline in UTC, the best choice for timestamps such as "when was this record created?". Store instants, and convert to a zone only when showing a time to a person. Java's zone data includes daylight saving rules, so conversions stay correct all year round.

Java Dates Syntax

java.time essentials

LocalDate d = LocalDate.of(2024, 7, 5);
LocalDate today = LocalDate.now();
var fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
d.format(fmt);  LocalDate.parse("05/07/2024", fmt);
d.plusDays(10);  d.minusMonths(1);  d.getDayOfWeek();
ChronoUnit.DAYS.between(a, b);  Period.between(a, b);
Duration.between(t1, t2).toMinutes();
d.isBefore(other);
ZonedDateTime z = dt.atZone(ZoneId.of("Europe/London"));

Java Dates Summary

  • LocalDate, LocalTime and LocalDateTime hold dates and times without a zone; create them with now() or of().
  • DateTimeFormatter.ofPattern formats dates for display and parses text into dates.
  • plusDays, minusMonths and friends return new objects; dates are immutable.
  • ChronoUnit.DAYS.between counts days; Period gives years, months and days; Duration measures hours and minutes.
  • Use ZonedDateTime for zones and Instant for exact moments; avoid the old Date class.

Java Dates Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A library due date

Java
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        var fmt = DateTimeFormatter.ofPattern("EEEE d MMMM yyyy", Locale.UK);
        LocalDate borrowed = LocalDate.of(2024, 7, 5);
        LocalDate due = borrowed.plusWeeks(3);
        System.out.println("Borrowed: " + borrowed.format(fmt));
        System.out.println("Due:      " + due.format(fmt));

        LocalDate returned = LocalDate.of(2024, 7, 30);
        long late = ChronoUnit.DAYS.between(due, returned);
        if (returned.isAfter(due)) {
            System.out.printf("%d days late, fine £%.2f%n", late, late * 0.25);
        }
    }
}
Output
Borrowed: Friday 5 July 2024
Due:      Friday 26 July 2024
4 days late, fine £1.00
Line-by-line explanation
  1. Line 8The pattern spells out the weekday and month, in UK English.
  2. Line 10plusWeeks returns a new date; borrowed is unchanged.
  3. Line 15Count the days between the due date and the return date.
  4. Line 16isAfter compares two dates.
Example 2

Ages and countdowns

Java
import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class Main {
    public static void main(String[] args) {
        LocalDate today = LocalDate.of(2024, 7, 5);
        LocalDate born = LocalDate.of(2008, Month.SEPTEMBER, 14);

        Period age = Period.between(born, today);
        System.out.println("Age: " + age.getYears() + " years, "
                + age.getMonths() + " months, " + age.getDays() + " days");

        LocalDate newYear = LocalDate.of(2025, 1, 1);
        System.out.println("Days until New Year: " + ChronoUnit.DAYS.between(today, newYear));
        System.out.println("New Year falls on a " + newYear.getDayOfWeek());
        System.out.println("Leap year? " + today.isLeapYear());
    }
}
Output
Age: 15 years, 9 months, 21 days
Days until New Year: 180
New Year falls on a WEDNESDAY
Leap year? true
Line-by-line explanation
  1. Line 8A fixed "today" keeps the example's output the same every time; use LocalDate.now() in real code.
  2. Line 9Month.SEPTEMBER is an enum, clearer than the number 9.
  3. Line 11Period splits the gap into years, months and days, exactly how ages are described.
  4. Line 17getDayOfWeek returns a DayOfWeek enum value.
Example 3

Shift times across time zones

Java
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        LocalTime start = LocalTime.of(8, 45);
        LocalTime end = LocalTime.of(17, 15);
        Duration shift = Duration.between(start, end);
        System.out.println("Shift: " + shift.toHours() + " h " + shift.toMinutesPart() + " min");

        var fmt = DateTimeFormatter.ofPattern("HH:mm");
        ZonedDateTime call = LocalDateTime.of(2024, 7, 5, 9, 0)
                .atZone(ZoneId.of("Europe/London"));
        for (String zone : new String[]{"Europe/Paris", "America/New_York", "Asia/Tokyo"}) {
            ZonedDateTime there = call.withZoneSameInstant(ZoneId.of(zone));
            System.out.println(zone + ": " + there.format(fmt));
        }
    }
}
Output
Shift: 8 h 30 min
Europe/Paris: 10:00
America/New_York: 04:00
Asia/Tokyo: 17:00
Line-by-line explanation
  1. Line 12Duration measures the time between two times of day.
  2. Line 13toMinutesPart gives the minutes left over after the whole hours.
  3. Lines 16 to 17A 9:00 call in London, in July, during British Summer Time.
  4. Line 19The same instant, shown in another city's local time.

Common Java Dates Mistakes

Ignoring the returned date

Don't
LocalDate d = LocalDate.of(2024, 7, 5);
d.plusDays(7);                 // result thrown away
System.out.println(d);         // still 2024-07-05
Do
d = d.plusDays(7);

mm instead of MM

Don't
DateTimeFormatter.ofPattern("dd/mm/yyyy");   // mm means minutes
Do
DateTimeFormatter.ofPattern("dd/MM/yyyy");   // MM means month

Using Period for a total number of days

Don't
int days = Period.between(a, b).getDays();   // only the "days" part, e.g. 21
Do
long days = ChronoUnit.DAYS.between(a, b);   // the full count, e.g. 295

Java Dates in Real Projects

java.time in practice

Booking systems calculate nights with ChronoUnit.DAYS.between, payroll software measures shifts with Duration, and global apps store every timestamp as an Instant and show it in each user's zone. Databases, JSON libraries and frameworks like Spring map LocalDate and Instant directly to and from their own date types, so java.time values flow through a whole application unchanged.

Java Dates FAQ

How do I get the current date in Java?

LocalDate.now() gives today's date in the computer's default time zone, and LocalDateTime.now() adds the time. Pass a zone when it matters, as in LocalDate.now(ZoneId.of("Asia/Tokyo")), because the date differs around the world at the same moment.

How do I convert a String to a LocalDate?

Text in ISO format, such as "2026-10-11", parses directly with LocalDate.parse(text). For other layouts, build a formatter, DateTimeFormatter.ofPattern("dd/MM/yyyy"), and call LocalDate.parse(text, formatter). Catch DateTimeParseException for text typed by users.

How do I calculate someone's age in Java?

Use Period.between(birthDate, LocalDate.now()).getYears(). Period counts complete years, months and days on the calendar, so a person's age changes exactly on their birthday, including for people born on 29 February.

Which date type should I store in a database?

Store real moments, such as when an order was placed, as an Instant or as a timestamp with a time zone. Store calendar dates without a time, such as birthdays, as a LocalDate. Use LocalDateTime only for local wall-clock times that aren't tied to a place, such as "shops open at 09:00".

How does java.time handle daylight saving time?

ZonedDateTime applies the zone's rules automatically. A local time that doesn't exist because clocks jumped forward is moved past the gap: 01:30 on 29 March 2026 in London becomes 02:30 British Summer Time. Adding Duration.ofHours(24) and Period.ofDays(1) can also give different results across a clock change.

Java Dates Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the code so it creates the date 25 December 2024.

LocalDate xmas = LocalDate.(2024, 12, 25);
Multiple choiceeasy

Which class holds a date with no time?

Predict the outputmedium

What does this print?

LocalDate d = LocalDate.of(2024, 1, 31).plusMonths(1);
System.out.println(d);
Multiple choicemedium

Which gives the total number of days between two dates?

Multiple choicehard

What should you store for "when was this order created?" in a system used worldwide?

Java Dates Quiz

5 questions to check what you learned.

  1. In LocalDate.of(2024, 3, 1), which month is it?

    • February
    • March
    • April
    • January
  2. What does MMMM show in a date pattern?

    • Minutes
    • The month number
    • Milliseconds
    • The full month name, such as July
  3. Why does d.plusDays(1) not change d?

    • It's a bug
    • plusDays needs a semicolon
    • java.time objects are immutable, so the method returns a new date
    • It only works on LocalDateTime
  4. Which exception does parsing badly formatted text throw?

    • DateTimeParseException
    • NumberFormatException
    • IOException
    • NullPointerException
  5. What does withZoneSameInstant do?

    • Changes the clock time but keeps the zone
    • Removes the time zone
    • Shows the same moment in a different time zone
    • Rounds to the nearest hour