Date Time API

1. Problems with the Old Date API

Before Java 8, working with dates and times in Java was painful. The original java.util.Date and java.util.Calendar classes were introduced in JDK 1.0 and 1.1 respectively, and they were riddled with design flaws that caused bugs in virtually every codebase.

What Was Wrong?

Problem Description Example
Mutable Date objects can be modified after creation. If you pass a Date to a method, that method can change your date. date.setTime(0) silently changes the date everywhere it is referenced
Not thread-safe SimpleDateFormat is not thread-safe. Using it from multiple threads causes corrupted output or exceptions. Shared SimpleDateFormat in a web server causes random NumberFormatException
Months start at 0 January is month 0, December is month 11. This causes off-by-one bugs constantly. new Date(2024, 1, 15) is actually February 15th, not January
Year offset from 1900 The year in Date(year, month, day) is offset from 1900. Year 2024 is represented as 124. new Date(2024, 0, 1) is actually year 3924
Poor API design Date represents both a date and a time. There is no way to represent just a date or just a time. No clean way to say “March 15th” without a time component
Time zone confusion Date stores a UTC timestamp but toString() converts to the local time zone. Calendar’s time zone handling is inconsistent. date.toString() shows local time, but date.getTime() returns UTC millis
SQL Date mess java.sql.Date extends java.util.Date but throws exceptions if you call time methods. Inheritance is broken. sqlDate.getHours() throws IllegalArgumentException
import java.util.Date;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class OldDateProblems {
    public static void main(String[] args) {
        // Problem 1: Months start at 0
        Calendar cal = Calendar.getInstance();
        cal.set(2024, 1, 15); // You think this is January 15, but it's FEBRUARY 15!
        System.out.println("Month 1 is: " + cal.getTime());
        // Output: Month 1 is: Thu Feb 15 ... 2024

        // Problem 2: Date is mutable
        Date startDate = new Date();
        Date endDate = startDate; // Both point to the same object!
        endDate.setTime(0);       // This ALSO changes startDate
        System.out.println("Start date changed to: " + startDate);
        // Output: Start date changed to: Thu Jan 01 00:00:00 GMT 1970

        // Problem 3: Year offset from 1900
        @SuppressWarnings("deprecation")
        Date badDate = new Date(2024, 0, 1); // Year 3924, not 2024!
        System.out.println("Year 2024? " + badDate);
        // Output: Year 2024? Sat Jan 01 ... 3924

        // Problem 4: SimpleDateFormat is NOT thread-safe
        // This shared formatter will cause bugs in multi-threaded code:
        // static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd");
        // Thread 1: FORMAT.parse("2024-01-15");
        // Thread 2: FORMAT.parse("2024-06-20"); // Can corrupt Thread 1's result!

        // Problem 5: No concept of "just a date" or "just a time"
        Date appointment = new Date(); // Always includes date AND time AND timezone
        // There is no way to say "March 15th" without a time attached

        System.out.println("\nAll these problems are solved by java.time (Java 8+)");
    }
}

2. java.time Package Overview

Java 8 introduced the java.time package, designed by Stephen Colebourne (the creator of Joda-Time) under JSR 310. It fixes every problem with the old API by following three core principles:

  • Immutable — All classes are immutable and thread-safe. Every “modification” returns a new object.
  • Clear separation — Separate classes for date-only, time-only, date-time, zoned date-time, and machine timestamps.
  • Fluent API — Methods like of(), now(), plus(), minus(), with() make code readable and intuitive.

Core Classes

Class Represents Example Value Use Case
LocalDate Date without time or timezone 2024-03-15 Birthdays, holidays, deadlines
LocalTime Time without date or timezone 14:30:00 Store opening hours, alarm times
LocalDateTime Date and time without timezone 2024-03-15T14:30:00 Appointments, event timestamps
ZonedDateTime Date, time, and timezone 2024-03-15T14:30:00+05:30[Asia/Kolkata] Flight departures, global meetings
Instant Machine timestamp (UTC) 2024-03-15T09:00:00Z Database timestamps, logs, APIs
Period Date-based amount P2Y3M5D (2 years, 3 months, 5 days) “How old is someone?”
Duration Time-based amount PT2H30M (2 hours, 30 minutes) “How long did this take?”
DateTimeFormatter Formatting and parsing dd/MM/yyyy HH:mm Display dates, parse user input

When to Use Which?

Ask yourself: “Does time zone matter?”

  • No timezone needed — Use LocalDate, LocalTime, or LocalDateTime. These are “local” to wherever the user is.
  • Timezone matters — Use ZonedDateTime. Essential for scheduling across regions.
  • Machine timestamp — Use Instant. A single point on the UTC timeline, independent of human calendars.
import java.time.*;

public class JavaTimeOverview {
    public static void main(String[] args) {
        // Each class represents a different level of precision
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
        LocalDateTime dateTime = LocalDateTime.now();
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        Instant instant = Instant.now();

        System.out.println("LocalDate:     " + date);       // 2024-03-15
        System.out.println("LocalTime:     " + time);       // 14:30:45.123456
        System.out.println("LocalDateTime: " + dateTime);   // 2024-03-15T14:30:45.123456
        System.out.println("ZonedDateTime: " + zonedDateTime); // 2024-03-15T14:30:45.123456-07:00[America/Los_Angeles]
        System.out.println("Instant:       " + instant);    // 2024-03-15T21:30:45.123456Z

        // All are immutable -- "modifying" creates a NEW object
        LocalDate tomorrow = date.plusDays(1);
        System.out.println("\nOriginal date: " + date);       // Unchanged!
        System.out.println("Tomorrow:      " + tomorrow);    // New object
    }
}

3. LocalDate

LocalDate represents a date without a time or timezone — just year, month, and day. Think of it as what you would write on a calendar: March 15, 2024. It is the most commonly used date class.

3.1 Creating LocalDate

import java.time.LocalDate;
import java.time.Month;

