Skip to content

Date and Time — LocalDate, LocalTime, ZonedDateTime, Duration, Period, and Formatting

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Date and Time. We cover key concepts, practical examples, and best practices to help you master this topic.

Java's java.time package provides a comprehensive, immutable date and time API that replaced the legacy Date and Calendar classes. The old API (java.util.Date, java.util.Calendar, java.text.SimpleDateFormat) was notoriously confusing — months were zero-indexed, Date represented both dates and timestamps, and SimpleDateFormat was not thread-safe.

What You'll Learn

  • LocalDate, LocalTime, LocalDateTime for date/time without timezone
  • ZonedDateTime for timezone-aware operations
  • Duration and Period for measuring time spans
  • DateTimeFormatter for Parsing and formatting

Why It Matters

Date and time operations are ubiquitous in business applications: scheduling, logging, analytics, and reporting. Using the modern java.time API eliminates thread-safety issues, unclear APIs, and date calculation bugs.

Real-World Use

Every application handles dates: flight booking (timezone-aware), financial reports (accounting periods), activity logs (timestamps), and expiry dates (tokens, subscriptions).


LocalDate

Date without time or timezone:

LocalDate today = LocalDate.now();
LocalDate specific = LocalDate.of(2026, Month.JUNE, 28);
LocalDate parsed = LocalDate.parse("2026-06-28");

int year = today.getYear();       // 2026
Month month = today.getMonth();   // JUNE
int day = today.getDayOfMonth();  // 28
DayOfWeek dow = today.getDayOfWeek(); // SUNDAY
int dayOfYear = today.getDayOfYear();

// Calculations
LocalDate tomorrow = today.plusDays(1);
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate lastYear = today.minusYears(1);

// Comparison
boolean isBefore = date1.isBefore(date2);
boolean isAfter = date1.isAfter(date2);
boolean isEqual = date1.isEqual(date2);

LocalTime

Time without date or timezone:

LocalTime now = LocalTime.now();
LocalTime specific = LocalTime.of(14, 30, 0); // 2:30 PM
LocalTime parsed = LocalTime.parse("14:30:00");

int hour = now.getHour();
int minute = now.getMinute();
int second = now.getSecond();

// Calculations
LocalTime later = now.plusHours(2);
LocalTime earlier = now.minusMinutes(30);
LocalTime truncated = now.truncatedTo(ChronoUnit.HOURS);

// Comparison
boolean isBefore = time1.isBefore(time2);

LocalDateTime

Combines date and time without timezone:

LocalDateTime now = LocalDateTime.now();
LocalDateTime specific = LocalDateTime.of(2026, Month.JUNE, 28, 14, 30);
LocalDateTime parsed = LocalDateTime.parse("2026-06-28T14:30:00");

// Conversion
LocalDate datePart = now.toLocalDate();
LocalTime timePart = now.toLocalTime();

// Calculations
LocalDateTime nextMonth = now.plusMonths(1);
long daysBetween = ChronoUnit.DAYS.between(start, end);

ZonedDateTime

Time with timezone:

ZonedDateTime now = ZonedDateTime.now(); // system default zone
ZonedDateTime inLondon = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime specific = ZonedDateTime.of(
    2026, 6, 28, 14, 30, 0, 0,
    ZoneId.of("America/New_York")
);

// Zone conversion
ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
ZonedDateTime tokyoTime = nyTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));

// Offset
ZoneOffset offset = nyTime.getOffset(); // -04:00 or -05:00

Available Zone IDs

Set<String> zones = ZoneId.getAvailableZoneIds(); // 600+ zones

Duration and Period

Duration (time-based: hours, minutes, seconds)

Duration fiveHours = Duration.ofHours(5);
Duration halfDay = Duration.ofMinutes(30 * 24);
long minutes = fiveHours.toMinutes(); // 300

Duration between = Duration.between(startTime, endTime);

Period (date-based: years, months, days)

Period twoMonths = Period.ofMonths(2);
Period between = Period.between(startDate, endDate);
int years = between.getYears();
int months = between.getMonths();
int days = between.getDays();

ChronoUnit

long hoursBetween = ChronoUnit.HOURS.between(start, end);
long daysBetween = ChronoUnit.DAYS.between(start, end);

DateTimeFormatter

Formatting

LocalDateTime now = LocalDateTime.now();

DateTimeFormatter iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
System.out.println(now.format(iso)); // 2026-06-28T14:30:00

