Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Dates and times

Java handles dates and times with the java.time package. Its classes are immutable: every operation returns a new object and the original stays unchanged. You'll meet the old Date and Calendar classes in older code, but new code doesn't use them.

LocalDate

LocalDate is a date without a time or time zone: year, month, day. You create one with of, and now() gives today's date:

void main() {
    LocalDate birthday = LocalDate.of(1995, 3, 14);
 
    IO.println(birthday);
    IO.println(birthday.getYear());
    IO.println(birthday.getMonth());
    IO.println(birthday.getDayOfWeek());
}

Output:

1995-03-14
1995
MARCH
TUESDAY

Months are numbered the human way — from 1 (January), not from zero. By default a date is printed in ISO format: year-month-day.

Time, and date with time

LocalTime holds only a time, LocalDateTime a date and a time together:

void main() {
    LocalTime opening = LocalTime.of(9, 30);
    LocalDateTime meeting = LocalDateTime.of(2026, 10, 5, 14, 0);
 
    IO.println(opening);
    IO.println(meeting);
    IO.println(meeting.toLocalDate());
}

Output:

09:30
2026-10-05T14:00
2026-10-05

The current moment comes from LocalDate.now(), LocalTime.now() and LocalDateTime.now(). Their result naturally changes with every run, so the examples in this lesson use fixed dates.

Date arithmetic

Methods such as plusDays, minusMonths and plusWeeks return a new date. Java takes care of month lengths and leap years:

void main() {
    LocalDate date = LocalDate.of(2024, 1, 31);
 
    IO.println(date.plusDays(1));
    IO.println(date.plusMonths(1));
    IO.println(date.minusYears(1));
    IO.println(date.isLeapYear());
}

Output:

2024-02-01
2024-02-29
2023-01-31
true

January 31 plus one month is February 29: there's no February 31, so Java takes the last day of the month.

How much time has passed

To compute the difference between dates, use ChronoUnit — it gives a number in the units you need. Period splits the difference into years, months and days, while Duration measures time in hours, minutes and seconds:

void main() {
    LocalDate start = LocalDate.of(2026, 1, 15);
    LocalDate end = LocalDate.of(2026, 10, 4);
 
    IO.println(ChronoUnit.DAYS.between(start, end) + " days");
 
    Period period = Period.between(start, end);
    IO.println(period.getMonths() + " months " + period.getDays() + " days");
 
    Duration lesson = Duration.between(LocalTime.of(10, 0), LocalTime.of(11, 35));
    IO.println(lesson.toMinutes() + " minutes");
}

Output:

262 days
8 months 19 days
95 minutes

isBefore, isAfter and isEqual help compare dates.

Time zones

A LocalDateTime doesn't know which city an event happens in. For that there is ZonedDateTime — a date and time in a specific time zone. The withZoneSameInstant method shows the same moment in another zone:

void main() {
    ZonedDateTime call = ZonedDateTime.of(
            LocalDateTime.of(2026, 10, 5, 18, 0), ZoneId.of("Europe/Berlin"));
 
    IO.println(call);
    IO.println(call.withZoneSameInstant(ZoneId.of("Asia/Tokyo")));
}

Output:

2026-10-05T18:00+02:00[Europe/Berlin]
2026-10-06T01:00+09:00[Asia/Tokyo]

Timestamps in logs and databases use Instant — a point on the time line in UTC, without a zone.

Common mistake

java.time objects are immutable, so calling plusDays without assigning the result changes nothing:

void main() {
    LocalDate deadline = LocalDate.of(2026, 10, 4);
    deadline.plusDays(7);
 
    IO.println(deadline);
}

Output:

2026-10-04

There's no compile error, but the result is lost. The fix is to keep the new date: deadline = deadline.plusDays(7);.

Thanks for reading!

Donate to the site — we work hard for you.