public class LocalDateCreation {
    public static void main(String[] args) {
        // Current date
        LocalDate today = LocalDate.now();
        System.out.println("Today: " + today);
        // Output: Today: 2024-03-15

        // Specific date using of()
        LocalDate christmas = LocalDate.of(2024, 12, 25);
        System.out.println("Christmas: " + christmas);
        // Output: Christmas: 2024-12-25

        // Using Month enum (more readable, no off-by-one errors!)
        LocalDate newYear = LocalDate.of(2025, Month.JANUARY, 1);
        System.out.println("New Year: " + newYear);
        // Output: New Year: 2025-01-01

        // Parse from string (ISO format: yyyy-MM-dd)
        LocalDate parsed = LocalDate.parse("2024-07-04");
        System.out.println("Parsed: " + parsed);
        // Output: Parsed: 2024-07-04

        // Special dates
        LocalDate epoch = LocalDate.EPOCH; // 1970-01-01
        LocalDate min = LocalDate.MIN;     // -999999999-01-01
        LocalDate max = LocalDate.MAX;     // +999999999-12-31
        System.out.println("Epoch: " + epoch);
        // Output: Epoch: 1970-01-01
    }
}

3.2 Manipulating LocalDate

Since LocalDate is immutable, all manipulation methods return a new LocalDate.

import java.time.LocalDate;
import java.time.Month;
import java.time.DayOfWeek;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;

public class LocalDateManipulation {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2024, Month.MARCH, 15);

        // Adding and subtracting
        System.out.println("Original:       " + date);              // 2024-03-15
        System.out.println("+5 days:        " + date.plusDays(5));   // 2024-03-20
        System.out.println("+2 weeks:       " + date.plusWeeks(2));  // 2024-03-29
        System.out.println("+3 months:      " + date.plusMonths(3)); // 2024-06-15
        System.out.println("+1 year:        " + date.plusYears(1));  // 2025-03-15
        System.out.println("-10 days:       " + date.minusDays(10)); // 2024-03-05

        // Using with() to set specific fields
        System.out.println("\nwithYear(2025): " + date.withYear(2025));      // 2025-03-15
        System.out.println("withMonth(1):   " + date.withMonth(1));         // 2024-01-15
        System.out.println("withDayOfMonth: " + date.withDayOfMonth(1));    // 2024-03-01

        // Temporal adjusters -- powerful date adjustments
        System.out.println("\nFirst day of month:   " + date.with(TemporalAdjusters.firstDayOfMonth()));
        // Output: 2024-03-01
        System.out.println("Last day of month:    " + date.with(TemporalAdjusters.lastDayOfMonth()));
        // Output: 2024-03-31
        System.out.println("First day of year:    " + date.with(TemporalAdjusters.firstDayOfYear()));
        // Output: 2024-01-01
        System.out.println("Next Monday:          " + date.with(TemporalAdjusters.next(DayOfWeek.MONDAY)));
        // Output: 2024-03-18
        System.out.println("Previous Friday:      " + date.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY)));
        // Output: 2024-03-08

        // Getting information
        System.out.println("\nYear:           " + date.getYear());        // 2024
        System.out.println("Month:          " + date.getMonth());        // MARCH
        System.out.println("Month value:    " + date.getMonthValue());   // 3 (not 2!)
        System.out.println("Day of month:   " + date.getDayOfMonth());   // 15
        System.out.println("Day of week:    " + date.getDayOfWeek());    // FRIDAY
        System.out.println("Day of year:    " + date.getDayOfYear());    // 75
        System.out.println("Leap year:      " + date.isLeapYear());      // true (2024)
        System.out.println("Days in month:  " + date.lengthOfMonth());   // 31
        System.out.println("Days in year:   " + date.lengthOfYear());    // 366
    }
}

3.3 Comparing Dates and Calculating Age

import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.time.temporal.ChronoUnit;

public class LocalDateComparison {
    public static void main(String[] args) {
        LocalDate today = LocalDate.of(2024, Month.MARCH, 15);
        LocalDate birthday = LocalDate.of(1990, Month.JULY, 20);
        LocalDate deadline = LocalDate.of(2024, Month.APRIL, 1);

        // Comparison methods
        System.out.println("Is today before deadline? " + today.isBefore(deadline));  // true
        System.out.println("Is today after birthday?  " + today.isAfter(birthday));   // true
        System.out.println("Are they equal?           " + today.isEqual(today));       // true

        // Calculate age
        Period age = Period.between(birthday, today);
        System.out.println("\nAge: " + age.getYears() + " years, "
            + age.getMonths() + " months, "
            + age.getDays() + " days");
        // Output: Age: 33 years, 7 months, 24 days

        // Days between dates
        long daysBetween = ChronoUnit.DAYS.between(today, deadline);
        System.out.println("Days until deadline: " + daysBetween);
        // Output: Days until deadline: 17

        long monthsBetween = ChronoUnit.MONTHS.between(birthday, today);
        System.out.println("Months since birth: " + monthsBetween);
        // Output: Months since birth: 403

        // Age calculation utility
        System.out.println("\n--- Age Calculator ---");
        LocalDate[] birthdays = {
            LocalDate.of(2000, 1, 1),
            LocalDate.of(1985, 6, 15),
            LocalDate.of(2010, 12, 25)
        };

        for (LocalDate bday : birthdays) {
            int years = Period.between(bday, today).getYears();
            System.out.printf("Born %s -> Age %d%n", bday, years);
        }
        // Output:
        // Born 2000-01-01 -> Age 24
        // Born 1985-06-15 -> Age 38
        // Born 2010-12-25 -> Age 13
    }
}

4. LocalTime

LocalTime represents a time without a date or timezone — hours, minutes, seconds, and nanoseconds. Think of it as what you see on a clock: 14:30:00. Use it for things like store opening hours, alarm times, or daily schedules.

