Java LocalDateTime
Table of Contents + β
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 addimport 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
Tseparator, then time. - The month is a real month number, so
6means June. No counting from zero like the oldCalendarclass.
Output
2026-06-13T09:15:42.3182026-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 separateLocalTime.
Output
2026-06-13T14:302026-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 likeJUNE. Want the number6? CallgetMonthValue().getDayOfWeek()returns a word likeSATURDAY.- The rest return plain numbers.
Output
Year: 2026Month: JUNEDay: 13Hour: 14Minute: 30Second: 45Weekday: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 prints14:30on June 13, sostartnever moved.
Output
Original: 2026-06-13T14:30Later: 2026-06-16T16:30Earlier: 2026-06-13T13:45You 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)andequals(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-13Time 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:
ddis the two-digit day,MMMthe short month name,yyyythe four-digit year.hhis the 12-hour hour,mmminutes,aaddsAMorPM.- Use
HHinstead ofhhfor the 24-hour clock.
Output
13 Jun 2026, 02:30 PMParsing 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:30lines up withdd-MM-yyyy HH:mm, field for field. - Disagree by even one separator and Java throws a
DateTimeParseException.
Output
2026-06-13T14:30Need 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 touchingmeeting.EEEprints 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 PMFollow-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 unchangedt = 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
HHandhh.HHis 24-hour,hhis 12-hour. Usinghhwithouta(AM/PM) hides morning vs afternoon.
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("hh:mm"); // β 14:30 shows as 02:30DateTimeFormatter 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:
LocalDatefor a date alone,LocalTimefor a time alone,LocalDateTimefor both,ZonedDateTimewhen a zone matters. - Define formatters once and reuse them. A
DateTimeFormatteris immutable and safe to share, so donβt build it inside a loop. - Compare with
isBeforeandisAfterfor cleanbooleanchecks. - Machine format for storage, pretty format for people. Store the plain
2026-06-13T14:30style, 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, orLocalDateTime.of(year, month, day, hour, minute)for an exact one. - β
Combine a date and time with
date.atTime(time)ortime.atDate(date). - β
Read parts with
getYear(),getMonth(),getDayOfMonth(),getHour(), and friends. - β
It is immutable, so
plusDays,plusHours, andminusMinutesreturn a new value. Store it back. - β
Compare with
isBefore()andisAfter(). - β
Split it with
toLocalDate()andtoLocalTime(). - β
Format and parse with a
DateTimeFormatterpattern. - β
For time zones, reach for
ZonedDateTimeinstead.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does a LocalDateTime store?
Why: LocalDateTime carries both a date and a time, but it has no time zone.
- 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
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
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.