Java LocalDateTime

In the last lesson you learned about Java LocalTime. A LocalTime holds only a time and a LocalDate holds only a date, but real life often needs both at once. For that, Java gives you LocalDateTime: one object that carries a date and a time together.

πŸ€” What is a LocalDateTime?

A LocalDateTime is a date and a time joined into one value. Think of a paper invitation: β€œParty on June 13, 2026 at 2:30 PM.” It tells you the day and the hour, but not which country’s clock.

  • Stores a date part (year, month, day) and a time part (hour, minute, second, nanoseconds).
  • Has no time zone, so it does not pin an exact instant on Earth.
  • Is immutable, so once made it never changes.
  • Lives in java.time, so add import java.time.LocalDateTime;.

πŸ› οΈ Creating a LocalDateTime

The two you will use most are now() for the current moment and of(...) for a specific one.

import java.time.LocalDateTime;
LocalDateTime rightNow = LocalDateTime.now();
LocalDateTime meeting = LocalDateTime.of(2026, 6, 13, 14, 30);
System.out.println(rightNow);
System.out.println(meeting);

Each line, in short:

  • now() asks the computer for the current date and time, so the value depends on when you run it.
  • of(2026, 6, 13, 14, 30) builds an exact moment. Order: year, month, day, hour, minute.
  • Printing shows date, then a T separator, then time.
  • The month is a real month number, so 6 means June. No counting from zero like the old Calendar class.

Output

2026-06-13T09:15:42.318
2026-06-13T14:30

🧩 Combining a LocalDate and a LocalTime

Already have a date in one variable and a time in another? You can combine them directly.

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
LocalDate date = LocalDate.of(2026, 6, 13);
LocalTime time = LocalTime.of(14, 30);
LocalDateTime combined1 = date.atTime(time);
LocalDateTime combined2 = time.atDate(date);
System.out.println(combined1);
System.out.println(combined2);

Both lines give the same result, just from different starting points:

  • date.atTime(time) reads as β€œtake this date, at this time”.
  • time.atDate(date) reads as β€œtake this time, on this date”.
  • Shortcut: date.atTime(14, 30) passes hour and minute straight in, no separate LocalTime.

Output

2026-06-13T14:30
2026-06-13T14:30

πŸ” Reading the parts

Each part has a simple getter method. The code below reads several pieces from one value.

import java.time.LocalDateTime;
LocalDateTime dt = LocalDateTime.of(2026, 6, 13, 14, 30, 45);
System.out.println("Year: " + dt.getYear());
System.out.println("Month: " + dt.getMonth());
System.out.println("Day: " + dt.getDayOfMonth());
System.out.println("Hour: " + dt.getHour());
System.out.println("Minute: " + dt.getMinute());
System.out.println("Second: " + dt.getSecond());
System.out.println("Weekday:" + dt.getDayOfWeek());

Each getter hands back one field:

  • getMonth() returns a word like JUNE. Want the number 6? Call getMonthValue().
  • getDayOfWeek() returns a word like SATURDAY.
  • The rest return plain numbers.

Output

Year: 2026
Month: JUNE
Day: 13
Hour: 14
Minute: 30
Second: 45
Weekday:SATURDAY

βž• It is immutable: add and subtract make a NEW object

A LocalDateTime is immutable, so plusDays and minusMinutes do not edit your value. They build a new value and hand it back, leaving the original untouched. The code below adds and subtracts, then prints both.

import java.time.LocalDateTime;
LocalDateTime start = LocalDateTime.of(2026, 6, 13, 14, 30);
LocalDateTime later = start.plusDays(3).plusHours(2);
LocalDateTime earlier = start.minusMinutes(45);
System.out.println("Original: " + start);
System.out.println("Later: " + later);
System.out.println("Earlier: " + earlier);

Look at the original in the output:

  • start.plusDays(3).plusHours(2) chains left to right: 3 days later, then add 2 hours to that.
  • start.minusMinutes(45) makes another new value, 45 minutes before the start.
  • Original: still prints 14:30 on June 13, so start never moved.