import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class LocalTimeDemo {
    public static void main(String[] args) {
        // Creating LocalTime
        LocalTime now = LocalTime.now();
        LocalTime morning = LocalTime.of(9, 0);           // 09:00
        LocalTime afternoon = LocalTime.of(14, 30, 0);    // 14:30:00
        LocalTime precise = LocalTime.of(10, 15, 30, 500_000_000); // 10:15:30.5
        LocalTime parsed = LocalTime.parse("18:45:00");    // 18:45:00

        System.out.println("Now:       " + now);
        System.out.println("Morning:   " + morning);
        System.out.println("Afternoon: " + afternoon);
        System.out.println("Precise:   " + precise);

        // Special constants
        System.out.println("\nMidnight:  " + LocalTime.MIDNIGHT); // 00:00
        System.out.println("Noon:      " + LocalTime.NOON);      // 12:00
        System.out.println("Min:       " + LocalTime.MIN);       // 00:00
        System.out.println("Max:       " + LocalTime.MAX);       // 23:59:59.999999999

        // Manipulation
        LocalTime meetingTime = LocalTime.of(10, 0);
        System.out.println("\nMeeting:   " + meetingTime);
        System.out.println("+2 hours:  " + meetingTime.plusHours(2));    // 12:00
        System.out.println("+30 mins:  " + meetingTime.plusMinutes(30)); // 10:30
        System.out.println("-1 hour:   " + meetingTime.minusHours(1));   // 09:00

        // Getting components
        System.out.println("\nHour:   " + afternoon.getHour());   // 14
        System.out.println("Minute: " + afternoon.getMinute()); // 30
        System.out.println("Second: " + afternoon.getSecond()); // 0

        // Comparing
        System.out.println("\nMorning before afternoon? " + morning.isBefore(afternoon)); // true
        System.out.println("Morning after afternoon?  " + morning.isAfter(afternoon));   // false

        // Time between
        long minutesBetween = ChronoUnit.MINUTES.between(morning, afternoon);
        System.out.println("Minutes from morning to afternoon: " + minutesBetween);
        // Output: Minutes from morning to afternoon: 330

        // Business hours check
        LocalTime openTime = LocalTime.of(9, 0);
        LocalTime closeTime = LocalTime.of(17, 0);
        LocalTime checkTime = LocalTime.of(14, 30);

        boolean isOpen = !checkTime.isBefore(openTime) && checkTime.isBefore(closeTime);
        System.out.println("\nStore open at " + checkTime + "? " + isOpen);
        // Output: Store open at 14:30? true
    }
}

5. LocalDateTime

LocalDateTime combines LocalDate and LocalTime into a single object — a date and time without a timezone. It is the most commonly used class when you need both date and time together, such as for appointments, event timestamps, or log entries in a single-timezone application.

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.temporal.ChronoUnit;

public class LocalDateTimeDemo {
    public static void main(String[] args) {
        // Creating LocalDateTime
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime specific = LocalDateTime.of(2024, Month.DECEMBER, 31, 23, 59, 59);
        LocalDateTime parsed = LocalDateTime.parse("2024-07-04T10:30:00");

        System.out.println("Now:      " + now);
        System.out.println("Specific: " + specific);   // 2024-12-31T23:59:59
        System.out.println("Parsed:   " + parsed);     // 2024-07-04T10:30

        // Combining LocalDate and LocalTime
        LocalDate date = LocalDate.of(2024, 6, 15);
        LocalTime time = LocalTime.of(14, 30);
        LocalDateTime combined = LocalDateTime.of(date, time);
        System.out.println("Combined: " + combined);   // 2024-06-15T14:30

        // Alternative: atTime() and atDate()
        LocalDateTime fromDate = date.atTime(9, 0);           // 2024-06-15T09:00
        LocalDateTime fromTime = time.atDate(date);            // 2024-06-15T14:30
        LocalDateTime startOfDay = date.atStartOfDay();        // 2024-06-15T00:00
        System.out.println("Start of day: " + startOfDay);

        // Extracting date and time
        LocalDate extractedDate = combined.toLocalDate();
        LocalTime extractedTime = combined.toLocalTime();
        System.out.println("\nExtracted date: " + extractedDate);  // 2024-06-15
        System.out.println("Extracted time: " + extractedTime);    // 14:30

        // Manipulation
        LocalDateTime event = LocalDateTime.of(2024, 3, 15, 10, 0);
        System.out.println("\nEvent:         " + event);
        System.out.println("+3 days:       " + event.plusDays(3));
        System.out.println("+2 hours:      " + event.plusHours(2));
        System.out.println("-30 minutes:   " + event.minusMinutes(30));
        System.out.println("Set hour to 8: " + event.withHour(8));

        // Comparing
        LocalDateTime meeting1 = LocalDateTime.of(2024, 3, 15, 10, 0);
        LocalDateTime meeting2 = LocalDateTime.of(2024, 3, 15, 14, 0);
        System.out.println("\nMeeting1 before Meeting2? " + meeting1.isBefore(meeting2)); // true

        long hoursBetween = ChronoUnit.HOURS.between(meeting1, meeting2);
        System.out.println("Hours between meetings: " + hoursBetween);
        // Output: Hours between meetings: 4
    }
}

6. ZonedDateTime

ZonedDateTime is a date-time with full time zone information. Use it whenever the timezone matters — scheduling meetings across countries, flight departure/arrival times, or any scenario where the same “local time” has different meanings in different regions.

Understanding Time Zones

A time zone is identified by a ZoneId like "America/New_York" or "Asia/Tokyo". It encodes the UTC offset AND the daylight saving rules for that region. Do not use fixed offsets like "GMT+5" unless you specifically want to ignore DST.

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Set;

