[!NOTE] Historically, working with Dates in Java was notoriously awful. The original
java.util.Dateclass was confusing, mutable, and lacked basic timezone support.
In Java 8, Oracle completely overhauled the system and introduced the java.time package, standardizing how dates should be computed.
The Big Three Classes
- LocalDate
Represents a date (Year, Month, Day) with no time and no timezone. Perfect for birthdays or national holidays.
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println(today); // Output: 2024-05-14
// You can also create specific dates!
LocalDate releaseDate = LocalDate.of(1995, 5, 23);
}
}
- LocalTime
Represents a time (Hour, Minute, Second, Nanosecond) with no date. Perfect for "Opening Store Hours".
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
LocalTime rightNow = LocalTime.now();
System.out.println(rightNow); // Output: 14:35:10.827364
}
}
- LocalDateTime
A combination of both. Still essentially "floating" in space, completely untethered to a timezone. This is effectively "The time that is physically reading on your wristwatch".
import java.time.LocalDateTime;
LocalDateTime current = LocalDateTime.now();
Formatting Dates for Users
By default, Java prints dates in ISO-8601 format (YYYY-MM-DD). However, end users generally prefer localized strings, like 14-May-2024.
We accomplish this using the DateTimeFormatter.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
LocalDateTime myDateObj = LocalDateTime.now();
// The 'E' is the Day of week.
// The 'MMM' is the 3-letter month.
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("E, MMM dd yyyy HH:mm:ss");
String formattedDate = myDateObj.format(myFormatObj);
System.out.println("Formatted: " + formattedDate); // E.g., Tue, May 14 2024 14:30:00
}
}
[!TIP] If you are building a global web application, NEVER store
LocalDateTimein your database! Always convert the user's action into UTC usingZonedDateTimeorInstant, save it to the database as UTC, and only ever convert it back to the local time when rendering the frontend UI in the browser.
Pick the Date-Time Type by Meaning
The right date-time class depends on what the value represents. A birthday is not a moment on the global timeline. A payment timestamp is. This distinction is the key to avoiding timezone bugs.
Type Choice Guide
| Use case | Type | Why |
|---|---|---|
| Birthday, exam date | LocalDate | Date only |
| Store opening time | LocalTime | Time only |
| Appointment without timezone | LocalDateTime | Date plus time |
| Audit timestamp | Instant | Exact point in UTC |
| User-facing timezone-aware event | ZonedDateTime | Includes zone rules |
Parsing and Formatting
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
LocalDate examDate = LocalDate.parse("15-06-2026", formatter);
String display = examDate.format(formatter);
Common Mistakes
- Storing future scheduled events without considering the user's timezone.
- Using old mutable
DateAPIs in new code without a strong reason. - Formatting dates for storage instead of storing structured date-time values.
- Confusing duration, period, date, and timestamp.
Mini Practice
Create a program that stores an exam date as LocalDate, calculates how many days are left, and prints it in dd MMM yyyy format.
Practice Lab: Exam Countdown
Use java.time for a real date calculation.
- Create a
LocalDatefor an upcoming exam. - Get today's date with
LocalDate.now(). - Calculate days remaining using
ChronoUnit.DAYS.between. - Format the exam date as
dd MMM yyyy. - Print a message like
Exam on 15 Jun 2026, 17 days left.
Goal: Choose date-only types for date-only problems and format them for users.
Revision Checkpoint
LocalDate: Date without time.LocalTime: Time without date.LocalDateTime: Date and time without timezone.Instant: Exact point on UTC timeline.DateTimeFormatter: Parses and formats date-time text.
Before the quiz: Pick the correct type for birthday, audit timestamp, and store opening time.