CoreJava Java8

Java 8 – New Date and Time API (java.time)

Java 8 – New Date and Time API (java.time)

Java's old java.util.Date and Calendar classes are widely regarded as poorly designed — they are mutable, not thread-safe, months are 0-indexed, and the API is confusing. Java 8 introduced the java.time package (inspired by Joda-Time) with immutable, thread-safe, and clearly named classes. This tutorial covers all the essential classes with practical examples.

Key Classes in java.time

Class Represents Has Time Zone?
LocalDate Date only (year, month, day) No
LocalTime Time only (hour, minute, second, nano) No
LocalDateTime Date + Time (no zone) No
ZonedDateTime Date + Time + Zone Yes
Instant Machine timestamp (nanoseconds since epoch) No (always UTC)
Duration Amount of time (hours, minutes, seconds) No
Period Amount of time in date units (years, months, days) No
DateTimeFormatter Format and parse date/time strings No

LocalDate – Working with Dates

import java.time.*;
import java.time.temporal.ChronoUnit;

// Create
LocalDate today     = LocalDate.now();
LocalDate specific  = LocalDate.of(2026, 6, 15);     // June 15, 2026
LocalDate fromStr   = LocalDate.parse("2026-06-15");  // ISO format

System.out.println("Today:    " + today);
System.out.println("Specific: " + specific);

// Access fields
System.out.println("Year:    " + specific.getYear());       // 2026
System.out.println("Month:   " + specific.getMonth());      // JUNE
System.out.println("MonthNo: " + specific.getMonthValue()); // 6
System.out.println("Day:     " + specific.getDayOfMonth()); // 15
System.out.println("DayOfWk: " + specific.getDayOfWeek()); // MONDAY

// Arithmetic — all return new instances (immutable)
LocalDate tomorrow   = today.plusDays(1);
LocalDate nextMonth  = today.plusMonths(1);
LocalDate lastYear   = today.minusYears(1);

// Comparison
System.out.println(specific.isAfter(today));       // depends on today
System.out.println(specific.isBefore(LocalDate.of(2027, 1, 1)));  // true

// Days between two dates
long daysBetween = ChronoUnit.DAYS.between(today, LocalDate.of(2027, 1, 1));
System.out.println("Days until 2027: " + daysBetween);

// Check properties
System.out.println("Leap year? " + today.isLeapYear());
System.out.println("Days in month: " + today.lengthOfMonth());

LocalTime – Working with Time

LocalTime now     = LocalTime.now();
LocalTime meeting = LocalTime.of(14, 30, 0);   // 14:30:00
LocalTime parsed  = LocalTime.parse("09:15:30");

System.out.println("Now:     " + now);
System.out.println("Meeting: " + meeting);

// Access fields
System.out.println("Hour:   " + meeting.getHour());    // 14
System.out.println("Minute: " + meeting.getMinute());  // 30
System.out.println("Second: " + meeting.getSecond());  // 0

// Arithmetic
LocalTime oneHourLater = meeting.plusHours(1);       // 15:30
LocalTime tenMinsEarly = meeting.minusMinutes(10);   // 14:20

// Is it AM or PM?
System.out.println("AM? " + now.isBefore(LocalTime.NOON));

LocalDateTime – Date + Time Together

LocalDateTime now = LocalDateTime.now();
LocalDateTime dt  = LocalDateTime.of(2026, 6, 15, 10, 30, 0);
LocalDateTime dtFromParts = LocalDate.of(2026, 6, 15)
                               .atTime(LocalTime.of(10, 30));

System.out.println("Now: " + now);
System.out.println("DT:  " + dt);

// Extract parts
LocalDate datePart = dt.toLocalDate();
LocalTime timePart = dt.toLocalTime();

// Arithmetic
LocalDateTime twoHoursLater = dt.plusHours(2);    // 2026-06-15T12:30
LocalDateTime nextWeek      = dt.plusWeeks(1);

// Duration between two LocalDateTimes
Duration duration = Duration.between(dt, dt.plusHours(3).plusMinutes(45));
System.out.println("Duration: " + duration.toHours() + "h " +
                   duration.toMinutesPart() + "m");  // 3h 45m

ZonedDateTime – Time with Time Zone

// Current time in India
ZonedDateTime india = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
System.out.println("India:   " + india);

// Current time in New York
ZonedDateTime newYork = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println("New York: " + newYork);

