Java LocalDate Tutorial with Examples
LocalDate class represent a date without a time-zone in the ISO-8601 calendar system, such as 1980-04-09, often viewed as year-month-day. This class is immutable and thread-safe.
Creating a LocalDate
We can create a LocalDate in several ways:
- static LocalDate now(): Obtains the current date from the system clock in the default time-zone.
- static LocalDate now(Clock clock): Obtains the current date from the specified clock.
- static LocalDate now(ZoneId zone): Obtains the current date from the system clock in the specified time-zone.
- static LocalDate of(int year, int month, int dayOfMonth): Obtains an instance of LocalDate from a year, month and day.
- static LocalDate of(int year, Month month, int dayOfMonth): Obtains an instance of LocalDate from a year, month and day.
- static LocalDate ofEpochDay(long epochDay): Obtains an instance of LocalDate from the epoch day count.
- static LocalDate ofYearDay(int year, int dayOfYear): Obtains an instance of LocalDate from a year and day-of-year.
- static LocalDate parse(CharSequence text): Obtains an instance of LocalDate from a text string such as 2007-12-03.
- static LocalDate parse(CharSequence text, DateTimeFormatter formatter): Obtains an instance of LocalDate from a text string using a specific formatter.
import java.time.Clock;
import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class LocalDateInitExample {
public static void main(String[] args) {
LocalDate localDate1 = LocalDate.now();
System.out.println("LocalDate1: " + localDate1);
LocalDate localDate2 = LocalDate.now(Clock.systemUTC());
System.out.println("LocalDate2: " + localDate2);
LocalDate localDate3 = LocalDate.now(ZoneId.systemDefault());
System.out.println("LocalDate3: " + localDate3);
LocalDate localDate4 = LocalDate.of(1980, 4, 9);
System.out.println("LocalDate4: " + localDate4);
LocalDate localDate5 = LocalDate.of(1980, Month.APRIL, 9);
System.out.println("LocalDate5: " + localDate5);
LocalDate localDate6 = LocalDate.ofEpochDay(3629);
System.out.println("LocalDate6: " + localDate6);
LocalDate localDate7 = LocalDate.ofYearDay(1997, 127);
System.out.println("LocalDate7: " + localDate7);
LocalDate localDate8 = LocalDate.parse("2018-07-24");
System.out.println("LocalDate8: " + localDate8);
LocalDate localDate9 = LocalDate.parse("20180724", DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("LocalDate9: " + localDate9);
}
}
LocalDate1: 2019-08-21 LocalDate2: 2019-08-20 LocalDate3: 2019-08-21 LocalDate4: 1980-04-09 LocalDate5: 1980-04-09 LocalDate6: 1979-12-09 LocalDate7: 1997-05-07 LocalDate8: 2018-07-24 LocalDate9: 2018-07-24
Since Java 9:
- static LocalDate ofInstant(Instant instant, ZoneId zone): Obtains an instance of LocalDate from an Instant and zone ID.
LocalDate localDate = LocalDate.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.println("LocalDate: " + localDate);
LocalDate: 2019-08-21
LocalDate from and to Epoch
Using LocalDate.ofEpochDay(...) we can obtain an instance of LocalDate from the epoch day count. The other way, we can convert a LocalDate to the number of day from the epoch:
- long toEpochDay(): Converts this date to the Epoch Day.
Another method is toEpochSecond(...), which is available since Java 9:
- long toEpochSecond(LocalTime time, ZoneOffset offset): Converts this LocalDate to the number of seconds since the epoch of 1970-01-01T00:00:00Z.
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneOffset;
public class LocalDateFromToEpochExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.parse("1980-04-09");
System.out.println("LocalDate : " + localDate);
System.out.println("LocalDate.toEpochDay() : " + localDate.toEpochDay());
System.out.println("LocalDate.toEpochSecond(): " + localDate.toEpochSecond(LocalTime.MIDNIGHT, ZoneOffset.UTC));
LocalDate copyLocalDate = LocalDate.ofEpochDay(localDate.toEpochDay());
System.out.println("Copied LocalDate : " + copyLocalDate);
}
}
LocalDate : 1980-04-09 LocalDate.toEpochDay() : 3751 LocalDate.toEpochSecond(): 324086400 Copied LocalDate : 1980-04-09
Getting Information from a LocalDate
Following methods can be used to access Date information from a LocalDate:
- int getDayOfMonth(): Gets the day-of-month field.
- DayOfWeek getDayOfWeek(): Gets the day-of-week field, which is an enum DayOfWeek.
- int getDayOfYear(): Gets the day-of-year field.
- Month getMonth(): Gets the month-of-year field using the Month enum.
- int getMonthValue(): Gets the month-of-year field from 1 to 12.
- int getYear(): Gets the year field.
Method getLong(...) also exists to get the value of specified field from a LocalDate:
- long getLong(TemporalField field): Gets the value of the specified field from this date as a long.
import java.time.LocalDate;
import java.time.temporal.ChronoField;
public class LocalDateInfoExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now();
System.out.println("LocalDate : " + localDate);
System.out.println("DayOfMonth : " + localDate.getDayOfMonth());
System.out.println("MonthValue : " + localDate.getMonthValue());
System.out.println("Year : " + localDate.getYear());
System.out.println("DayOfWeek : " + localDate.getDayOfWeek());
System.out.println("Month : " + localDate.getMonth());
System.out.println("DayOfYear : " + localDate.getDayOfYear());
System.out.println("DAY_OF_MONTH : " + localDate.getLong(ChronoField.DAY_OF_MONTH));
System.out.println("MONTH_OF_YEAR: " + localDate.getLong(ChronoField.MONTH_OF_YEAR));
System.out.println("YEAR : " + localDate.getLong(ChronoField.YEAR));
}
}
LocalDate : 2019-08-21 DayOfMonth : 21 MonthValue : 8 Year : 2019 DayOfWeek : WEDNESDAY Month : AUGUST DayOfYear : 233 DAY_OF_MONTH : 21 MONTH_OF_YEAR: 8 YEAR : 2019
Following methods maybe seldom in use:
- IsoChronology getChronology(): Gets the chronology of this date, which is the ISO calendar system.
- Era getEra(): Gets the era applicable at this date.
- boolean isLeapYear(): Checks if the year is a leap year, according to the ISO proleptic calendar system rules.
- int lengthOfMonth(): Returns the length of the month represented by this date.
- int lengthOfYear(): Returns the length of the year represented by this date.
System.out.println("Chronology : " + localDate.getChronology());
System.out.println("Era : " + localDate.getEra());
System.out.println("LeapYear : " + localDate.isLeapYear()); // for 2019
System.out.println("LengthOfMonth: " + localDate.lengthOfMonth()); // for AUGUST
System.out.println("LengthOfYear : " + localDate.lengthOfYear()); // for 2019
Chronology : ISO Era : CE LeapYear : false LengthOfMonth: 31 LengthOfYear : 365
Add/Subtract Operations on LocalDate
LocalDate class also has several methods which can be used to do add/subtract operations:
- LocalDate minus(long amountToSubtract, TemporalUnit unit): Returns a copy of this date with the specified amount subtracted.
- LocalDate minus(TemporalAmount amountToSubtract): Returns a copy of this date with the specified amount subtracted.
- LocalDate minusDays(long daysToSubtract): Returns a copy of this LocalDate with the specified number of days subtracted.
- LocalDate minusMonths(long monthsToSubtract): Returns a copy of this LocalDate with the specified number of months subtracted.
- LocalDate minusWeeks(long weeksToSubtract): Returns a copy of this LocalDate with the specified number of weeks subtracted.
- LocalDate minusYears(long yearsToSubtract): Returns a copy of this LocalDate with the specified number of years subtracted.
- LocalDate plus(long amountToAdd, TemporalUnit unit): Returns a copy of this date with the specified amount added.
- LocalDate plus(TemporalAmount amountToAdd): Returns a copy of this date with the specified amount added.
- LocalDate plusDays(long daysToAdd): Returns a copy of this LocalDate with the specified number of days added.
- LocalDate plusMonths(long monthsToAdd): Returns a copy of this LocalDate with the specified number of months added.
- LocalDate plusWeeks(long weeksToAdd): Returns a copy of this LocalDate with the specified number of weeks added.
- LocalDate plusYears(long yearsToAdd): Returns a copy of this LocalDate with the specified number of years added.
import java.time.Duration;
import java.time.LocalDate;
import java.time.Period;
import java.time.temporal.ChronoUnit;
public class LocalDateAddSubstractExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.parse("1980-04-09");
System.out.println("LocalDate : " + localDate);
// Adding/subtracting days
System.out.println("10 days before: " + localDate.minusDays(10));
System.out.println("15 days later : " + localDate.plusDays(15));
// Adding/subtracting months
System.out.println("Minus 4 months: " + localDate.minusMonths(4));
System.out.println("Plus 5 months : " + localDate.plusMonths(5));
// Adding/subtracting weeks
System.out.println("Minus 20 weeks: " + localDate.minusWeeks(20));
System.out.println("Plus 30 weeks : " + localDate.plusWeeks(30));
// Adding/subtracting years
System.out.println("Minus 12 years: " + localDate.minusYears(12));
System.out.println("Plus 4 years : " + localDate.plusYears(4));
// Using DAYS
System.out.println("30 days before: " + localDate.minus(30, ChronoUnit.DAYS));
// Using WEEKS
System.out.println("3 weeks before: " + localDate.minus(3, ChronoUnit.WEEKS));
// Using MONTHS
System.out.println("6 months later: " + localDate.plus(6, ChronoUnit.MONTHS));
// Using YEARS
System.out.println("2 years later : " + localDate.plus(2, ChronoUnit.YEARS));
// Using TemporalAmount - Period
System.out.println("5 years later : " + localDate.plus(Period.ofYears(5)));
}
}
LocalDate : 1980-04-09 10 days before: 1980-03-30 15 days later : 1980-04-24 Minus 4 months: 1979-12-09 Plus 5 months : 1980-09-09 Minus 20 weeks: 1979-11-21 Plus 30 weeks : 1980-11-05 Minus 12 years: 1968-04-09 Plus 4 years : 1984-04-09 30 days before: 1980-03-10 3 weeks before: 1980-03-19 6 months later: 1980-10-09 2 years later : 1982-04-09 5 years later : 1985-04-09
Note: Using Duration as TemporalAmount
// Using TemporalAmount - Duration System.out.println("60 days before: " + localDate.minus(Duration.ofDays(60)));
producing following error:
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds at java.base/java.time.LocalDate.plus(LocalDate.java:1272) at java.base/java.time.LocalDate.minus(LocalDate.java:1448) at java.base/java.time.LocalDate.minus(LocalDate.java:139) at java.base/java.time.Duration.subtractFrom(Duration.java:1137) at java.base/java.time.LocalDate.minus(LocalDate.java:1424) at com.dariawan.datetime.LocalDateAddSubstractExample.main(LocalDateAddSubstractExample.java:80)
It's because temporal is a LocalDate which doesn't have seconds
@Override
public Temporal subtractFrom(Temporal temporal) {
if (seconds != 0) {
temporal = temporal.minus(seconds, SECONDS);
}
if (nanos != 0) {
temporal = temporal.minus(nanos, NANOS);
}
return temporal;
}
Not sure if this is a bug or expected behavior
Comparing LocalDates
LocalDate class is implementing interface ChronoLocalDate. Following methods can be use to compare two LocalDates:
- int compareTo(ChronoLocalDate other): Compares this date to another date.
- boolean isAfter(ChronoLocalDate other): Checks if this date is after the specified date.
- boolean isBefore(ChronoLocalDate other): Checks if this date is before the specified date.
- boolean isEqual(ChronoLocalDate other): Checks if this date is equal to the specified date.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class LocalDateCompareExample {
public static void main(String[] args) {
LocalDate localDate1 = LocalDate.parse("1979-12-09");
LocalDate localDate2 = LocalDate.parse("1980-04-09");
LocalDate localDate3 = LocalDate.parse("19791209", DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("LocalDate1 after LocalDate2 : " + localDate1.isAfter(localDate2));
System.out.println("LocalDate1 before LocalDate2 : " + localDate1.isBefore(localDate2));
System.out.println("LocalDate1 equal LocalDate3 : " + localDate1.isEqual(localDate3));
System.out.println("LocalDate3 equal LocalDate3 : " + localDate2.isEqual(localDate3));
System.out.println("LocalDate1 compareTo LocalDate2: " + localDate1.compareTo(localDate2));
System.out.println("LocalDate2 compareTo LocalDate1: " + localDate2.compareTo(localDate1));
System.out.println("LocalDate1 compareTo LocalDate3: " + localDate1.compareTo(localDate3));
System.out.println("LocalDate3 compareTo LocalDate2: " + localDate3.compareTo(localDate2));
}
}
LocalDate1 after LocalDate2 : false LocalDate1 before LocalDate2 : true LocalDate1 equal LocalDate3 : true LocalDate3 equal LocalDate3 : false LocalDate1 compareTo LocalDate2: -1 LocalDate2 compareTo LocalDate1: 1 LocalDate1 compareTo LocalDate3: 0 LocalDate3 compareTo LocalDate2: -1
Supported Field and Unit of a LocalDate
Use isSupported(...) to check if a particular field/unit is supported in a LocalDate:
- boolean isSupported(TemporalField field): Checks if the specified field is supported.
- boolean isSupported(TemporalUnit unit): Checks if the specified unit is supported.
LocalDate localDate = LocalDate.now();
System.out.println("*** ChronoField ***");
for(ChronoField chronoField : ChronoField.values()){
System.out.println(chronoField + " is supported:" + localDate.isSupported(chronoField));
}
System.out.println("\n*** ChronoUnit ***");
for(ChronoUnit chronoUnit : ChronoUnit.values()){
System.out.println(chronoUnit + " is supported:" + localDate.isSupported(chronoUnit));
}
*** ChronoField *** NanoOfSecond is supported:false NanoOfDay is supported:false MicroOfSecond is supported:false MicroOfDay is supported:false MilliOfSecond is supported:false MilliOfDay is supported:false SecondOfMinute is supported:false SecondOfDay is supported:false MinuteOfHour is supported:false MinuteOfDay is supported:false HourOfAmPm is supported:false ClockHourOfAmPm is supported:false HourOfDay is supported:false ClockHourOfDay is supported:false AmPmOfDay is supported:false DayOfWeek is supported:true AlignedDayOfWeekInMonth is supported:true AlignedDayOfWeekInYear is supported:true DayOfMonth is supported:true DayOfYear is supported:true EpochDay is supported:true AlignedWeekOfMonth is supported:true AlignedWeekOfYear is supported:true MonthOfYear is supported:true ProlepticMonth is supported:true YearOfEra is supported:true Year is supported:true Era is supported:true InstantSeconds is supported:false OffsetSeconds is supported:false *** ChronoUnit *** Nanos is supported:false Micros is supported:false Millis is supported:false Seconds is supported:false Minutes is supported:false Hours is supported:false HalfDays is supported:false Days is supported:true Weeks is supported:true Months is supported:true Years is supported:true Decades is supported:true Centuries is supported:true Millennia is supported:true Eras is supported:true Forever is supported:false
Convert LocalDate to LocalDateTime
LocalDate class only represent a date without time. To have time information together with date, we need different class. The class that representing a date and the time within that date is LocalDateTime. There are several methods available to convert LocalDate into LocalDateTime:
- LocalDateTime atStartOfDay(): Combines this date with the time of midnight to create a LocalDateTime at the start of this date.
- LocalDateTime atTime(int hour, int minute): Combines this date with a time to create a LocalDateTime.
- LocalDateTime atTime(int hour, int minute, int second): Combines this date with a time to create a LocalDateTime.
- LocalDateTime atTime(int hour, int minute, int second, int nanoOfSecond): Combines this date with a time to create a LocalDateTime.
- LocalDateTime atTime(LocalTime time): Combines this date with a time to create a LocalDateTime.
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class LocalDateToLocalDateTimeExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.parse("1980-04-09");
LocalDateTime localDateTime1 = localDate.atStartOfDay();
System.out.println("LocalDateTime1: " + localDateTime1);
LocalDateTime localDateTime2 = localDate.atTime(3, 10);
System.out.println("LocalDateTime2: " + localDateTime2);
LocalDateTime localDateTime3 = localDate.atTime(15, 10, 25);
System.out.println("LocalDateTime3: " + localDateTime3);
LocalDateTime localDateTime4 = localDate.atTime(15, 10, 25, 123456789);
System.out.println("LocalDateTime4: " + localDateTime4);
LocalDateTime localDateTime5 = localDate.atTime(LocalTime.NOON);
System.out.println("LocalDateTime5: " + localDateTime5);
}
}
LocalDateTime1: 1980-04-09T00:00 LocalDateTime2: 1980-04-09T03:10 LocalDateTime3: 1980-04-09T15:10:25 LocalDateTime4: 1980-04-09T15:10:25.123456789 LocalDateTime5: 1980-04-09T12:00
Getting OffsetDateTime or ZonedDateTime from a LocalDate
Following method is used to create ZonedDateTime from a LocalDate:
- ZonedDateTime atStartOfDay(ZoneId zone): Returns a zoned date-time from this date at the earliest valid time according to the rules in the time-zone.
And this method is to create OffsetDateTime from a LocalDate:
- OffsetDateTime atTime(OffsetTime time): Combines this date with an offset time to create an OffsetDateTime.
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class LocalDateToZonedOffsetDateTimeExample {
public static void main(String[] args) {
LocalDate localDate = LocalDate.parse("1983-07-12");
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.of("Asia/Shanghai"));
System.out.println("ZonedDateTime : " + zonedDateTime);
OffsetDateTime offsetDateTime = localDate.atTime(OffsetTime.of(LocalTime.NOON, ZoneOffset.UTC));
System.out.println("OffsetDateTime: " + offsetDateTime);
}
}
ZonedDateTime : 1983-07-12T00:00+08:00[Asia/Shanghai] OffsetDateTime: 1983-07-12T12:00Z
Conclusion
The LocalDate class represents a local date without time information. If you need both Date and Time information, you should use LocalDateTime instead.