LocalDate.now() and LocalDate.of()

Get today's date for a given zone or clock, and build a specific calendar date that is validated as it is created.

Signature
public static LocalDate now()
public static LocalDate now(ZoneId zone)
public static LocalDate now(Clock clock)
public static LocalDate of(int year, int month, int dayOfMonth)
public static LocalDate of(int year, Month month, int dayOfMonth)
  • Added in Java Java 8

Parameters

ParameterTypeDescription
$zoneoptionalZoneIdnow(zone) only: the zone whose calendar decides what 'today' is.
$clockoptionalClocknow(clock) only: the clock to read the instant and zone from; pass a fixed clock in tests.
$yearoptionalintof() only: the proleptic year, from -999999999 to 999999999.
$monthoptionalint or Monthof() only: the month, 1 (January) to 12 (December), or a Month constant.
$dayOfMonthoptionalintof() only: the day of the month, 1 to 31, checked against the month and year.

Return value

LocalDatenow(): the current date in the default time zone (or the given zone or clock). of(): the date for the given year, month and day.

Errors

of() throws DateTimeException if a field is out of range or the day is not valid for that month and year (for example 31 April or 29 February in a non-leap year). now() does not throw.

LocalDate is a date on a calendar with no time and no zone, such as 2026-03-14. The two static factories cover the two ways you get one in code: now() asks a clock what today is, and of() builds a date you already know.

now() depends on a zone

There is no single "today". At 23:30 UTC on 14 March it is already 15 March in Sydney. The no-argument LocalDate.now() uses the JVM's default time zone, which on a server is usually whatever the container image was built with, often UTC. That is rarely the zone your user cares about.

In a service, pass the zone explicitly with now(ZoneId), or better, inject a Clock and call now(clock). A clock carries both the instant and the zone, and in tests you swap it for Clock.fixed(...) so "today" stops changing under your assertions.

LocalDate today = LocalDate.now(clock);                 // testable
LocalDate there = LocalDate.now(ZoneId.of("Asia/Tokyo")); // explicit zone

of() validates as it builds

LocalDate.of(year, month, day) takes months from 1 to 12, not 0 to 11 as the old java.util.Calendar did. It checks the whole date, so of(2026, 2, 29) and of(2026, 4, 31) throw DateTimeException instead of rolling over into March or May. That makes it a cheap validator for year, month and day fields that arrive separately in a form or a query string: catch the exception and return a 400.

The Month overload, of(2026, Month.MARCH, 1), reads better in code and removes any doubt about numbering.

Mistakes people make

  • Calling LocalDate.now() deep inside business logic. The code becomes untestable and depends on the server's zone. Inject a Clock.
  • Using LocalDate for a moment in time. "Created at" belongs in an Instant; LocalDate suits birthdays, invoice dates and holidays.
  • Comparing with ==. Use equals, isBefore and isAfter.

Values are immutable and thread-safe, so a LocalDate can sit in a static field, a record or a map key without any copying.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Working out which day's orders a nightly report should cover, using the shop's zone from an injected Clock.
  • Validating separate year, month and day fields in a sign-up form and returning a 400 for 31 April.
  • Building fixed dates such as a public holiday list or a contract start date in configuration code.

Frequently asked questions

How do I get the current date in Java?

Call LocalDate.now(), but prefer LocalDate.now(ZoneId) or LocalDate.now(clock) in server code. The no-argument version uses the JVM's default zone, which may not match your users.

Are months zero-based in LocalDate.of?

No. Months run from 1 to 12, unlike java.util.Calendar. You can also pass a Month constant such as Month.MARCH to avoid any doubt.

What happens if I call LocalDate.of with an invalid date?

It throws DateTimeException, for example 'Invalid date 'APRIL 31''. It never rolls the date over into the next month.

More examples

Today in the user's zone, not the server's

The same instant is 30 June in New York and London but already 1 July in Tokyo. A daily report or a 'due today' check must use the user's zone, which the clock carries.

Example · java
import java.time.*;

LocalDate todayFor(Clock clock, String zone) {
    return LocalDate.now(clock.withZone(ZoneId.of(zone)));
}

void main() {
    Clock clock = Clock.fixed(Instant.parse("2026-06-30T20:00:00Z"), ZoneOffset.UTC);
    for (String zone : List.of("America/New_York", "Europe/London", "Asia/Tokyo")) {
        IO.println(zone + " -> " + todayFor(clock, zone));
    }
}
// Output:
// America/New_York -> 2026-06-30
// Europe/London -> 2026-06-30
// Asia/Tokyo -> 2026-07-01

Validating year, month and day fields from a form

LocalDate.of() rejects impossible dates instead of rolling them over, so it doubles as a validator. 2028 is a leap year, so 29 February is accepted there.

Example · java
import java.time.*;

String validate(int year, int month, int day) {
    try {
        return "ok  " + LocalDate.of(year, month, day);
    } catch (DateTimeException e) {
        return "400 " + e.getMessage();
    }
}

void main() {
    IO.println(validate(2028, 2, 29));
    IO.println(validate(2026, 4, 31));
    IO.println(validate(2026, 13, 1));
}
// Output:
// ok  2028-02-29
// 400 Invalid date 'APRIL 31'
// 400 Invalid value for MonthOfYear (valid values 1 - 12): 13

Other factories worth knowing

ofInstant (Java 9) turns a stored timestamp into a calendar date for a zone: 23:30 UTC on New Year's Eve is already 2027 in Berlin. withDayOfMonth and lengthOfMonth give the first and last day of a month for reporting ranges.

Example · java
import java.time.*;

void main() {
    IO.println(LocalDate.ofYearDay(2026, 256));
    IO.println(LocalDate.ofEpochDay(0));
    IO.println(LocalDate.ofInstant(Instant.parse("2026-12-31T23:30:00Z"), ZoneId.of("Europe/Berlin")));

    LocalDate d = LocalDate.of(2026, 2, 10);
    IO.println(d.withDayOfMonth(1) + " to " + d.withDayOfMonth(d.lengthOfMonth()));
}
// Output:
// 2026-09-13
// 1970-01-01
// 2027-01-01
// 2026-02-01 to 2026-02-28

Discussion

  • Be the first to comment on this lesson.