// Convert between zones
ZonedDateTime indiaInLondon = india.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("India time in London: " + indiaInLondon);

// List all available zone IDs
ZoneId.getAvailableZoneIds().stream()
      .filter(z -> z.startsWith("Asia"))
      .sorted()
      .forEach(System.out::println);

DateTimeFormatter – Format and Parse

import java.time.format.DateTimeFormatter;

LocalDateTime dt = LocalDateTime.of(2026, 6, 15, 14, 30, 0);

// Built-in formatters
System.out.println(dt.format(DateTimeFormatter.ISO_LOCAL_DATE));      // 2026-06-15
System.out.println(dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 2026-06-15T14:30:00

// Custom pattern
DateTimeFormatter custom = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
System.out.println(dt.format(custom));   // 15/06/2026 14:30:00

DateTimeFormatter indian = DateTimeFormatter.ofPattern("d MMMM yyyy, h:mm a");
System.out.println(dt.format(indian));   // 15 June 2026, 2:30 PM

// Parsing — string → LocalDateTime
LocalDateTime parsed = LocalDateTime.parse("15/06/2026 14:30:00", custom);
System.out.println(parsed);  // 2026-06-15T14:30

// Parse with locale
DateTimeFormatter withLocale = DateTimeFormatter.ofPattern("d MMMM yyyy",
    java.util.Locale.ENGLISH);
LocalDate date = LocalDate.parse("15 June 2026", withLocale);
System.out.println(date);  // 2026-06-15

Period and Duration

// Period — date-based amount (years, months, days)
LocalDate start = LocalDate.of(1990, 1, 15);
LocalDate end   = LocalDate.now();

Period age = Period.between(start, end);
System.out.printf("Age: %d years, %d months, %d days%n",
    age.getYears(), age.getMonths(), age.getDays());

Period tenDays  = Period.ofDays(10);
Period twoYears = Period.ofYears(2);
LocalDate future = end.plus(twoYears);

// Duration — time-based amount (hours, minutes, seconds, nanos)
Duration twoHours = Duration.ofHours(2);
Duration ninetyMin = Duration.ofMinutes(90);

System.out.println("2h in minutes: " + twoHours.toMinutes());    // 120
System.out.println("90min in hours: " + ninetyMin.toHours());    // 1

// Duration between two instants
Instant before = Instant.now();
Thread.sleep(100);
Instant after = Instant.now();
Duration elapsed = Duration.between(before, after);
System.out.println("Elapsed ms: " + elapsed.toMillis());  // ~100

Instant – Machine Timestamp

Instant now = Instant.now();
System.out.println("Epoch seconds: " + now.getEpochSecond());
System.out.println("Instant:       " + now);   // 2026-06-15T09:00:00.123456789Z

// Convert to/from LocalDateTime
LocalDateTime ldt = LocalDateTime.ofInstant(now, ZoneId.systemDefault());
Instant back = ldt.toInstant(java.time.ZoneOffset.UTC);

// Legacy interop — converting old Date to new API
java.util.Date oldDate = new java.util.Date();
Instant fromOld = oldDate.toInstant();
LocalDateTime fromOldLdt = LocalDateTime.ofInstant(fromOld, ZoneId.systemDefault());

Old API vs New API – Comparison

Old (java.util) New (java.time) Improvement
new Date() LocalDate.now() Immutable, clearly named
Calendar.JANUARY = 0 Month.JANUARY = 1 No more 0-indexed months
SimpleDateFormat (not thread-safe) DateTimeFormatter (thread-safe) Safe to share across threads
Mutable — date.setTime() All operations return new objects No accidental shared-state bugs
No timezone concept in Date ZonedDateTime explicit Clear timezone handling

Summary

Java 8's java.time package replaces every class from java.util.Date and Calendar. Use LocalDate for dates without time, LocalDateTime for combined date-time without a zone, and ZonedDateTime when the timezone matters (storing events, scheduling). DateTimeFormatter handles all formatting and parsing and is thread-safe. Period measures calendar-unit gaps (years/months/days); Duration measures time-unit gaps (hours/minutes/seconds). All classes are immutable — every arithmetic operation returns a new object, making the API safe for multi-threaded use.

Topics: CoreJava Java8
← Newer Post Older Post →

Comments

https://www.blogger.com/comment/frame/6690124484600543990?po=2165920636684371908&hl=en&saa=85391&origin=https://www.java9r.com