By WebNest Studio Engineering Team
Java - Core Tutorial
Date and Time API
Java 8 introduced the java.time package to replace the old, error-prone java.util.Date and java.util.Calendar classes. The new API is modeled closely on the well-regarded Joda-Time library and fixes long-standing problems: the old classes were mutable, not thread-safe, used confusing zero-based months, and mixed date, time, and timezone concerns into a small number of overloaded classes.
Why it matters
Dates appear in almost every application: due dates, bookings, subscriptions, reports. The old Date and Calendar classes were mutable and easy to misuse, and they still appear in legacy code. The java.time API is what you should write today, and its immutability and clear class names remove most date bugs.
Core Classes
java.time splits date and time concerns into focused, purpose-built classes:
LocalDate— a date without time or timezone, such as 2026-09-21.LocalTime— a time without date or timezone, such as 14:30:00.LocalDateTime— a combined date and time, still without timezone.Period— a date-based amount of time (years, months, days), used for differences between LocalDate values.Duration— a time-based amount (hours, minutes, seconds, nanoseconds), used for differences between time-based values.DateTimeFormatter— formats and parses date/time objects using a pattern, replacing the old and not-thread-safe SimpleDateFormat.
Immutability
Every class in java.time is immutable: methods like plusDays() or minusMonths() return a brand-new object with the adjusted value rather than modifying the original in place. This makes the classes inherently thread-safe and eliminates a whole category of bugs where a shared Date object was silently mutated by one part of a program and unexpectedly affected another.
Example
LocalDate, Period, and DateTimeFormatter working together
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class DateTimeDemo {
public static void main(String[] args) {
LocalDate today = LocalDate.of(2026, 9, 21);
LocalDate nextMonth = today.plusMonths(1); // returns a new LocalDate, today is unchanged
System.out.println("Today: " + today);
System.out.println("Next month: " + nextMonth);
LocalDate birthday = LocalDate.of(2000, 5, 15);
Period age = Period.between(birthday, today);
System.out.println("Age: " + age.getYears() + " years, " + age.getMonths() + " months");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
System.out.println(today.format(formatter));
}
}
Today: 2026-09-21
Next month: 2026-10-21
Age: 26 years, 4 months
21-Sep-2026
Common Mistakes
- Calling today.plusMonths(1) and expecting "today" itself to change — java.time objects are immutable, so the result must be captured in a new variable.
- Mixing up Period (date-based: years/months/days) with Duration (time-based: hours/minutes/seconds) when measuring an interval.
- Continuing to use java.util.Date or Calendar in new code out of habit — java.time should be preferred for all new development.
- Forgetting that LocalDate and LocalTime carry no timezone information — ZonedDateTime is needed when timezone matters.
Exercise
Starting from 31 January 2024, add one month and print the result, then print that date in the pattern dd/MM/yyyy. Finally print the number of days from 1 January 2024 to 1 March 2024.
Expected output: 2024-02-29, 29/02/2024, 60 (one per line)
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class DatePractice {
public static void main(String[] args) {
LocalDate start = LocalDate.of(2024, 1, 31);
// TODO: add one month and print the new date
// TODO: print the new date formatted as dd/MM/yyyy
// TODO: print the days between 2024-01-01 and 2024-03-01
}
}
Show hints
plusMonths(1)returns a new date. February has no day 31, so the result is the last valid day of the month.ChronoUnit.DAYS.between(from, to)returns the number of days as along.
Show solution
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
public class DatePractice {
public static void main(String[] args) {
LocalDate start = LocalDate.of(2024, 1, 31);
LocalDate next = start.plusMonths(1);
System.out.println(next); // 2024-02-29 (2024 is a leap year)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
System.out.println(next.format(formatter)); // 29/02/2024
long days = ChronoUnit.DAYS.between(LocalDate.of(2024, 1, 1), LocalDate.of(2024, 3, 1));
System.out.println(days); // 60
}
}
Quick quiz
1. After LocalDate d = LocalDate.of(2024, 1, 1); d.plusDays(5); what is the value of d?
- A. 2024-01-06
- B. 2024-01-01
- C. 2024-01-05
- D. It throws an exception
Show answer
B. LocalDate is immutable. plusDays returns a new object, and here the result is discarded.
2. Which class measures an amount of time in hours, minutes and seconds?
- A. Period
- B. LocalDate
- C. Duration
- D. DateTimeFormatter
Show answer
C. Duration is time-based. Period is date-based: years, months and days.
3. Which class should represent a date of birth?
- A. LocalDateTime
- B. Instant
- C. ZonedDateTime
- D. LocalDate
Show answer
D. A date of birth has no time of day and no time zone.
Interview questions
Why was the java.time API introduced?
Show answer
java.util.Date and Calendar are mutable, so a date passed to a method can be changed by it, and they are not thread-safe; SimpleDateFormat in particular fails when shared between threads. Their design is also confusing: months start at 0 and a Date is really a timestamp. The java.time classes are immutable, thread-safe, and separate the concepts of date, time, timestamp and time zone into different classes.
What is the difference between LocalDateTime, ZonedDateTime and Instant?
Show answer
LocalDateTime is a date and time with no time zone, like the reading on a wall clock; it does not identify a single moment. ZonedDateTime adds a time zone, so it does. Instant is a point on the UTC timeline, counted from 1 January 1970, and is the usual choice for storing when something happened.
Key Points to Remember
- java.time (LocalDate, LocalTime, LocalDateTime, Period, Duration, DateTimeFormatter) replaces the legacy Date and Calendar classes.
- All java.time classes are immutable — operations return new instances instead of mutating the original.
- Period measures date-based differences (years/months/days); Duration measures time-based differences (hours/minutes/seconds).
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering