Working with dates in Java used to be a nightmare. The old java.util.Date and Calendar classes were mutable (not thread-safe), had confusing month numbering (January was 0!), and lacked clarity for time zones.
Java 8 introduced the java.time package (based on Joda-Time), which is immutable, thread-safe, and very intuitive.
Meet the Core Classes
1. LocalDate: Just the Date
No time, no time zone. Perfect for birthdays or holidays.
LocalDate today = LocalDate.now();
LocalDate christmas = LocalDate.of(2025, 12, 25);
2. LocalTime: Just the Time
No date, no time zone. Perfect for a daily alarm or business hours.
LocalTime now = LocalTime.now();
LocalTime closingTime = LocalTime.of(18, 0); // 6:00 PM
3. LocalDateTime: Date + Time
Still no time zone.
LocalDateTime meeting = LocalDateTime.of(2025, 11, 21, 14, 30);
4. ZonedDateTime: The Full Picture
Date + Time + Time Zone. Use this for global applications.
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
The Power of Immutability
One of the best things about the new API is that all objects are immutable. When you modify a date, you get a new object back. This makes it perfectly safe to use in multi-threaded environments.
LocalDate start = LocalDate.of(2025, 1, 1);
LocalDate end = start.plusMonths(6).plusDays(15);
// 'start' is still Jan 1st! No accidental changes.
Working with Periods and Durations
How much time has passed? Java 8 gives us two ways to measure:
- Period: For date-based time (Years, Months, Days).
- Duration: For time-based time (Hours, Minutes, Seconds).
// Calculating age
LocalDate birthDate = LocalDate.of(1995, 5, 15);
Period age = Period.between(birthDate, LocalDate.now());
System.out.println("You are " + age.getYears() + " years old.");
// Calculating task time
Instant startTime = Instant.now();
performHeavyTask();
Duration elapsed = Duration.between(startTime, Instant.now());
System.out.println("Task took " + elapsed.toMillis() + " ms.");
Formatting and Parsing
Converting dates to strings (and vice versa) is now much safer with DateTimeFormatter.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
// Date to String
String formatted = today.format(formatter);
// String to Date
LocalDate parsed = LocalDate.parse("15-05-1995", formatter);
Conclusion
The java.time API is a massive improvement over the old ways of handling time. It prevents many common bugs by being immutable and provides a wealth of utility methods that make date manipulation a breeze. If you are still using java.util.Date, it’s time to upgrade!