public class ZonedDateTimeDemo {
    public static void main(String[] args) {
        // Creating ZonedDateTime
        ZonedDateTime nowHere = ZonedDateTime.now();
        ZonedDateTime nowTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
        ZonedDateTime nowLondon = ZonedDateTime.now(ZoneId.of("Europe/London"));

        System.out.println("Here:   " + nowHere);
        System.out.println("Tokyo:  " + nowTokyo);
        System.out.println("London: " + nowLondon);

        // Specific date-time in a zone
        ZonedDateTime meeting = ZonedDateTime.of(
            2024, 3, 15, 10, 0, 0, 0,
            ZoneId.of("America/New_York")
        );
        System.out.println("\nMeeting (NY): " + meeting);
        // Output: Meeting (NY): 2024-03-15T10:00-04:00[America/New_York]

        // Converting between time zones
        ZonedDateTime meetingLA = meeting.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
        ZonedDateTime meetingLondon = meeting.withZoneSameInstant(ZoneId.of("Europe/London"));
        ZonedDateTime meetingTokyo = meeting.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        ZonedDateTime meetingIndia = meeting.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));

        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("HH:mm z (MMM dd)");
        System.out.println("\nMeeting at 10:00 AM New York is:");
        System.out.println("  Los Angeles: " + meetingLA.format(fmt));
        System.out.println("  London:      " + meetingLondon.format(fmt));
        System.out.println("  Tokyo:       " + meetingTokyo.format(fmt));
        System.out.println("  India:       " + meetingIndia.format(fmt));
        // Output:
        // Meeting at 10:00 AM New York is:
        //   Los Angeles: 07:00 PDT (Mar 15)
        //   London:      14:00 GMT (Mar 15)
        //   Tokyo:       23:00 JST (Mar 15)
        //   India:       19:30 IST (Mar 15)

        // withZoneSameLocal vs withZoneSameInstant
        // withZoneSameInstant: Same moment, different clock reading
        // withZoneSameLocal: Same clock reading, different moment
        ZonedDateTime noonNY = ZonedDateTime.of(2024, 6, 15, 12, 0, 0, 0,
            ZoneId.of("America/New_York"));
        ZonedDateTime sameInstant = noonNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
        ZonedDateTime sameLocal = noonNY.withZoneSameLocal(ZoneId.of("Asia/Tokyo"));
        System.out.println("\nNoon in NY:      " + noonNY);
        System.out.println("Same instant:    " + sameInstant);  // Next day 1 AM in Tokyo
        System.out.println("Same local time: " + sameLocal);    // Noon in Tokyo (different moment!)

        // Available zone IDs
        Set zones = ZoneId.getAvailableZoneIds();
        System.out.println("\nTotal time zones available: " + zones.size());
        // Output: Total time zones available: ~600

        // Handling Daylight Saving Time
        // Spring forward: 2:00 AM -> 3:00 AM (1 hour gap)
        ZonedDateTime beforeDST = ZonedDateTime.of(
            2024, 3, 10, 1, 30, 0, 0, ZoneId.of("America/New_York"));
        ZonedDateTime afterDST = beforeDST.plusHours(1);
        System.out.println("\nBefore DST: " + beforeDST); // 01:30 EST
        System.out.println("After +1h:  " + afterDST);    // 03:30 EDT (skips 2:00-3:00!)
    }
}

7. Instant

Instant represents a single point on the UTC timeline — a machine timestamp measured in seconds and nanoseconds from the Unix epoch (January 1, 1970, 00:00:00 UTC). It has no concept of human-readable dates, months, or time zones. Think of it as what a computer stores internally when tracking “when something happened.”

Use Instant for:

  • Database timestamps
  • Log entries
  • Measuring elapsed time
  • REST API timestamps
  • Anything that needs to be timezone-independent
import java.time.Instant;
import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

public class InstantDemo {
    public static void main(String[] args) throws InterruptedException {
        // Current instant
        Instant now = Instant.now();
        System.out.println("Now: " + now);
        // Output: Now: 2024-03-15T21:30:45.123456Z  (always UTC, denoted by Z)

        // From epoch
        Instant epoch = Instant.EPOCH;
        System.out.println("Epoch: " + epoch);
        // Output: Epoch: 1970-01-01T00:00:00Z

        Instant fromEpochSeconds = Instant.ofEpochSecond(1_700_000_000);
        System.out.println("From epoch seconds: " + fromEpochSeconds);
        // Output: From epoch seconds: 2023-11-14T22:13:20Z

        Instant fromEpochMillis = Instant.ofEpochMilli(System.currentTimeMillis());
        System.out.println("From epoch millis:  " + fromEpochMillis);

        // Parse ISO-8601 string
        Instant parsed = Instant.parse("2024-01-15T10:30:00Z");
        System.out.println("Parsed: " + parsed);

        // Getting epoch values
        System.out.println("\nEpoch second: " + now.getEpochSecond());
        System.out.println("Nano adjust:  " + now.getNano());

        // Measuring execution time
        System.out.println("\n--- Execution Time ---");
        Instant start = Instant.now();

        // Simulate work
        long sum = 0;
        for (int i = 0; i < 10_000_000; i++) {
            sum += i;
        }

        Instant end = Instant.now();
        Duration elapsed = Duration.between(start, end);
        System.out.println("Sum: " + sum);
        System.out.printf("Elapsed: %d ms (%d ns)%n",
            elapsed.toMillis(), elapsed.toNanos());
        // Output: Elapsed: 15 ms (15234567 ns)

        // Comparing instants
        Instant past = Instant.now().minus(1, ChronoUnit.HOURS);
        Instant future = Instant.now().plus(1, ChronoUnit.HOURS);
        System.out.println("\nPast is before now: " + past.isBefore(now));    // true
        System.out.println("Future is after now: " + future.isAfter(now));   // true

        // Converting Instant to ZonedDateTime (for human display)
        ZonedDateTime inNY = now.atZone(ZoneId.of("America/New_York"));
        ZonedDateTime inTokyo = now.atZone(ZoneId.of("Asia/Tokyo"));
        System.out.println("\nSame instant, different zones:");
        System.out.println("  New York: " + inNY);
        System.out.println("  Tokyo:    " + inTokyo);
    }
}

8. Period and Duration

Java 8 provides two classes for representing amounts of time:

  • Period -- A date-based amount: years, months, and days. Use it to answer "How many years/months/days between two dates?"
  • Duration -- A time-based amount: hours, minutes, seconds, and nanoseconds. Use it to answer "How long did this operation take?"
Feature Period Duration
Measures Years, months, days Hours, minutes, seconds, nanos
Pair with LocalDate LocalTime, Instant
ISO format P2Y3M5D PT2H30M
Factory method Period.between(date1, date2) Duration.between(time1, time2)
Use case "Contract expires in 2 years" "API call took 350ms"
import java.time.*;
import java.time.temporal.ChronoUnit;

