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!