Output

Original: 2026-06-13T14:30
Later: 2026-06-16T16:30
Earlier: 2026-06-13T13:45

You must store the result

Writing start.plusDays(3); on its own does nothing, because the new value is thrown away. Always assign it back: start = start.plusDays(3); or save it into a new variable.

The same family covers every field: plusYears, plusMonths, plusWeeks, plusDays, plusHours, plusMinutes, plusSeconds, and a matching minus... for each.

βš–οΈ Comparing two LocalDateTime values

To check which moment comes first, use isBefore and isAfter. Both return a boolean, so they fit right into an if. The code below decides if an event is in the past.

import java.time.LocalDateTime;
LocalDateTime event = LocalDateTime.of(2026, 6, 13, 14, 30);
LocalDateTime now = LocalDateTime.now();
if (event.isAfter(now)) {
System.out.println("The event is still in the future.");
} else if (event.isBefore(now)) {
System.out.println("The event has already passed.");
} else {
System.out.println("The event is happening right now.");
}

It reads like plain English:

  • event.isAfter(now) is true if the event comes after now, so it is in the future.
  • event.isBefore(now) is true if it comes before now, so it has passed.
  • isEqual(other) and equals(other) check for an exact match.

Output

The event has already passed.

πŸ”„ Converting to and from LocalDate and LocalTime

A LocalDateTime is a date plus a time, so you can split it back with toLocalDate() and toLocalTime(). The code below pulls each half out.

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
LocalDateTime dt = LocalDateTime.of(2026, 6, 13, 14, 30);
LocalDate justDate = dt.toLocalDate();
LocalTime justTime = dt.toLocalTime();
System.out.println("Date only: " + justDate);
System.out.println("Time only: " + justTime);

Each method gives you a smaller, focused object:

  • toLocalDate() keeps the calendar part, drops the clock part.
  • toLocalTime() keeps the clock part, drops the calendar part.
  • To go back, combine them: justDate.atTime(justTime).

Output

Date only: 2026-06-13
Time only: 14:30

🎨 Formatting and parsing with DateTimeFormatter

The default 2026-06-13T14:30 is fine for logs, not for people. To control the look, use a DateTimeFormatter: give it a pattern, and it turns the value into a readable String. The code below formats one value.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDateTime dt = LocalDateTime.of(2026, 6, 13, 14, 30);
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd MMM yyyy, hh:mm a");
String pretty = dt.format(formatter);
System.out.println(pretty);

The pattern letters are the whole trick:

  • dd is the two-digit day, MMM the short month name, yyyy the four-digit year.
  • hh is the 12-hour hour, mm minutes, a adds AM or PM.
  • Use HH instead of hh for the 24-hour clock.

Output

13 Jun 2026, 02:30 PM

Parsing is the reverse trip: start with a String and turn it back into a LocalDateTime. The pattern must match the text exactly.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm");
LocalDateTime parsed =
LocalDateTime.parse("13-06-2026 14:30", formatter);
System.out.println(parsed);

Here parse reads the text with the pattern and rebuilds the value:

  • The text 13-06-2026 14:30 lines up with dd-MM-yyyy HH:mm, field for field.
  • Disagree by even one separator and Java throws a DateTimeParseException.

Output

2026-06-13T14:30

Need a time zone? Reach for ZonedDateTime

A LocalDateTime has no time zone, so it cannot represent an exact instant across the world. For zones, like scheduling across countries, use java.time.ZonedDateTime, which adds a zone such as America/New_York.

πŸ› οΈ Worked example: scheduling a follow-up

A meeting starts at a set time, and you want a follow-up exactly 3 days and 2 hours later, in a friendly format. The code below schedules it and prints both moments.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDateTime meeting = LocalDateTime.of(2026, 6, 13, 14, 30);
LocalDateTime followUp = meeting.plusDays(3).plusHours(2);
DateTimeFormatter fmt =
DateTimeFormatter.ofPattern("EEE, dd MMM yyyy 'at' hh:mm a");
System.out.println("Meeting: " + meeting.format(fmt));
System.out.println("Follow-up: " + followUp.format(fmt));

