skip to content

LocalDate / LocalTime / LocalDateTime

LocalDate, LocalTime and LocalDateTime carry no zone or offset, which makes them right for a birthday or a shop's opening hour and wrong for a timestamp. Interviewers check that you can pick the correct type for a given field.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What are LocalDate, LocalTime, and LocalDateTime, and when would you use each?

level: juniorimportance: must knowfreq 80%

answer

  1. Date only / time only / both
  2. All three are zone-less
  3. LocalDateTime is NOT an instant
  4. Smallest type that fits
  5. Immutable + thread-safe

basics

~10 s

LocalDate is a date only (year-month-day), LocalTime is a time only (hour-minute-second), and LocalDateTime is both together. None of them carries a time zone. Use whichever matches the data you have.

solid answer

~40 s

These are the three zone-less core types in java.time. LocalDate models a calendar date with no time and no zone (a birthday, a due date). LocalTime models a wall-clock time with no date and no zone (a shop opening at 09:00). LocalDateTime combines both but still has no zone or offset, so it cannot be turned into an exact instant on the global timeline without extra zone information. Choose the smallest type that fits: LocalDate when time is irrelevant, LocalTime when the date is irrelevant, LocalDateTime when you need both but the location/zone genuinely does not matter or is supplied elsewhere. For an exact point on the global timeline (logs, timestamps, cross-region scheduling) you reach for ZonedDateTime, OffsetDateTime, or Instant instead. All three Local types are immutable and thread-safe.

code

java · 7 lines
java
LocalDate d = LocalDate.of(2026, 2, 14);   // 2026-02-14
LocalTime t = LocalTime.of(9, 30);          // 09:30
LocalDateTime dt = d.atTime(t);             // 2026-02-14T09:30, no zone

// Recover the parts:
LocalDate back = dt.toLocalDate();
LocalTime time = dt.toLocalTime();

go deeper

for a junior

Can name all three, state that each is date-only / time-only / both, and pick the right one for a birthday vs. an opening time.

for a middle

Explains that all three are zone-less and immutable, and knows LocalDateTime is not an instant and needs a zone to become one.

for a senior

Articulates the design rationale (single-purpose immutable types), the trade-off vs. ZonedDateTime/OffsetDateTime/Instant, and storage/timeline implications of choosing a Local type.

for a principal

Can set team conventions for which type crosses API/persistence boundaries (e.g. store Instant/OffsetDateTime, use Local types only for true wall-clock semantics), and reason about migration from legacy Date/Calendar.

## The problem these types solve Java's original date/time classes (`java.util.Date`, `Calendar`) were mutable, error-prone, and merged several distinct ideas into one type. Java 8 introduced the `java.time` package (the JSR-310 API) with small, single-purpose, **immutable** types. Three of them are *zone-less* (also called *local*): they describe a date or time the way a wall clock or a paper calendar does, without saying *where* on Earth the reading was taken. ## Terms defined - **Immutable**: once created, the object never changes; every "modifying" method returns a new object. This makes the types automatically thread-safe. - **Time zone**: a region's full set of civil-time rules, e.g. `Europe/Berlin`, including daylight-saving transitions. Represented by `ZoneId`. - **Offset**: a fixed difference from UTC, e.g. `+02:00`. Represented by `ZoneOffset`. - **Instant**: an exact point on the global timeline, independent of any zone (think "the same moment everywhere"). ## The three types **`LocalDate`** holds year, month, and day-of-month only. Example: `2026-02-14`. There is no hour, no zone. Use it for things that are conceptually a date: a birthday, an invoice due date, a holiday. **`LocalTime`** holds hour, minute, second, and nanosecond only. Example: `09:30:00`. There is no date, no zone. Use it for a daily wall-clock time: when a store opens, an alarm time. **`LocalDateTime`** holds both a date and a time, e.g. `2026-02-14T09:30`. Crucially it still has **no zone and no offset**. So `2026-02-14T09:30` is ambiguous as a global instant — 09:30 in Tokyo and 09:30 in New York are different moments. You cannot convert a `LocalDateTime` to an `Instant` without supplying a zone. ## When NOT to use them If you need a precise moment that is comparable across regions — a server log timestamp, an event scheduled for users worldwide, an audit record — a Local type is the wrong choice because it loses the zone. Use `Instant` (machine timestamp), `OffsetDateTime` (date-time + fixed offset, good for storage), or `ZonedDateTime` (date-time + full zone rules, good for region-aware scheduling). ## Rule of thumb Pick the **smallest** type that captures exactly the information you have, and add zone information only when the data genuinely involves a location on the timeline. ## A small example ```java LocalDate d = LocalDate.of(2026, 2, 14); // 2026-02-14 LocalTime t = LocalTime.of(9, 30); // 09:30 LocalDateTime dt = d.atTime(t); // 2026-02-14T09:30 (still no zone) ``` From `LocalDateTime` you can recover the parts with `dt.toLocalDate()` and `dt.toLocalTime()`.

  • Why can't you convert a LocalDateTime directly to an Instant?
    Because it has no zone or offset. The same wall-clock reading maps to different global instants depending on the zone, so you must supply a ZoneId (e.g. dt.atZone(zone).toInstant()) to resolve the ambiguity.
  • Which type would you store a user's date of birth in?
    LocalDate — a birthday is a calendar date with no time-of-day or zone meaning.

A paper calendar (LocalDate), a wall clock (LocalTime), and a calendar page with a clock drawn on it (LocalDateTime) — none of them tells you which country you're standing in.

saying these in an interview costs you the question

  • Thinking LocalDateTime represents a precise moment in time / an instant
  • Using LocalDateTime for log or audit timestamps that must compare across regions
  • Assuming these types carry the JVM default time zone (they carry none)
  • Treating them as mutable and calling a method expecting it to change the object in place

context

open as a page

How do you create, access, and combine LocalDate/LocalTime/LocalDateTime, given that they are immutable?

level: middleimportance: must knowfreq 65%

basics

~20 s

Create them with factory methods like LocalDate.of(...), LocalTime.now(), or by parsing a string. Read parts with getters such as getYear() or getHour(). They never change in place — methods like plusDays or atTime return a brand-new object you must assign.

open as a page

How are months and days-of-week numbered in java.time, and why does it matter?

level: juniorimportance: should knowfreq 55%

basics

~20 s

In java.time months are 1-based: January is 1 and December is 12. Days of week are also 1-based with MONDAY = 1 and SUNDAY = 7. This is different from the old Calendar class, where January was 0.

open as a page

What happens when you add a year to February 29 (a leap day), and how does java.time handle leap years generally?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Feb 29 only exists in leap years. If you add one year to Feb 29 and the target year isn't a leap year, java.time adjusts the result to Feb 28 instead of failing. It never produces an invalid date like Feb 30.

open as a page

What are the risks of using LocalDateTime for persistence and APIs, and what would you use instead?

level: principalimportance: should knowfreq 50%

basics

~20 s

LocalDateTime has no time zone, so a stored value like 2026-02-14T09:30 is ambiguous — you can't tell which real moment it was. For timestamps that cross zones, store an Instant or OffsetDateTime instead, and keep LocalDateTime only for true wall-clock data.

open as a page