DateTimeFormatter custom = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
System.out.println(now.format(custom)); // 28/06/2026 14:30

DateTimeFormatter fullDate = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
System.out.println(now.format(fullDate)); // Sunday, June 28, 2026 (locale-dependent)

Common Patterns

Pattern Output
yyyy-MM-dd 2026-06-28
dd/MM/yyyy 28/06/2026
HH:mm:ss 14:30:00
EEE, MMM d, yyyy Sun, Jun 28, 2026
hh:mm a 02:30 PM

Parsing

LocalDate date = LocalDate.parse("28/06/2026",
    DateTimeFormatter.ofPattern("dd/MM/yyyy"));

Legacy Compatibility

Convert between old and new APIs:

// Date to Instant
Date legacy = new Date();
Instant instant = legacy.toInstant();

// Calendar to Instant
Calendar cal = Calendar.getInstance();
Instant fromCal = cal.toInstant();

// Instant to LocalDateTime
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

Common Mistakes

  1. Using LocalDateTime when you need timezone-awareness. LocalDateTime is a plain date+time without zone. For world-wide apps, use ZonedDateTime.
  2. Assuming Period.between() returns total days. Period gives years, months, days — not total days. For total days, use ChronoUnit.DAYS.between().
  3. Using SimpleDateFormat in multi-threaded code. SimpleDateFormat is not thread-safe. DateTimeFormatter is immutable and thread-safe.
  4. Parsing with wrong format. LocalDate.parse("28/06/2026") throws DateTimeParseException — the default format is yyyy-MM-dd.
  5. Forgetting Month is 1-indexed. Unlike the old Calendar where January was 0, Month.JANUARY is 1.

Practice Questions

1. What is the difference between LocalDate and ZonedDateTime?
LocalDate is a date without time or timezone. ZonedDateTime includes time and full timezone rules (including DST).

2. What is the difference between Duration and Period?
Duration is time-based (hours, minutes, seconds, nanoseconds). Period is date-based (years, months, days).

3. Is DateTimeFormatter thread-safe?
Yes. DateTimeFormatter is immutable and thread-safe, unlike the legacy SimpleDateFormat.

4. How do you convert a java.util.Date to LocalDateTime?
LegacyDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().

5. What does ChronoUnit.DAYS.between() return?
The total number of days between two temporal values, ignoring time components.

Challenge Question:
Write a method long calculateAgeInDays(int year, int month, int day) that returns the number of days between that date and today. Then write a method String nextFriday13th() that returns the date of the next Friday the 13th after today. Use ZonedDateTime for both.

FAQ

Why was the java.time API introduced?

The old java.util.Date and Calendar had design flaws: mutability (not thread-safe), zero-indexed months, confusing class hierarchy, and limited timezone support. java.time was inspired by Joda-Time and is based on ISO 8601.

What is an Instant?

Instant represents a point on the timeline (epoch seconds + nanoseconds). It is timezone-independent. Use Instant for timestamps, logging, and machine-to-machine communication.

How do I handle Daylight Saving Time?

Use ZonedDateTime. It handles DST transitions automatically. For example, adding 1 day to a ZonedDateTime produces the same clock time even across DST boundaries.

What is the difference between `ofPattern()` and `ofLocalizedDate()`?

ofPattern() accepts a custom pattern string. ofLocalizedDate() uses the locale's default format (SHORT, MEDIUM, LONG, FULL).

Can I store LocalDateTime in a database?

Yes, most ORMs support java.time types since JPA 2.2 (2017). Map to SQL TIMESTAMP or DATE columns depending on precision needed.

Mini Project

Write a program DateTimeDemo.java that:

  1. Prints today's date, current time, and current date-time
  2. Calculates the user's age in years, months, and days from their birthdate
  3. Shows the current time in London, New York, Tokyo, and Sydney
  4. Formats today's date in 5 different formats (ISO, custom, full, medium, short)
  5. Calculates the duration until the next New Year (January 1, next year) in days, hours, minutes, and seconds
  6. Parses a date string "July 4, 2026" and prints it back formatted as "2026-07-04"
  7. Demonstrates DST-safe arithmetic with ZonedDateTime

What's Next

Date and time are essential, but how do you get input from users? Lesson 31 covers Scanner and Basic I/O — reading input with Scanner, using Console for password input, working with System.in/out/err, and printf-style formatting.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro