The Joda-Time library, introduced in Java 8, is a popular Java library for handling date and time operations. It provides a more comprehensive and user-friendly API compared to the old java.util.Date and java.util.Calendar classes.
Joda-Time offers a wide range of features for working with date and time, including better handling of time zones, durations, intervals, and formatting.
History
The date/time API before Java 8, has multiple design problems such as java.util.Date and SimpleDateFormatter classes are not thread-safe.
The date class doesn’t represent actual date instead it specifies an instant in time with millisecond precision.

The problems with the java.util.Date are tried to be handled by introducing new methods deprecating few of the methods inside it and with an alternative class java.util.Calendar. But Calendar class also has similar problems and design flaws that lead to error prone code.
With all these kinds of limitations that java.util.Date and Calendar has, the developers started using third party date and time libraries such as Joda Time API, since it is creating more and more features and more thread-safe classes and interfaces.
Joda Date & Time API
Oracle decided to provide high quality date and time support in the native Java API. As a result, Java 8 integrates many of the Joda time features in the java.time package.
https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html
The new java.time.* package has the below important classes to deal with Date & Time :
- java.time.LocalDate
- java.time.LocalDateTime
- java.time.LocalTime
- java.time.Instant
- java.time.Duration
- java.time.Period
Along with this Joda date and time API will make developer life easy when you are dealing with different time zones.
LocalDate class – java.time.LocalDate
The LocalDate class in Java is part of the java.time package, which was introduced in Java 8 as part of the new Date and Time API (often referred to as the Joda-Time-inspired API). The LocalDate class represents a date (year, month, day) without a time-zone or time-of-day.
Here are some key points and examples of how to use LocalDate:
Key Features
- Immutability:
LocalDateis immutable, meaning once it is created, its values cannot be changed. This makes it thread-safe. - Date Representation: It represents a date, such as 2024-08-26, without a time component.
- No Timezone: It does not include time-of-day information or timezone information, making it suitable for representing dates like birthdays or holidays.
Commonly Used Methods:
Creation:
LocalDate.now(): Gets the current date from the system clock.LocalDate.of(int year, int month, int dayOfMonth): Creates an instance with the specified year, month, and day.LocalDate.parse(CharSequence text): Parses a string in the formatYYYY-MM-DDto aLocalDate.
LocalDate today = LocalDate.now(); // Current date
LocalDate date = LocalDate.of(2024, 8, 26); // 26th August 2024
LocalDate parsedDate = LocalDate.parse("2024-08-26"); // Parses to 26th August 2024
Getting Date Parts:
int getYear(): Returns the year.int getMonthValue(): Returns the month (from 1 to 12).int getDayOfMonth(): Returns the day of the month.
int year = today.getYear(); // 2024
int month = today.getMonthValue(); // 8
int day = today.getDayOfMonth(); // 26
Date Manipulation:
LocalDate plusDays(long daysToAdd): Adds the specified number of days to this date.LocalDate minusMonths(long monthsToSubtract): Subtracts the specified number of months from this date.LocalDate withYear(int year): Returns a copy of this date with the year altered.
LocalDate tomorrow = today.plusDays(1); // Adds one day
LocalDate previousMonth = today.minusMonths(1); // Subtracts one month
LocalDate nextYearSameDay = today.withYear(2025); // Changes the year to 2025
Comparisons:
boolean isBefore(LocalDate otherDate): Checks if this date is before the specified date.boolean isAfter(LocalDate otherDate): Checks if this date is after the specified date.boolean isEqual(LocalDate otherDate): Checks if this date is equal to the specified date.
boolean isBefore = today.isBefore(LocalDate.of(2024, 12, 31)); // true
boolean isAfter = today.isAfter(LocalDate.of(2024, 1, 1)); // true
Miscellaneous:
DayOfWeek getDayOfWeek(): Returns the day of the week (e.g., MONDAY, TUESDAY).int lengthOfMonth(): Returns the length of the month in days.
DayOfWeek dayOfWeek = today.getDayOfWeek(); // MONDAY
int lengthOfMonth = today.lengthOfMonth(); // 31 (for August)
Example
import java.time.LocalDate;
public class LocalDateExample {
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println("Today's date: " + today);
LocalDate specificDate = LocalDate.of(2024, 8, 26);
System.out.println("Specific date: " + specificDate);
LocalDate tomorrow = today.plusDays(1);
System.out.println("Tomorrow's date: " + tomorrow);
boolean isLeapYear = specificDate.isLeapYear();
System.out.println("Is the year a leap year? " + isLeapYear);
}
}
Output :
Today's date: 2024-08-26
Specific date: 2024-08-26
Tomorrow's date: 2024-08-27
Is the year a leap year? true
The LocalDate class is very useful for handling dates without the complexity of time zones or times of the day.
LocalTime class
The LocalTime class in Java is part of the java.time package, which was introduced in Java 8 as part of the Date and Time API (inspired by Joda-Time). The LocalTime class represents a time of day (hours, minutes, seconds, and nanoseconds) without any date or time zone information.
Key Features:
- Immutability:
LocalTimeinstances are immutable and thread-safe. - Time Representation: It represents a specific time of day, such as 14:30:00, without reference to a date or time zone.
- Precision: It can represent time down to the nanosecond precision.
Commonly Used Methods:
Creation:
LocalTime.now(): Gets the current time from the system clock.LocalTime.of(int hour, int minute): Creates an instance with the specified hour and minute.LocalTime.of(int hour, int minute, int second): Creates an instance with the specified hour, minute, and second.LocalTime.of(int hour, int minute, int second, int nanoOfSecond): Creates an instance with hour, minute, second, and nanosecond precision.LocalTime.parse(CharSequence text): Parses a string in the formatHH:mm:ssorHH:mmto aLocalTime.
LocalTime now = LocalTime.now(); // Current time
LocalTime specificTime = LocalTime.of(14, 30); // 14:30 (2:30 PM)
LocalTime parsedTime = LocalTime.parse("14:30:00"); // Parses to 14:30:00 (2:30 PM)
Getting Time Parts:
int getHour(): Returns the hour of the day.int getMinute(): Returns the minute of the hour.int getSecond(): Returns the second of the minute.int getNano(): Returns the nanosecond part of the second.
int hour = now.getHour(); // e.g., 14
int minute = now.getMinute(); // e.g., 30
int second = now.getSecond(); // e.g., 45
int nano = now.getNano(); // e.g., 123456789
Time Manipulation:
LocalTime plusHours(long hoursToAdd): Adds the specified number of hours to this time.LocalTime minusMinutes(long minutesToSubtract): Subtracts the specified number of minutes from this time.LocalTime withHour(int hour): Returns a copy of this time with the hour altered.
LocalTime later = now.plusHours(2); // Adds two hours
LocalTime earlier = now.minusMinutes(30); // Subtracts 30 minutes
LocalTime updatedTime = now.withHour(16); // Changes the hour to 16 (4 PM)
Comparisons:
boolean isBefore(LocalTime otherTime): Checks if this time is before the specified time.boolean isAfter(LocalTime otherTime): Checks if this time is after the specified time.boolean equals(Object obj): Checks if this time is equal to the specified time.
boolean isBefore = now.isBefore(LocalTime.of(16, 0)); // true if current time is before 4 PM
boolean isAfter = now.isAfter(LocalTime.of(12, 0)); // true if current time is after noon
Miscellaneous:
int toSecondOfDay(): Returns the number of seconds since midnight.LocalTime truncatedTo(TemporalUnit unit): Returns a copy of this time truncated to the specified unit (e.g.,ChronoUnit.MINUTESto truncate seconds).
int secondsOfDay = now.toSecondOfDay(); // e.g., 52200 seconds since midnight (14:30:00)
LocalTime truncated = now.truncatedTo(ChronoUnit.MINUTES); // Truncate to the nearest minute
Example
import java.time.LocalTime;
public class LocalTimeExample {
public static void main(String[] args) {
LocalTime now = LocalTime.now();
System.out.println("Current time: " + now);
LocalTime specificTime = LocalTime.of(14, 30, 45);
System.out.println("Specific time: " + specificTime);
LocalTime inTwoHours = now.plusHours(2);
System.out.println("Time in two hours: " + inTwoHours);
boolean isBefore = specificTime.isBefore(now);
System.out.println("Is the specific time before now? " + isBefore);
}
}
Output :
Current time: 14:30:45.123
Specific time: 14:30:45
Time in two hours: 16:30:45.123
Is the specific time before now? false
The LocalTime class is particularly useful when dealing with times that are independent of any specific date or time zone, such as setting alarms, scheduling tasks, or logging time-related data.
LocalDateTime class
The LocalDateTime class in Java is part of the java.time package, introduced in Java 8 as part of the new Date and Time API (inspired by Joda-Time). The LocalDateTime class represents a date-time without a time zone, combining a LocalDate and a LocalTime into a single instance.
Key Features:
- Immutability:
LocalDateTimeinstances are immutable and thread-safe. - Date and Time Representation: It combines date (year, month, day) and time (hour, minute, second, nanosecond) into one object.
- No Time Zone: Like
LocalDateandLocalTime, it does not include any time zone information.
Commonly Used Methods:
Creation:
LocalDateTime.now(): Gets the current date and time from the system clock.LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute): Creates an instance with the specified date and time.LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second): Creates an instance with the specified date, time, and second.LocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond): Creates an instance with date, time, second, and nanosecond precision.LocalDateTime.of(LocalDate date, LocalTime time): Combines aLocalDateandLocalTimeinto aLocalDateTime.LocalDateTime.parse(CharSequence text): Parses a string in the formatYYYY-MM-DDTHH:MM:SSto aLocalDateTime.
LocalDateTime now = LocalDateTime.now(); // Current date and time
LocalDateTime specificDateTime = LocalDateTime.of(2024, 8, 26, 14, 30); // 26th August 2024, 14:30
LocalDateTime parsedDateTime = LocalDateTime.parse("2024-08-26T14:30:00"); // Parses to 26th August 2024, 14:30:00
Getting Date and Time Parts:
LocalDate toLocalDate(): Extracts the date part as aLocalDate.LocalTime toLocalTime(): Extracts the time part as aLocalTime.int getYear(),int getMonthValue(),int getDayOfMonth(), etc.: Gets the respective parts of the date.int getHour(),int getMinute(),int getSecond(), etc.: Gets the respective parts of the time.
LocalDate datePart = now.toLocalDate(); // e.g., 2024-08-26
LocalTime timePart = now.toLocalTime(); // e.g., 14:30:45
int year = now.getYear(); // 2024
int hour = now.getHour(); // 14
Date-Time Manipulation:
LocalDateTime plusDays(long daysToAdd): Adds the specified number of days to this date-time.LocalDateTime minusHours(long hoursToSubtract): Subtracts the specified number of hours from this date-time.LocalDateTime withYear(int year): Returns a copy of this date-time with the year altered.
LocalDateTime tomorrow = now.plusDays(1); // Adds one day
LocalDateTime twoHoursEarlier = now.minusHours(2); // Subtracts two hours
LocalDateTime nextYearSameTime = now.withYear(2025); // Changes the year to 2025
Comparisons:
boolean isBefore(LocalDateTime otherDateTime): Checks if this date-time is before the specified date-time.boolean isAfter(LocalDateTime otherDateTime): Checks if this date-time is after the specified date-time.boolean equals(Object obj): Checks if this date-time is equal to the specified date-time.
boolean isBefore = now.isBefore(LocalDateTime.of(2024, 12, 31, 23, 59)); // true
boolean isAfter = now.isAfter(LocalDateTime.of(2024, 1, 1, 0, 0)); // true
Conversion:
ZonedDateTime atZone(ZoneId zone): Converts thisLocalDateTimeto aZonedDateTimeusing the specified time zone.OffsetDateTime atOffset(ZoneOffset offset): Converts thisLocalDateTimeto anOffsetDateTimewith the specified offset from UTC.
ZonedDateTime zonedDateTime = now.atZone(ZoneId.of("America/New_York")); // Converts to ZonedDateTime
OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(-5)); // Converts to OffsetDateTime with -5 hours offset
Example :
import java.time.LocalDateTime;
public class LocalDateTimeExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("Current date and time: " + now);
LocalDateTime specificDateTime = LocalDateTime.of(2024, 8, 26, 14, 30, 0);
System.out.println("Specific date and time: " + specificDateTime);
LocalDateTime inTwoDays = now.plusDays(2);
System.out.println("Date and time in two days: " + inTwoDays);
boolean isBefore = specificDateTime.isBefore(now);
System.out.println("Is the specific date-time before now? " + isBefore);
}
}
Output :
Current date and time: 2024-08-26T14:30:45.123
Specific date and time: 2024-08-26T14:30:00
Date and time in two days: 2024-08-28T14:30:45.123
Is the specific date-time before now? false
The LocalDateTime class is useful when you need to represent both date and time without the complexities of time zones. It is commonly used for logging timestamps, scheduling, and time calculations in applications where time zone considerations are not necessary.
Get Date with Timezone details
To get the current date and time with timezone information in Java, you can use the ZonedDateTime or OffsetDateTime classes from the java.time package. These classes allow you to handle date and time along with timezone information or a fixed UTC offset.
Using ZonedDateTime:
ZonedDateTime represents a date and time with a timezone, which includes the information about the time zone’s rules, such as daylight saving time adjustments.
import java.time.ZonedDateTime;
import java.time.ZoneId;
public class ZonedDateTimeExample {
public static void main(String[] args) {
// Get current date and time with the system's default timezone
ZonedDateTime currentDateTime = ZonedDateTime.now();
System.out.println("Current date and time with default timezone: " + currentDateTime);
// Get current date and time with a specific timezone
ZonedDateTime newYorkDateTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println("Current date and time in New York: " + newYorkDateTime);
// Get current date and time in UTC
ZonedDateTime utcDateTime = ZonedDateTime.now(ZoneId.of("UTC"));
System.out.println("Current date and time in UTC: " + utcDateTime);
}
}
Output :
Current date and time with default timezone: 2024-08-26T14:30:45.123-04:00[America/New_York]
Current date and time in New York: 2024-08-26T14:30:45.123-04:00[America/New_York]
Current date and time in UTC: 2024-08-26T18:30:45.123Z[UTC]
2. Using OffsetDateTime:
OffsetDateTime represents a date and time with an offset from UTC but without a specific timezone (e.g., +01:00, -05:00).
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
public class OffsetDateTimeExample {
public static void main(String[] args) {
// Get current date and time with the system's default offset
OffsetDateTime currentOffsetDateTime = OffsetDateTime.now();
System.out.println("Current date and time with default offset: " + currentOffsetDateTime);
// Get current date and time with a specific offset
OffsetDateTime offsetDateTime = OffsetDateTime.now(ZoneOffset.ofHours(-5));
System.out.println("Current date and time with offset -5 hours: " + offsetDateTime);
}
}
Output :
Current date and time with default offset: 2024-08-26T14:30:45.123-04:00
Current date and time with offset -5 hours: 2024-08-26T13:30:45.123-05:00
3. Using Instant and Converting to ZonedDateTime:
Instant represents a point in time in UTC. You can convert it to a ZonedDateTime to include timezone information.
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class InstantExample {
public static void main(String[] args) {
// Get current instant in UTC
Instant now = Instant.now();
System.out.println("Current instant in UTC: " + now);
// Convert Instant to ZonedDateTime with a specific timezone
ZonedDateTime zonedDateTime = now.atZone(ZoneId.of("Europe/Paris"));
System.out.println("Current date and time in Paris: " + zonedDateTime);
}
}
Output :
Current instant in UTC: 2024-08-26T18:30:45.123Z
Current date and time in Paris: 2024-08-26T20:30:45.123+02:00[Europe/Paris]
Key Points:
ZonedDateTimeincludes both the date-time and the timezone, including timezone rules like Daylight Saving Time (DST).OffsetDateTimeincludes the date-time and a fixed offset from UTC but not timezone rules.Instantis always in UTC and can be converted toZonedDateTimeto apply a specific timezone.
These classes are useful when working with dates and times in different time zones or when you need to handle timezone-sensitive operations.