public class PeriodDurationDemo {
    public static void main(String[] args) {
        // ========== PERIOD (date-based) ==========
        System.out.println("=== Period ===");

        // Creating periods
        Period twoYears = Period.ofYears(2);
        Period threeMonths = Period.ofMonths(3);
        Period tenDays = Period.ofDays(10);
        Period custom = Period.of(1, 6, 15); // 1 year, 6 months, 15 days

        System.out.println("Two years:    " + twoYears);    // P2Y
        System.out.println("Three months: " + threeMonths); // P3M
        System.out.println("Custom:       " + custom);      // P1Y6M15D

        // Between two dates
        LocalDate hired = LocalDate.of(2020, Month.MARCH, 1);
        LocalDate today = LocalDate.of(2024, Month.MARCH, 15);
        Period tenure = Period.between(hired, today);
        System.out.println("\nTenure: " + tenure.getYears() + " years, "
            + tenure.getMonths() + " months, "
            + tenure.getDays() + " days");
        // Output: Tenure: 4 years, 0 months, 14 days

        // Adding period to a date
        LocalDate contractStart = LocalDate.of(2024, 1, 1);
        LocalDate contractEnd = contractStart.plus(Period.of(2, 0, 0));
        System.out.println("Contract: " + contractStart + " to " + contractEnd);
        // Output: Contract: 2024-01-01 to 2026-01-01

        // ========== DURATION (time-based) ==========
        System.out.println("\n=== Duration ===");

        // Creating durations
        Duration twoHours = Duration.ofHours(2);
        Duration thirtyMinutes = Duration.ofMinutes(30);
        Duration fiveSeconds = Duration.ofSeconds(5);
        Duration halfSecond = Duration.ofMillis(500);

        System.out.println("Two hours:      " + twoHours);      // PT2H
        System.out.println("Thirty minutes: " + thirtyMinutes); // PT30M
        System.out.println("Five seconds:   " + fiveSeconds);   // PT5S
        System.out.println("Half second:    " + halfSecond);     // PT0.5S

        // Between two times
        LocalTime start = LocalTime.of(9, 0);
        LocalTime end = LocalTime.of(17, 30);
        Duration workday = Duration.between(start, end);
        System.out.println("\nWorkday: " + workday);
        System.out.println("In hours:   " + workday.toHours());     // 8
        System.out.println("In minutes: " + workday.toMinutes());   // 510
        System.out.println("In seconds: " + workday.getSeconds());  // 30600

        // Between two instants
        Instant begin = Instant.parse("2024-03-15T10:00:00Z");
        Instant finish = Instant.parse("2024-03-15T10:05:30.500Z");
        Duration apiCall = Duration.between(begin, finish);
        System.out.println("\nAPI duration: " + apiCall);            // PT5M30.5S
        System.out.println("In millis:    " + apiCall.toMillis());  // 330500

        // Manipulation
        Duration meeting = Duration.ofHours(1);
        System.out.println("\nMeeting:     " + meeting);
        System.out.println("+30 min:     " + meeting.plusMinutes(30)); // PT1H30M
        System.out.println("x2:          " + meeting.multipliedBy(2)); // PT2H

        // Parse ISO-8601
        Duration parsed = Duration.parse("PT2H30M");
        System.out.println("Parsed:      " + parsed); // PT2H30M

        // ChronoUnit for total amounts
        long totalDays = ChronoUnit.DAYS.between(
            LocalDate.of(2024, 1, 1), LocalDate.of(2024, 12, 31));
        System.out.println("\nDays in 2024: " + totalDays);
        // Output: Days in 2024: 365
    }
}

9. DateTimeFormatter

DateTimeFormatter is the replacement for SimpleDateFormat. It is immutable and thread-safe, which means you can safely share a single instance across your entire application. It handles both formatting (date to string) and parsing (string to date).

9.1 Predefined Formatters

Java provides several built-in formatters for common ISO formats:

Formatter Example Output Use Case
ISO_LOCAL_DATE 2024-03-15 Standard date format
ISO_LOCAL_TIME 14:30:00 Standard time format
ISO_LOCAL_DATE_TIME 2024-03-15T14:30:00 Standard date-time format
ISO_ZONED_DATE_TIME 2024-03-15T14:30:00-04:00[America/New_York] Date-time with zone
ISO_INSTANT 2024-03-15T18:30:00Z UTC timestamp
ISO_DATE 2024-03-15 or 2024-03-15-04:00 Date with optional offset
RFC_1123_DATE_TIME Fri, 15 Mar 2024 14:30:00 -0400 HTTP headers
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

