Dates & Times (LocalDate, LocalDateTime)

Dates look simple and turn out to be a minefield — leap years, month lengths, time zones. Java's modern java.time package handles all of it with clean, immutable classes. This lesson covers the three you'll use daily: LocalDate , LocalTime , and LocalDateTime .

Learn Dates & Times (LocalDate, LocalDateTime) in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and…

Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

You'll need comfort with method calls and imports — everything here lives in java.time . Knowing that objects can be immutable will make the key idea click instantly.

💡 Analogy: A LocalDate is like a single page torn from a calendar — it says "17 June 2026" and nothing else. You can't erase and rewrite it; if you want "one week later" you grab a fresh page. That's immutability: every plusDays hands you a new page and leaves the original exactly as it was. This is what makes java.time safe to pass around without anyone secretly changing your dates.

There are three everyday building blocks: LocalDate (date only), LocalTime (time only), and LocalDateTime (both). "Local" means no time zone — perfect for birthdays, opening hours, and appointments where the zone is understood. We'll stick to these three.

Use the static of(...) factory methods to build a specific value, or now() for the current moment. Months are 1-based here (June is 6) — a welcome fix from the old Date class where January was 0. You can also use the readable Month.JUNE enum.

Once you have an object, getters pull out the pieces: getYear() , getMonth() , getDayOfMonth() , getDayOfWeek() , and more.

Every java.time object is immutable . A method like plusDays(10) does not change the date — it returns a brand-new date and leaves the original untouched. This is wonderful for safety but trips up everyone at least once.

Compare two dates with isBefore , isAfter , and isEqual . To measure the gap, you have two tools:

DateTimeFormatter converts in both directions: format turns a date object into a custom String, and parse turns a String back into a date object. You define the shape with a pattern of letters.

These lines compute and print how many days remain until a holiday. They've been shuffled.

Create both dates first, measure the gap with ChronoUnit.DAYS.between (earlier date first so the result is positive), then print.

Predict the output before opening each answer.

Answer: 2026-06-17 — unchanged. plusDays(5) returns a new date that is thrown away because the result isn't captured. LocalDate is immutable. To move the date you'd need d = d.plusDays(5); .

Answer: 2026-02-28 . There's no 31 February, so plusMonths clamps to the last valid day of the target month. (2026 isn't a leap year, so February ends on the 28th.) java.time handles month-length edge cases for you.

Answer: 16 . between counts whole days from start to end — June 17 minus June 1 is 16 days. It's exclusive of the start and inclusive of the end's calendar position, so the gap, not the number of dates, is 16.

🎯 Your Turn #1 — 18th birthday

Given a birth date, compute and print the 18th-birthday date.

🎯 Your Turn #2 — Countdown

Count the days between today and a deadline using ChronoUnit .

🧩 Mini-Challenge — Age calculator

Write an age method that returns whole years between a birth date and today using Period .

You can now build dates and times with java.time , you understand why every object is immutable (and the bug that causes), and you can add, compare, measure, format, and parse with confidence. You're using the same modern API every professional Java codebase relies on.

Next up: Comparable & Comparator — teaching Java how to sort your own objects.

Practice quiz

In LocalDate.of(2026, 6, 17), how is the month value interpreted?

  • 0-based, so 6 is July
  • It is the day, not the month
  • 1-based, so 6 is June
  • It must be a Month enum

Answer: 1-based, so 6 is June. java.time months are 1-based: 6 means June. This fixes the old Date class where January was 0.

After LocalDate d = LocalDate.of(2026,6,17); d.plusDays(5); what does d hold?

  • 2026-06-17
  • 2026-06-22
  • It throws an exception
  • null

Answer: 2026-06-17. java.time objects are immutable; plusDays returns a NEW date that is discarded here, so d is unchanged. Verified on Java 21.

What does LocalDate.of(2026, 1, 31).plusMonths(1) produce?

  • 2026-02-31
  • 2026-03-03
  • It throws DateTimeException
  • 2026-02-28

Answer: 2026-02-28. There is no 31 February, so plusMonths clamps to the last valid day; 2026 is not a leap year, giving 2026-02-28. Verified on Java 21.

Which class should you use for a date with no time, like a birthday?

  • LocalDateTime
  • LocalDate
  • LocalTime
  • Instant

Answer: LocalDate. LocalDate holds a date with no time-of-day, perfect for birthdays and deadlines.

What does ChronoUnit.DAYS.between(LocalDate.of(2026,6,1), LocalDate.of(2026,6,17)) return?

  • 16
  • 17
  • 15
  • 1

Answer: 16. between counts whole days from start to end: June 17 minus June 1 is 16. Verified on Java 21.

Which pair measures a human breakdown of years/months/days versus a total count in one unit?

  • Duration vs Period
  • Instant vs LocalDate
  • Period vs ChronoUnit.DAYS.between
  • ChronoUnit vs LocalTime

Answer: Period vs ChronoUnit.DAYS.between. Period.between gives a years/months/days breakdown; ChronoUnit.DAYS.between gives a single total count of days.

In a DateTimeFormatter pattern, what is the difference between MM and mm?

  • MM is minutes, mm is month
  • MM is month, mm is minutes
  • Both mean month
  • Both mean minutes

Answer: MM is month, mm is minutes. Pattern letters are case-sensitive: uppercase MM is the month, lowercase mm is minutes — a classic source of bugs.

Why prefer java.time over the old Date and Calendar classes?

  • java.time is mutable and faster
  • Date and Calendar are immutable and thread-safe
  • Date supports time zones and java.time does not
  • java.time classes are immutable, thread-safe, and use 1-based months

Answer: java.time classes are immutable, thread-safe, and use 1-based months. The modern java.time API is immutable, thread-safe, clearly named, and uses natural 1-based months, unlike the error-prone legacy classes.

What is the correct way to actually move a date forward by one day?

  • date.plusDays(1);
  • date = date.plusDays(1);
  • date.addDays(1);
  • date.setDay(date.getDay()+1);

Answer: date = date.plusDays(1);. Because dates are immutable you must capture the returned value: date = date.plusDays(1).

Period measures date-based units; what does Duration measure?

  • Years, months, and days
  • Only whole days
  • Hours, minutes, seconds, and nanos
  • Time zones

Answer: Hours, minutes, seconds, and nanos. Duration measures time-based units (hours/minutes/seconds/nanos) and pairs with LocalTime/Instant, while Period covers years/months/days.