Walking through it:

  • meeting.plusDays(3).plusHours(2) builds the follow-up without touching meeting.
  • EEE prints the short weekday.
  • 'at' is printed as-is. Anything in single quotes inside a pattern is a literal.

Output

Meeting: Sat, 13 Jun 2026 at 02:30 PM
Follow-up: Tue, 16 Jun 2026 at 04:30 PM

⚠️ Common Mistakes

A few LocalDateTime slip-ups to watch for:

  • Treating it as mutable. Plus and minus return a new value. Store it, or nothing happens.
LocalDateTime t = LocalDateTime.of(2026, 6, 13, 14, 30);
t.plusDays(3); // ❌ result thrown away, t unchanged
t = t.plusDays(3); // βœ… store the new value back
  • Forgetting it has no time zone. It is just a wall-clock reading. For zones, use ZonedDateTime.
LocalDateTime flight = LocalDateTime.of(2026, 6, 13, 14, 30); // ❌ which zone?
// βœ… use ZonedDateTime when the zone actually matters
  • Mixing up HH and hh. HH is 24-hour, hh is 12-hour. Using hh without a (AM/PM) hides morning vs afternoon.
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("hh:mm"); // ❌ 14:30 shows as 02:30
DateTimeFormatter right = DateTimeFormatter.ofPattern("HH:mm"); // βœ… shows 14:30
  • A pattern that does not match the text. Mismatched parsing throws a DateTimeParseException. Line them up field for field.

βœ… Best Practices

Habits for working with LocalDateTime:

  • Always capture the result: t = t.plusDays(3);.
  • Pick the right type: LocalDate for a date alone, LocalTime for a time alone, LocalDateTime for both, ZonedDateTime when a zone matters.
  • Define formatters once and reuse them. A DateTimeFormatter is immutable and safe to share, so don’t build it inside a loop.
  • Compare with isBefore and isAfter for clean boolean checks.
  • Machine format for storage, pretty format for people. Store the plain 2026-06-13T14:30 style, apply a display pattern only when showing it.

🧩 What You’ve Learned

Let’s recap LocalDateTime.

  • βœ… A LocalDateTime holds a date and a time together, with no time zone.
  • βœ… Create one with LocalDateTime.now() for the current moment, or LocalDateTime.of(year, month, day, hour, minute) for an exact one.
  • βœ… Combine a date and time with date.atTime(time) or time.atDate(date).
  • βœ… Read parts with getYear(), getMonth(), getDayOfMonth(), getHour(), and friends.
  • βœ… It is immutable, so plusDays, plusHours, and minusMinutes return a new value. Store it back.
  • βœ… Compare with isBefore() and isAfter().
  • βœ… Split it with toLocalDate() and toLocalTime().
  • βœ… Format and parse with a DateTimeFormatter pattern.
  • βœ… For time zones, reach for ZonedDateTime instead.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does a LocalDateTime store?

    Why: LocalDateTime carries both a date and a time, but it has no time zone.

  2. 2

    What does start.plusDays(3) do to the original start value?

    Why: LocalDateTime is immutable, so plus and minus return a new value; the original is untouched.

  3. 3

    How do you combine a LocalDate named date with a LocalTime named time?

    Why: date.atTime(time) joins them; time.atDate(date) does the same the other way.

  4. 4

    Which type should you use when a time zone matters?

    Why: LocalDateTime has no zone; ZonedDateTime adds one like America/New_York.

πŸš€ What’s Next?

You have now covered the core java.time types. Next up is one of the biggest building blocks in Java: methods. Methods let you name a piece of work once and run it whenever you need it, so your code stays short and clear.

Introduction to Methods in Java

Share & Connect