public class DateTimeFormatterDemo {
    public static void main(String[] args) {
        LocalDateTime dateTime = LocalDateTime.of(2024, 3, 15, 14, 30, 0);
        LocalDate date = dateTime.toLocalDate();

        // Predefined formatters
        System.out.println("=== Predefined Formatters ===");
        System.out.println("ISO_LOCAL_DATE:      " + date.format(DateTimeFormatter.ISO_LOCAL_DATE));
        System.out.println("ISO_LOCAL_DATE_TIME: " + dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        // Output:
        // ISO_LOCAL_DATE:      2024-03-15
        // ISO_LOCAL_DATE_TIME: 2024-03-15T14:30:00

        // Custom patterns
        System.out.println("\n=== Custom Patterns ===");
        DateTimeFormatter f1 = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        DateTimeFormatter f2 = DateTimeFormatter.ofPattern("MMMM dd, yyyy");
        DateTimeFormatter f3 = DateTimeFormatter.ofPattern("MM-dd-yyyy HH:mm:ss");
        DateTimeFormatter f4 = DateTimeFormatter.ofPattern("EEE, MMM d, yyyy h:mm a");
        DateTimeFormatter f5 = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");

        System.out.println("dd/MM/yyyy:          " + date.format(f1));
        System.out.println("MMMM dd, yyyy:       " + date.format(f2));
        System.out.println("MM-dd-yyyy HH:mm:ss: " + dateTime.format(f3));
        System.out.println("EEE, MMM d, ...:     " + dateTime.format(f4));
        System.out.println("yyyy/MM/dd HH:mm:    " + dateTime.format(f5));
        // Output:
        // dd/MM/yyyy:          15/03/2024
        // MMMM dd, yyyy:       March 15, 2024
        // MM-dd-yyyy HH:mm:ss: 03-15-2024 14:30:00
        // EEE, MMM d, ...:     Fri, Mar 15, 2024 2:30 PM
        // yyyy/MM/dd HH:mm:    2024/03/15 14:30

        // Localized formatters
        System.out.println("\n=== Localized Formatters ===");
        DateTimeFormatter french = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
            .withLocale(Locale.FRENCH);
        DateTimeFormatter german = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
            .withLocale(Locale.GERMAN);
        DateTimeFormatter japanese = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
            .withLocale(Locale.JAPANESE);

        System.out.println("French (FULL):    " + date.format(french));
        System.out.println("German (LONG):    " + date.format(german));
        System.out.println("Japanese (MEDIUM):" + date.format(japanese));
        // Output (varies by JDK):
        // French (FULL):    vendredi 15 mars 2024
        // German (LONG):    15. Marz 2024
        // Japanese (MEDIUM):2024/03/15

        // Parsing strings to dates
        System.out.println("\n=== Parsing ===");
        LocalDate parsed1 = LocalDate.parse("2024-03-15"); // ISO format, no formatter needed
        LocalDate parsed2 = LocalDate.parse("15/03/2024", f1);
        LocalDate parsed3 = LocalDate.parse("March 15, 2024", f2);
        LocalDateTime parsed4 = LocalDateTime.parse("03-15-2024 14:30:00", f3);

        System.out.println("Parsed ISO:    " + parsed1);
        System.out.println("Parsed dd/MM:  " + parsed2);
        System.out.println("Parsed Month:  " + parsed3);
        System.out.println("Parsed full:   " + parsed4);
    }
}

Pattern Symbols Reference

Symbol Meaning Example
y Year 2024 (yyyy), 24 (yy)
M Month 3 (M), 03 (MM), Mar (MMM), March (MMMM)
d Day of month 5 (d), 05 (dd)
E Day of week Fri (EEE), Friday (EEEE)
H Hour (0-23) 14 (HH)
h Hour (1-12) 2 (h), 02 (hh)
m Minute 30 (mm)
s Second 45 (ss)
S Fraction of second 123 (SSS)
a AM/PM PM
z Time zone name PST, PDT
Z Time zone offset -0800
V Time zone ID America/Los_Angeles (VV)

10. Converting from Legacy API

If you are working with legacy code that uses java.util.Date or java.util.Calendar, Java 8 provides bridge methods to convert to and from the new API. The key conversion point is Instant -- all legacy classes can convert to an Instant, and from there you can get any java.time class.

import java.time.*;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.sql.Timestamp;

public class LegacyConversion {
    public static void main(String[] args) {
        // ========== java.util.Date <-> java.time ==========
        System.out.println("=== java.util.Date Conversion ===");

        // Date -> Instant -> LocalDateTime
        Date oldDate = new Date();
        Instant instant = oldDate.toInstant();
        LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        LocalDate ld = ldt.toLocalDate();
        ZonedDateTime zdt = instant.atZone(ZoneId.systemDefault());

        System.out.println("Old Date:      " + oldDate);
        System.out.println("Instant:       " + instant);
        System.out.println("LocalDateTime: " + ldt);
        System.out.println("LocalDate:     " + ld);
        System.out.println("ZonedDateTime: " + zdt);

        // LocalDateTime -> Date (reverse)
        LocalDateTime newDateTime = LocalDateTime.of(2024, 6, 15, 14, 30);
        Date backToDate = Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant());
        System.out.println("\nBack to Date:  " + backToDate);

        // ========== Calendar <-> java.time ==========
        System.out.println("\n=== Calendar Conversion ===");

        // Calendar -> ZonedDateTime
        Calendar calendar = Calendar.getInstance();
        if (calendar instanceof GregorianCalendar gc) {
            ZonedDateTime fromCal = gc.toZonedDateTime();
            System.out.println("From Calendar: " + fromCal);
        }

        // ZonedDateTime -> Calendar
        ZonedDateTime zonedNow = ZonedDateTime.now();
        GregorianCalendar backToCal = GregorianCalendar.from(zonedNow);
        System.out.println("Back to Cal:   " + backToCal.getTime());

        // ========== TimeZone <-> ZoneId ==========
        System.out.println("\n=== TimeZone Conversion ===");
        TimeZone oldTZ = TimeZone.getTimeZone("America/New_York");
        ZoneId newZoneId = oldTZ.toZoneId();
        TimeZone backToTZ = TimeZone.getTimeZone(newZoneId);
        System.out.println("Old TimeZone: " + oldTZ.getID());
        System.out.println("New ZoneId:   " + newZoneId);

        // ========== java.sql.Timestamp <-> java.time ==========
        System.out.println("\n=== SQL Timestamp Conversion ===");

        // Timestamp -> LocalDateTime (no timezone conversion)
        Timestamp sqlTimestamp = Timestamp.valueOf("2024-03-15 14:30:00");
        LocalDateTime fromTimestamp = sqlTimestamp.toLocalDateTime();
        System.out.println("From Timestamp: " + fromTimestamp);

        // LocalDateTime -> Timestamp
        Timestamp backToTimestamp = Timestamp.valueOf(newDateTime);
        System.out.println("Back to Timestamp: " + backToTimestamp);

        // Timestamp -> Instant
        Instant fromTimestampInstant = sqlTimestamp.toInstant();
        System.out.println("Timestamp Instant: " + fromTimestampInstant);
    }
}

Migration Cheat Sheet

