1. Introduction to DateTime API
What is DateTime API?
The DateTime API (introduced in Java 8) provides a comprehensive model for date and time manipulation. It addresses the shortcomings of the old Date and Calendar classes.
Why New DateTime API?
- Immutable and Thread-safe
- Fluent API with clear methods
- Comprehensive date-time features
- Time zone support built-in
- Human-readable and intuitive
Main Packages:
java.time- Core classesjava.time.format- Formatting and parsingjava.time.temporal- Extended operationsjava.time.zone- Time zone support
2. Core Classes Overview
| Class | Description | Example |
|---|---|---|
LocalDate | Date without time | 2024-01-15 |
LocalTime | Time without date | 14:30:00 |
LocalDateTime | Date and time without timezone | 2024-01-15T14:30:00 |
ZonedDateTime | Date and time with timezone | 2024-01-15T14:30:00+05:30 |
Instant | Machine timestamp (epoch) | 1705311000 |
Duration | Time-based amount (hours, minutes, seconds) | PT2H30M |
Period | Date-based amount (years, months, days) | P1Y2M3D |
3. Complete Code Examples
Example 1: LocalDate, LocalTime, LocalDateTime
import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; public class BasicDateTimeExamples { public static void main(String[] args) { System.out.println("=== LocalDate, LocalTime, LocalDateTime ==="); // 1. LocalDate - represents a date (year-month-day) LocalDate currentDate = LocalDate.now(); System.out.println("Current Date: " + currentDate); LocalDate specificDate = LocalDate.of(2024, Month.JANUARY, 15); System.out.println("Specific Date: " + specificDate); LocalDate parsedDate = LocalDate.parse("2024-12-25"); System.out.println("Parsed Date: " + parsedDate); // 2. LocalTime - represents a time (hour-minute-second-nano) LocalTime currentTime = LocalTime.now(); System.out.println("Current Time: " + currentTime); LocalTime specificTime = LocalTime.of(14, 30, 45); System.out.println("Specific Time: " + specificTime); LocalTime parsedTime = LocalTime.parse("08:15:30"); System.out.println("Parsed Time: " + parsedTime); // 3. LocalDateTime - represents both date and time LocalDateTime currentDateTime = LocalDateTime.now(); System.out.println("Current DateTime: " + currentDateTime); LocalDateTime specificDateTime = LocalDateTime.of(2024, Month.JUNE, 15, 10, 30, 45); System.out.println("Specific DateTime: " + specificDateTime); LocalDateTime combinedDateTime = LocalDateTime.of(specificDate, specificTime); System.out.println("Combined DateTime: " + combinedDateTime); // 4. Getting components System.out.println("\n=== Date/Time Components ==="); System.out.println("Year: " + currentDate.getYear()); System.out.println("Month: " + currentDate.getMonth() + " (Value: " + currentDate.getMonthValue() + ")"); System.out.println("Day: " + currentDate.getDayOfMonth()); System.out.println("Day of Week: " + currentDate.getDayOfWeek()); System.out.println("Day of Year: " + currentDate.getDayOfYear()); System.out.println("Hour: " + currentTime.getHour()); System.out.println("Minute: " + currentTime.getMinute()); System.out.println("Second: " + currentTime.getSecond()); // 5. Date/Time arithmetic System.out.println("\n=== Date/Time Arithmetic ==="); LocalDate tomorrow = currentDate.plusDays(1); System.out.println("Tomorrow: " + tomorrow); LocalDate nextWeek = currentDate.plusWeeks(1); System.out.println("Next Week: " + nextWeek); LocalDate nextMonth = currentDate.plusMonths(1); System.out.println("Next Month: " + nextMonth); LocalDate previousYear = currentDate.minusYears(1); System.out.println("Previous Year: " + previousYear); LocalTime nextHour = currentTime.plusHours(1); System.out.println("Next Hour: " + nextHour); // 6. Comparisons System.out.println("\n=== Comparisons ==="); System.out.println("Is today after specific date? " + currentDate.isAfter(specificDate)); System.out.println("Is today before specific date? " + currentDate.isBefore(specificDate)); System.out.println("Is today equal to specific date? " + currentDate.isEqual(specificDate)); // 7. Temporal Units System.out.println("\n=== Temporal Units ==="); long daysBetween = ChronoUnit.DAYS.between(specificDate, currentDate); System.out.println("Days between: " + daysBetween); long hoursBetween = ChronoUnit.HOURS.between(specificTime, currentTime); System.out.println("Hours between: " + hoursBetween); } } Example 2: ZonedDateTime and Time Zones
import java.time.*; import java.util.Set; public class TimeZoneExamples { public static void main(String[] args) { System.out.println("=== ZonedDateTime and Time Zones ==="); // 1. Get available time zones Set<String> allZones = ZoneId.getAvailableZoneIds(); System.out.println("Total time zones: " + allZones.size()); System.out.println("Some common zones:"); allZones.stream() .filter(zone -> zone.contains("America") || zone.contains("Europe") || zone.contains("Asia")) .sorted() .limit(10) .forEach(System.out::println); // 2. Create ZonedDateTime instances ZonedDateTime currentZoned = ZonedDateTime.now(); System.out.println("\nCurrent Zoned DateTime: " + currentZoned); ZoneId newYorkZone = ZoneId.of("America/New_York"); ZonedDateTime newYorkTime = ZonedDateTime.now(newYorkZone); System.out.println("New York Time: " + newYorkTime); ZoneId tokyoZone = ZoneId.of("Asia/Tokyo"); ZonedDateTime tokyoTime = ZonedDateTime.now(tokyoZone); System.out.println("Tokyo Time: " + tokyoTime); // 3. Convert between time zones ZonedDateTime convertedTime = newYorkTime.withZoneSameInstant(tokyoZone); System.out.println("New York time in Tokyo: " + convertedTime); // 4. Create specific zoned datetime ZonedDateTime meetingTime = ZonedDateTime.of( LocalDateTime.of(2024, 6, 15, 14, 30), ZoneId.of("Europe/London") ); System.out.println("Meeting in London: " + meetingTime); ZonedDateTime meetingInIndia = meetingTime.withZoneSameInstant(ZoneId.of("Asia/Kolkata")); System.out.println("Meeting in India: " + meetingInIndia); // 5. ZoneOffset ZoneOffset offset = ZoneOffset.of("+05:30"); OffsetDateTime offsetDateTime = OffsetDateTime.now(offset); System.out.println("Offset DateTime: " + offsetDateTime); // 6. Daylight Saving Time example ZoneId londonZone = ZoneId.of("Europe/London"); ZonedDateTime beforeDST = ZonedDateTime.of(2024, 3, 30, 12, 0, 0, 0, londonZone); ZonedDateTime afterDST = beforeDST.plusDays(7); System.out.println("\n=== Daylight Saving Time ==="); System.out.println("Before DST: " + beforeDST); System.out.println("After DST: " + afterDST); System.out.println("Difference: " + Duration.between(beforeDST, afterDST).toHours() + " hours"); } } Example 3: Instant and Duration
import java.time.*; import java.util.concurrent.TimeUnit; public class InstantDurationExamples { public static void main(String[] args) throws InterruptedException { System.out.println("=== Instant and Duration ==="); // 1. Instant - machine readable timestamp Instant start = Instant.now(); System.out.println("Current Instant: " + start); System.out.println("Epoch Seconds: " + start.getEpochSecond()); System.out.println("Epoch Milli: " + start.toEpochMilli()); // Simulate some processing TimeUnit.SECONDS.sleep(2); Instant end = Instant.now(); System.out.println("End Instant: " + end); // 2. Duration - time-based amount between two instants Duration duration = Duration.between(start, end); System.out.println("\n=== Duration ==="); System.out.println("Duration: " + duration); System.out.println("Seconds: " + duration.getSeconds()); System.out.println("Millis: " + duration.toMillis()); System.out.println("Minutes: " + duration.toMinutes()); System.out.println("Nanos: " + duration.getNano()); // 3. Creating durations Duration twoHours = Duration.ofHours(2); System.out.println("Two hours: " + twoHours); Duration thirtyMinutes = Duration.ofMinutes(30); System.out.println("Thirty minutes: " + thirtyMinutes); Duration combined = twoHours.plus(thirtyMinutes); System.out.println("Combined: " + combined); System.out.println("Total minutes: " + combined.toMinutes()); // 4. Duration arithmetic Duration halfDuration = duration.dividedBy(2); System.out.println("Half duration: " + halfDuration); // 5. Using Duration with other types LocalTime startTime = LocalTime.of(9, 0); LocalTime endTime = LocalTime.of(17, 30); Duration workDuration = Duration.between(startTime, endTime); System.out.println("Work duration: " + workDuration); System.out.println("Work hours: " + workDuration.toHours()); // 6. Instant arithmetic Instant tomorrow = Instant.now().plus(Duration.ofDays(1)); System.out.println("Tomorrow: " + tomorrow); Instant yesterday = Instant.now().minus(Duration.ofDays(1)); System.out.println("Yesterday: " + yesterday); // 7. Convert between Instant and LocalDateTime LocalDateTime localFromInstant = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); System.out.println("LocalDateTime from Instant: " + localFromInstant); Instant instantFromLocal = localFromInstant.toInstant(ZoneOffset.UTC); System.out.println("Instant from LocalDateTime: " + instantFromLocal); } } Example 4: Period and Date Arithmetic
import java.time.*; import java.time.temporal.ChronoUnit; public class PeriodExamples { public static void main(String[] args) { System.out.println("=== Period and Date Arithmetic ==="); // 1. Period - date-based amount (years, months, days) LocalDate birthDate = LocalDate.of(1990, Month.MAY, 15); LocalDate currentDate = LocalDate.now(); Period age = Period.between(birthDate, currentDate); System.out.println("Age: " + age.getYears() + " years, " + age.getMonths() + " months, " + age.getDays() + " days"); // 2. Creating periods Period oneYear = Period.ofYears(1); System.out.println("One year: " + oneYear); Period sixMonths = Period.ofMonths(6); System.out.println("Six months: " + sixMonths); Period complexPeriod = Period.of(1, 6, 15); System.out.println("Complex period: " + complexPeriod); // 3. Period arithmetic LocalDate futureDate = currentDate.plus(complexPeriod); System.out.println("Current date: " + currentDate); System.out.println("Future date: " + futureDate); LocalDate pastDate = currentDate.minus(oneYear); System.out.println("Past date: " + pastDate); // 4. ChronoUnit for precise calculations long totalMonths = ChronoUnit.MONTHS.between(birthDate, currentDate); System.out.println("Total months lived: " + totalMonths); long totalWeeks = ChronoUnit.WEEKS.between(birthDate, currentDate); System.out.println("Total weeks lived: " + totalWeeks); long totalDays = ChronoUnit.DAYS.between(birthDate, currentDate); System.out.println("Total days lived: " + totalDays); // 5. Working with specific dates LocalDate projectStart = LocalDate.of(2024, 1, 1); LocalDate projectEnd = LocalDate.of(2024, 12, 31); Period projectDuration = Period.between(projectStart, projectEnd); System.out.println("Project duration: " + projectDuration); // 6. Birthday calculation LocalDate nextBirthday = birthDate.withYear(currentDate.getYear()); if (nextBirthday.isBefore(currentDate) || nextBirthday.isEqual(currentDate)) { nextBirthday = nextBirthday.plusYears(1); } Period untilNextBirthday = Period.between(currentDate, nextBirthday); System.out.println("Time until next birthday: " + untilNextBirthday.getMonths() + " months, " + untilNextBirthday.getDays() + " days"); // 7. Leap year example LocalDate leapYearDate = LocalDate.of(2024, 2, 28); LocalDate nextDay = leapYearDate.plusDays(1); System.out.println("Leap year date: " + leapYearDate); System.out.println("Next day: " + nextDay); System.out.println("Is leap year? " + leapYearDate.isLeapYear()); } } Example 5: Formatting and Parsing
import java.time.*; import java.time.format.*; import java.util.Locale; public class FormattingExamples { public static void main(String[] args) { System.out.println("=== Formatting and Parsing ==="); LocalDateTime currentDateTime = LocalDateTime.now(); // 1. Built-in formatters System.out.println("ISO_DATE: " + currentDateTime.format(DateTimeFormatter.ISO_DATE)); System.out.println("ISO_DATE_TIME: " + currentDateTime.format(DateTimeFormatter.ISO_DATE_TIME)); System.out.println("ISO_TIME: " + currentDateTime.format(DateTimeFormatter.ISO_TIME)); // 2. Custom patterns DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); System.out.println("Custom format: " + currentDateTime.format(customFormatter)); DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy 'at' hh:mm a"); System.out.println("Full format: " + currentDateTime.format(fullFormatter)); // 3. Localized formatting DateTimeFormatter germanFormatter = DateTimeFormatter.ofPattern("dd. MMMM yyyy", Locale.GERMAN); System.out.println("German format: " + currentDateTime.format(germanFormatter)); DateTimeFormatter japaneseFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日", Locale.JAPANESE); System.out.println("Japanese format: " + currentDateTime.format(japaneseFormatter)); // 4. Parsing strings to dates String dateString = "2024-12-25"; LocalDate christmas = LocalDate.parse(dateString); System.out.println("Parsed date: " + christmas); String dateTimeString = "2024-06-15T14:30:45"; LocalDateTime parsedDateTime = LocalDateTime.parse(dateTimeString); System.out.println("Parsed datetime: " + parsedDateTime); // 5. Parsing with custom formats String customDateString = "15/06/2024 14:30:45"; DateTimeFormatter parser = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); LocalDateTime parsedCustom = LocalDateTime.parse(customDateString, parser); System.out.println("Parsed custom: " + parsedCustom); // 6. Formatting ZonedDateTime ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("America/New_York")); DateTimeFormatter zonedFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); System.out.println("Zoned format: " + zoned.format(zonedFormatter)); // 7. Formatting with TextStyle DateTimeFormatter mediumFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); System.out.println("Medium format: " + currentDateTime.format(mediumFormatter)); DateTimeFormatter shortFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT); System.out.println("Short date: " + currentDateTime.format(shortFormatter)); // 8. Handling different input formats String[] possibleFormats = { "yyyy-MM-dd", "dd/MM/yyyy", "MM/dd/yyyy", "yyyyMMdd" }; String inputDate = "25/12/2024"; LocalDate parsedDate = null; for (String format : possibleFormats) { try { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); parsedDate = LocalDate.parse(inputDate, formatter); break; } catch (DateTimeParseException e) { // Try next format } } if (parsedDate != null) { System.out.println("Successfully parsed: " + parsedDate); } } } Example 6: Real-World Application - Employee Management
import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; class Employee { private String name; private LocalDate joinDate; private LocalTime shiftStart; private LocalTime shiftEnd; private ZoneId timeZone; public Employee(String name, LocalDate joinDate, LocalTime shiftStart, LocalTime shiftEnd, ZoneId timeZone) { this.name = name; this.joinDate = joinDate; this.shiftStart = shiftStart; this.shiftEnd = shiftEnd; this.timeZone = timeZone; } public Duration getShiftDuration() { return Duration.between(shiftStart, shiftEnd); } public Period getEmploymentPeriod() { return Period.between(joinDate, LocalDate.now()); } public boolean isWorkingNow() { LocalTime now = LocalTime.now(timeZone); return !now.isBefore(shiftStart) && now.isBefore(shiftEnd); } public ZonedDateTime getShiftStartToday() { return ZonedDateTime.of(LocalDate.now(), shiftStart, timeZone); } public ZonedDateTime getShiftEndToday() { return ZonedDateTime.of(LocalDate.now(), shiftEnd, timeZone); } // Getters public String getName() { return name; } public LocalDate getJoinDate() { return joinDate; } public LocalTime getShiftStart() { return shiftStart; } public LocalTime getShiftEnd() { return shiftEnd; } public ZoneId getTimeZone() { return timeZone; } } public class EmployeeManagementSystem { public static void main(String[] args) { System.out.println("=== Employee Management System ==="); // Create employees in different time zones List<Employee> employees = Arrays.asList( new Employee("John Doe", LocalDate.of(2020, Month.JANUARY, 15), LocalTime.of(9, 0), LocalTime.of(17, 0), ZoneId.of("America/New_York")), new Employee("Alice Smith", LocalDate.of(2021, Month.MARCH, 10), LocalTime.of(8, 0), LocalTime.of(16, 30), ZoneId.of("Europe/London")), new Employee("Bob Johnson", LocalDate.of(2019, Month.NOVEMBER, 5), LocalTime.of(10, 0), LocalTime.of(19, 0), ZoneId.of("Asia/Kolkata")) ); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); // Analyze each employee for (Employee emp : employees) { System.out.println("\n--- " + emp.getName() + " ---"); System.out.println("Join Date: " + emp.getJoinDate()); System.out.println("Employment Period: " + emp.getEmploymentPeriod().getYears() + " years, " + emp.getEmploymentPeriod().getMonths() + " months"); System.out.println("Shift: " + emp.getShiftStart() + " - " + emp.getShiftEnd()); System.out.println("Shift Duration: " + emp.getShiftDuration().toHours() + " hours"); System.out.println("Time Zone: " + emp.getTimeZone()); System.out.println("Shift Start Today: " + emp.getShiftStartToday().format(formatter)); System.out.println("Shift End Today: " + emp.getShiftEndToday().format(formatter)); System.out.println("Is Working Now: " + emp.isWorkingNow()); // Convert to local time for meeting ZonedDateTime meetingTime = ZonedDateTime.of( LocalDateTime.of(2024, 6, 15, 14, 0), ZoneId.of("America/New_York") ); ZonedDateTime employeeMeetingTime = meetingTime.withZoneSameInstant(emp.getTimeZone()); System.out.println("Meeting time for employee: " + employeeMeetingTime.format(formatter)); } // Company-wide statistics System.out.println("\n=== Company Statistics ==="); // Average employment duration double avgEmploymentYears = employees.stream() .mapToLong(emp -> ChronoUnit.YEARS.between(emp.getJoinDate(), LocalDate.now())) .average() .orElse(0); System.out.println("Average employment: " + avgEmploymentYears + " years"); // Find employees with longest shift Employee longestShiftEmp = employees.stream() .max(Comparator.comparing(emp -> emp.getShiftDuration())) .orElse(null); System.out.println("Longest shift: " + longestShiftEmp.getName() + " (" + longestShiftEmp.getShiftDuration().toHours() + " hours)"); // Employees working now List<Employee> workingNow = employees.stream() .filter(Employee::isWorkingNow) .toList(); System.out.println("Employees working now: " + workingNow.size()); workingNow.forEach(emp -> System.out.println(" - " + emp.getName())); } } Example 7: Date/Time Utilities and Helper Methods
import java.time.*; import java.time.DayOfWeek; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.List; public class DateTimeUtilities { // 1. Calculate age in years public static int calculateAge(LocalDate birthDate) { return Period.between(birthDate, LocalDate.now()).getYears(); } // 2. Check if date is weekend public static boolean isWeekend(LocalDate date) { DayOfWeek day = date.getDayOfWeek(); return day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY; } // 3. Get next working day (skip weekends) public static LocalDate getNextWorkingDay(LocalDate date) { LocalDate nextDay = date.plusDays(1); while (isWeekend(nextDay)) { nextDay = nextDay.plusDays(1); } return nextDay; } // 4. Calculate business days between two dates public static long getBusinessDaysBetween(LocalDate start, LocalDate end) { return start.datesUntil(end) .filter(date -> !isWeekend(date)) .count(); } // 5. Get all dates in a range public static List<LocalDate> getDatesInRange(LocalDate start, LocalDate end) { List<LocalDate> dates = new ArrayList<>(); LocalDate current = start; while (!current.isAfter(end)) { dates.add(current); current = current.plusDays(1); } return dates; } // 6. Get first/last day of month public static LocalDate getFirstDayOfMonth(LocalDate date) { return date.with(TemporalAdjusters.firstDayOfMonth()); } public static LocalDate getLastDayOfMonth(LocalDate date) { return date.with(TemporalAdjusters.lastDayOfMonth()); } // 7. Get next specific day of week public static LocalDate getNextDayOfWeek(LocalDate date, DayOfWeek dayOfWeek) { return date.with(TemporalAdjusters.next(dayOfWeek)); } // 8. Check if time is within business hours public static boolean isBusinessHours(LocalTime time) { LocalTime businessStart = LocalTime.of(9, 0); LocalTime businessEnd = LocalTime.of(17, 0); return !time.isBefore(businessStart) && time.isBefore(businessEnd); } // 9. Calculate time until next business hour public static Duration timeUntilBusinessHours() { LocalTime now = LocalTime.now(); LocalTime businessStart = LocalTime.of(9, 0); if (now.isBefore(businessStart)) { return Duration.between(now, businessStart); } else { return Duration.ZERO; } } public static void main(String[] args) { System.out.println("=== DateTime Utilities ==="); LocalDate birthDate = LocalDate.of(1990, 5, 15); LocalDate today = LocalDate.now(); LocalDate nextMonth = today.plusMonths(1); // Test utility methods System.out.println("Age: " + calculateAge(birthDate) + " years"); System.out.println("Is weekend? " + isWeekend(today)); System.out.println("Next working day: " + getNextWorkingDay(today)); System.out.println("Business days this month: " + getBusinessDaysBetween(getFirstDayOfMonth(today), getLastDayOfMonth(today))); System.out.println("First day of month: " + getFirstDayOfMonth(today)); System.out.println("Last day of month: " + getLastDayOfMonth(today)); System.out.println("Next Monday: " + getNextDayOfWeek(today, DayOfWeek.MONDAY)); System.out.println("Is business hours? " + isBusinessHours(LocalTime.now())); System.out.println("Time until business hours: " + timeUntilBusinessHours()); // Generate report for next month System.out.println("\n=== Next Month Calendar ==="); List<LocalDate> nextMonthDates = getDatesInRange( getFirstDayOfMonth(nextMonth), getLastDayOfMonth(nextMonth) ); nextMonthDates.forEach(date -> { String weekendMarker = isWeekend(date) ? " (Weekend)" : ""; System.out.println(date.getDayOfWeek() + " " + date + weekendMarker); }); // Working with TemporalAdjusters System.out.println("\n=== Temporal Adjusters ==="); System.out.println("First Monday of next month: " + nextMonth.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); System.out.println("Last Friday of this month: " + today.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY))); System.out.println("Next or same Monday: " + today.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY))); } } Example 8: Time Zone Conversion Utility
import java.time.*; import java.time.format.DateTimeFormatter; import java.util.*; class TimeZoneConverter { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); public static ZonedDateTime convert(ZonedDateTime sourceDateTime, ZoneId targetZone) { return sourceDateTime.withZoneSameInstant(targetZone); } public static Map<String, ZonedDateTime> getWorldTimes(ZonedDateTime dateTime) { String[] majorCities = { "America/New_York", "Europe/London", "Europe/Paris", "Asia/Tokyo", "Asia/Kolkata", "Australia/Sydney", "Africa/Johannesburg", "America/Los_Angeles" }; Map<String, ZonedDateTime> worldTimes = new LinkedHashMap<>(); for (String city : majorCities) { ZoneId zone = ZoneId.of(city); worldTimes.put(zone.getId(), convert(dateTime, zone)); } return worldTimes; } public static void printWorldClocks() { ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); System.out.println("=== World Clocks (UTC Reference: " + now.format(FORMATTER) + ") ==="); Map<String, ZonedDateTime> worldTimes = getWorldTimes(now); worldTimes.forEach((city, time) -> { String cityName = city.split("/")[1].replace("_", " "); System.out.printf("%-20s: %s\n", cityName, time.format(FORMATTER)); }); } public static void scheduleMeeting(LocalDateTime localMeetingTime, ZoneId localZone, String... participantZones) { ZonedDateTime meetingTime = ZonedDateTime.of(localMeetingTime, localZone); System.out.println("\n=== Meeting Schedule ==="); System.out.println("Local Meeting Time: " + meetingTime.format(FORMATTER)); System.out.println("\nParticipant Times:"); for (String zone : participantZones) { ZoneId participantZone = ZoneId.of(zone); ZonedDateTime participantTime = convert(meetingTime, participantZone); String cityName = zone.split("/")[1].replace("_", " "); System.out.printf("%-20s: %s\n", cityName, participantTime.format(FORMATTER)); } } } public class TimeZoneExamplesAdvanced { public static void main(String[] args) { System.out.println("=== Advanced Time Zone Examples ==="); // 1. World clocks TimeZoneConverter.printWorldClocks(); // 2. Schedule a meeting LocalDateTime meetingTime = LocalDateTime.of(2024, 6, 15, 14, 0); ZoneId organizerZone = ZoneId.of("America/New_York"); String[] participants = { "Europe/London", "Europe/Paris", "Asia/Kolkata", "Asia/Tokyo", "America/Los_Angeles" }; TimeZoneConverter.scheduleMeeting(meetingTime, organizerZone, participants); // 3. Daylight Saving Time transitions System.out.println("\n=== Daylight Saving Time Analysis ==="); ZoneId londonZone = ZoneId.of("Europe/London"); // DST transition in 2024 (March 31st) ZonedDateTime beforeDST = ZonedDateTime.of( LocalDateTime.of(2024, 3, 31, 0, 30), londonZone); System.out.println("Before DST: " + beforeDST.format(TimeZoneConverter.FORMATTER)); // Add 1 hour - should jump to 2:30 due to DST ZonedDateTime afterDST = beforeDST.plusHours(1); System.out.println("After adding 1 hour: " + afterDST.format(TimeZoneConverter.FORMATTER)); // 4. Calculate duration across DST boundary Duration duration = Duration.between(beforeDST, afterDST); System.out.println("Actual duration: " + duration.toMinutes() + " minutes"); // 5. Working with fixed offsets ZoneOffset fixedOffset = ZoneOffset.of("+08:00"); OffsetDateTime fixedTime = OffsetDateTime.now(fixedOffset); System.out.println("\nFixed offset time: " + fixedTime.format(TimeZoneConverter.FORMATTER)); } } 9. Best Practices and Common Patterns
import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; public class BestPractices { // 1. Use immutable DateTime objects public static LocalDate addDaysToDate(LocalDate date, long days) { return date.plusDays(days); // Returns new instance } // 2. Use proper method names for clarity public static boolean isDateInFuture(LocalDate date) { return date.isAfter(LocalDate.now()); } // 3. Handle time zones explicitly public static ZonedDateTime convertToUTC(ZonedDateTime dateTime) { return dateTime.withZoneSameInstant(ZoneOffset.UTC); } // 4. Use Duration for time-based calculations public static boolean isWithinWorkingHours(LocalTime time, Duration tolerance) { LocalTime workStart = LocalTime.of(9, 0); LocalTime workEnd = LocalTime.of(17, 0); return !time.isBefore(workStart.minus(tolerance)) && !time.isAfter(workEnd.plus(tolerance)); } // 5. Use Period for date-based calculations public static boolean isWithinWarranty(LocalDate purchaseDate, Period warrantyPeriod) { LocalDate warrantyEnd = purchaseDate.plus(warrantyPeriod); return !LocalDate.now().isAfter(warrantyEnd); } // 6. Validate date ranges public static void validateDateRange(LocalDate start, LocalDate end) { if (start.isAfter(end)) { throw new IllegalArgumentException("Start date cannot be after end date"); } if (start.isBefore(LocalDate.of(1900, 1, 1))) { throw new IllegalArgumentException("Dates before 1900 are not supported"); } } // 7. Use constants for common formats private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE; private static final DateTimeFormatter DISPLAY_FORMATTER = DateTimeFormatter.ofPattern("MMM dd, yyyy"); public static String formatForDisplay(LocalDate date) { return date.format(DISPLAY_FORMATTER); } public static String formatForStorage(LocalDate date) { return date.format(ISO_FORMATTER); } public static void main(String[] args) { System.out.println("=== Best Practices Examples ==="); // Example usage LocalDate today = LocalDate.now(); LocalDate futureDate = addDaysToDate(today, 30); System.out.println("Today: " + formatForDisplay(today)); System.out.println("Future date: " + formatForDisplay(futureDate)); System.out.println("Is future? " + isDateInFuture(futureDate)); // Warranty check LocalDate purchaseDate = LocalDate.of(2023, 1, 15); Period twoYearWarranty = Period.ofYears(2); System.out.println("Under warranty? " + isWithinWarranty(purchaseDate, twoYearWarranty)); // Working hours with tolerance LocalTime currentTime = LocalTime.now(); Duration fifteenMinTolerance = Duration.ofMinutes(15); System.out.println("Within working hours with tolerance? " + isWithinWorkingHours(currentTime, fifteenMinTolerance)); // Date range validation try { validateDateRange(LocalDate.of(2024, 1, 1), LocalDate.of(2023, 1, 1)); } catch (IllegalArgumentException e) { System.out.println("Validation error: " + e.getMessage()); } // Storage and display formats System.out.println("Storage format: " + formatForStorage(today)); System.out.println("Display format: " + formatForDisplay(today)); } } 10. Conclusion
Key Takeaways:
- Immutability: All DateTime objects are immutable and thread-safe
- Clarity: Method names clearly express their purpose
- Comprehensive: Covers all date-time use cases
- Time Zone Ready: Built-in time zone support
- Fluent API: Easy to chain operations
When to Use Which Class:
- LocalDate: When you need only date (birthdays, holidays)
- LocalTime: When you need only time (store hours, meetings)
- LocalDateTime: When you need both but no timezone (appointments)
- ZonedDateTime: When timezone matters (international meetings)
- Instant: For machine timestamps (logging, events)
- Duration: For time-based amounts (2 hours, 30 minutes)
- Period: For date-based amounts (1 year, 2 months)
Best Practices:
- ✅ Use
LocalDatefor birthdays instead ofLocalDateTime - ✅ Always specify timezone for international applications
- ✅ Use
Durationfor short periods,Periodfor longer spans - ✅ Prefer
plus/minusmethods over manual calculations - ✅ Use
DateTimeFormatterfor consistent formatting
Common Pitfalls to Avoid:
- ❌ Using old
DateandCalendarclasses - ❌ Ignoring time zones in global applications
- ❌ Not handling DST transitions
- ❌ Using strings for date calculations
- ❌ Forgetting about immutability
Final Thoughts:
The Java DateTime API is one of the most significant improvements in Java 8. It provides a clean, intuitive, and comprehensive way to work with dates and times. Unlike the old Date/Calendar API, it's designed with modern development practices in mind.
Master the DateTime API to write cleaner, more maintainable, and timezone-aware applications!