Old API New API Conversion Method
java.util.Date Instant date.toInstant()
Instant java.util.Date Date.from(instant)
java.util.Date LocalDate date.toInstant().atZone(zone).toLocalDate()
LocalDate java.util.Date Date.from(localDate.atStartOfDay(zone).toInstant())
GregorianCalendar ZonedDateTime gc.toZonedDateTime()
ZonedDateTime GregorianCalendar GregorianCalendar.from(zdt)
java.sql.Timestamp LocalDateTime ts.toLocalDateTime()
LocalDateTime java.sql.Timestamp Timestamp.valueOf(ldt)
java.sql.Date LocalDate sqlDate.toLocalDate()
LocalDate java.sql.Date java.sql.Date.valueOf(localDate)
TimeZone ZoneId timeZone.toZoneId()
SimpleDateFormat DateTimeFormatter No direct conversion; rewrite pattern

11. Complete Practical Example -- Event Scheduling System

This example demonstrates a realistic event scheduling system that uses every major class from the java.time package. It handles creating events across time zones, calculating durations, formatting for different locales, and checking for schedule conflicts.

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

public class EventSchedulingSystem {

    // Immutable Event record
    record Event(
        String name,
        ZonedDateTime start,
        Duration duration,
        ZoneId creatorZone
    ) {
        ZonedDateTime end() {
            return start.plus(duration);
        }

        boolean conflictsWith(Event other) {
            return this.start.isBefore(other.end()) && other.start.isBefore(this.end());
        }

        String formatForZone(ZoneId zone) {
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE, MMM d yyyy 'at' h:mm a z");
            ZonedDateTime inZone = start.withZoneSameInstant(zone);
            return name + ": " + inZone.format(fmt)
                + " (" + duration.toHours() + "h " + (duration.toMinutesPart()) + "m)";
        }
    }

    public static void main(String[] args) {
        System.out.println("=== Event Scheduling System ===\n");

        // Define time zones for participants
        ZoneId newYork = ZoneId.of("America/New_York");
        ZoneId london = ZoneId.of("Europe/London");
        ZoneId tokyo = ZoneId.of("Asia/Tokyo");
        ZoneId india = ZoneId.of("Asia/Kolkata");

        // ---- Create Events ----
        System.out.println("--- Creating Events ---");

        // Event 1: Team standup at 9 AM New York time
        Event standup = new Event(
            "Team Standup",
            ZonedDateTime.of(2024, 3, 18, 9, 0, 0, 0, newYork),
            Duration.ofMinutes(30),
            newYork
        );

        // Event 2: Client demo at 2 PM London time
        Event clientDemo = new Event(
            "Client Demo",
            ZonedDateTime.of(2024, 3, 18, 14, 0, 0, 0, london),
            Duration.ofHours(1).plusMinutes(30),
            london
        );

        // Event 3: Sprint planning at 10 AM Tokyo time
        Event sprintPlanning = new Event(
            "Sprint Planning",
            ZonedDateTime.of(2024, 3, 18, 10, 0, 0, 0, tokyo),
            Duration.ofHours(2),
            tokyo
        );

        List events = List.of(standup, clientDemo, sprintPlanning);

        // ---- Display Events in All Time Zones ----
        System.out.println("\n--- Events in Each Time Zone ---");
        List zones = List.of(newYork, london, tokyo, india);

        for (ZoneId zone : zones) {
            System.out.println("\n" + zone.getId() + ":");
            for (Event event : events) {
                System.out.println("  " + event.formatForZone(zone));
            }
        }

        // ---- Check for Conflicts ----
        System.out.println("\n--- Conflict Detection ---");
        for (int i = 0; i < events.size(); i++) {
            for (int j = i + 1; j < events.size(); j++) {
                Event e1 = events.get(i);
                Event e2 = events.get(j);
                if (e1.conflictsWith(e2)) {
                    System.out.println("CONFLICT: " + e1.name() + " overlaps with " + e2.name());
                } else {
                    System.out.println("OK: " + e1.name() + " and " + e2.name() + " do not overlap");
                }
            }
        }

        // ---- Calculate Time Until Events ----
        System.out.println("\n--- Time Until Events (from now) ---");
        ZonedDateTime now = ZonedDateTime.of(2024, 3, 15, 12, 0, 0, 0, newYork);

        for (Event event : events) {
            Duration until = Duration.between(now.toInstant(), event.start().toInstant());
            long days = until.toDays();
            long hours = until.toHoursPart();
            long minutes = until.toMinutesPart();
            System.out.printf("  %s: %d days, %d hours, %d minutes%n",
                event.name(), days, hours, minutes);
        }

        // ---- Find Next Available Slot ----
        System.out.println("\n--- Next Available Slot ---");
        LocalDate meetingDate = LocalDate.of(2024, 3, 18);
        Duration meetingLength = Duration.ofHours(1);

        // Check each hour of the business day (9 AM - 5 PM New York)
        LocalTime checkStart = LocalTime.of(9, 0);
        LocalTime checkEnd = LocalTime.of(17, 0);

        LocalTime candidate = checkStart;
        while (candidate.plus(meetingLength).isBefore(checkEnd)
               || candidate.plus(meetingLength).equals(checkEnd)) {
            ZonedDateTime candidateStart = ZonedDateTime.of(meetingDate, candidate, newYork);
            ZonedDateTime candidateEnd = candidateStart.plus(meetingLength);

            boolean hasConflict = false;
            for (Event event : events) {
                ZonedDateTime eventStartNY = event.start().withZoneSameInstant(newYork);
                ZonedDateTime eventEndNY = event.end().withZoneSameInstant(newYork);
                if (candidateStart.isBefore(eventEndNY) && eventStartNY.isBefore(candidateEnd)) {
                    hasConflict = true;
                    break;
                }
            }

            if (!hasConflict) {
                System.out.println("  Available: " + candidate + " - " + candidate.plus(meetingLength) + " (New York)");
                break;
            }
            candidate = candidate.plusMinutes(30);
        }

        // ---- Date Calculations ----
        System.out.println("\n--- Date Calculations ---");

        // Recurring weekly event -- next 4 occurrences
        LocalDate nextMonday = meetingDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
        System.out.println("Next 4 Monday standups:");
        for (int i = 0; i < 4; i++) {
            LocalDate occurrence = nextMonday.plusWeeks(i);
            System.out.println("  " + occurrence + " (" + occurrence.getDayOfWeek() + ")");
        }

        // Business days until deadline
        LocalDate deadline = LocalDate.of(2024, 4, 1);
        long businessDays = 0;
        LocalDate check = meetingDate;
        while (check.isBefore(deadline)) {
            DayOfWeek dow = check.getDayOfWeek();
            if (dow != DayOfWeek.SATURDAY && dow != DayOfWeek.SUNDAY) {
                businessDays++;
            }
            check = check.plusDays(1);
        }
        System.out.println("\nBusiness days until " + deadline + ": " + businessDays);

        // Quarter end date
        int currentQuarter = (meetingDate.getMonthValue() - 1) / 3 + 1;
        LocalDate quarterEnd = LocalDate.of(meetingDate.getYear(), currentQuarter * 3, 1)
            .with(TemporalAdjusters.lastDayOfMonth());
        Period untilQuarterEnd = Period.between(meetingDate, quarterEnd);
        System.out.println("Quarter " + currentQuarter + " ends: " + quarterEnd
            + " (" + untilQuarterEnd.getMonths() + " months, "
            + untilQuarterEnd.getDays() + " days away)");

        // ---- Age and Anniversary ----
        System.out.println("\n--- Age Calculator ---");
        LocalDate birthday = LocalDate.of(1990, Month.JULY, 20);
        LocalDate today = LocalDate.of(2024, 3, 15);

        Period age = Period.between(birthday, today);
        System.out.println("Birthday: " + birthday);
        System.out.println("Age: " + age.getYears() + " years, "
            + age.getMonths() + " months, " + age.getDays() + " days");

        long totalDaysLived = ChronoUnit.DAYS.between(birthday, today);
        System.out.println("Total days lived: " + String.format("%,d", totalDaysLived));

        // Next birthday
        LocalDate nextBirthday = birthday.withYear(today.getYear());
        if (nextBirthday.isBefore(today) || nextBirthday.isEqual(today)) {
            nextBirthday = nextBirthday.plusYears(1);
        }
        long daysUntilBirthday = ChronoUnit.DAYS.between(today, nextBirthday);
        System.out.println("Next birthday: " + nextBirthday
            + " (" + daysUntilBirthday + " days away)");

        // ---- Summary ----
        System.out.println("\n=== Classes Used ===");
        System.out.println("LocalDate       - date without time");
        System.out.println("LocalTime       - time without date");
        System.out.println("LocalDateTime   - date and time without zone");
        System.out.println("ZonedDateTime   - date, time, and zone");
        System.out.println("Instant         - machine timestamp (UTC)");
        System.out.println("Period          - date-based amount (years/months/days)");
        System.out.println("Duration        - time-based amount (hours/minutes/seconds)");
        System.out.println("ZoneId          - time zone identifier");
        System.out.println("DateTimeFormatter - formatting and parsing");
        System.out.println("TemporalAdjusters - date adjustments (first/last day, next Monday)");
        System.out.println("ChronoUnit      - unit-based calculations");
    }
}

// Sample Output:
// === Event Scheduling System ===
//
// --- Creating Events ---
//
// --- Events in Each Time Zone ---
//
// America/New_York:
//   Team Standup: Mon, Mar 18 2024 at 9:00 AM EDT (0h 30m)
//   Client Demo: Mon, Mar 18 2024 at 10:00 AM EDT (1h 30m)
//   Sprint Planning: Sun, Mar 17 2024 at 9:00 PM EDT (2h 0m)
//
// Europe/London:
//   Team Standup: Mon, Mar 18 2024 at 1:00 PM GMT (0h 30m)
//   Client Demo: Mon, Mar 18 2024 at 2:00 PM GMT (1h 30m)
//   Sprint Planning: Mon, Mar 18 2024 at 1:00 AM GMT (2h 0m)
//
// Asia/Tokyo:
//   Team Standup: Mon, Mar 18 2024 at 10:00 PM JST (0h 30m)
//   Client Demo: Mon, Mar 18 2024 at 11:00 PM JST (1h 30m)
//   Sprint Planning: Mon, Mar 18 2024 at 10:00 AM JST (2h 0m)
//
// Asia/Kolkata:
//   Team Standup: Mon, Mar 18 2024 at 6:30 PM IST (0h 30m)
//   Client Demo: Mon, Mar 18 2024 at 7:30 PM IST (1h 30m)
//   Sprint Planning: Mon, Mar 18 2024 at 6:30 AM IST (2h 0m)
//
// --- Conflict Detection ---
// CONFLICT: Team Standup overlaps with Client Demo
// OK: Team Standup and Sprint Planning do not overlap
// OK: Client Demo and Sprint Planning do not overlap
//
// --- Business days until 2024-04-01: 10
// --- Age: 33 years, 7 months, 24 days
// === Classes Used ===
// LocalDate, LocalTime, ZonedDateTime, Duration, Period, ZoneId,
// DateTimeFormatter, TemporalAdjusters, ChronoUnit

Quick Reference

Task Code
Current date LocalDate.now()
Current time LocalTime.now()
Current date-time LocalDateTime.now()
Current instant Instant.now()
Specific date LocalDate.of(2024, Month.MARCH, 15)
Parse date string LocalDate.parse("2024-03-15")
Format date date.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))
Add days date.plusDays(5)
Subtract months date.minusMonths(3)
Days between dates ChronoUnit.DAYS.between(date1, date2)
Period between dates Period.between(date1, date2)
Duration between times Duration.between(time1, time2)
Compare dates date1.isBefore(date2), isAfter(), isEqual()
First day of month date.with(TemporalAdjusters.firstDayOfMonth())
Next Monday date.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
Convert time zone zdt.withZoneSameInstant(ZoneId.of("Asia/Tokyo"))
Date to Instant oldDate.toInstant()
Instant to Date Date.from(instant)
Leap year check date.isLeapYear()
Day of week date.getDayOfWeek()



Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *