Every now and then I struggle a little bit with all the date-time types we have in the java.time package:
- Instant
- OffsetDateTime
- ZonedDateTime
- LocalDateTime
- LocalDate
- LocalTime
- OffsetTime
But digging a bit through the source code of these classes, the fog slowly disappears.
An Instant
is actually a point in time without any extra
information. Internally it is stored as the number of
milliseconds and nanoseconds since the beginning of the epoch:
/**
* The number of seconds from the epoch of 1970-01-01T00:00:00Z.
*/
private final long seconds;
/**
* The number of nanoseconds, later along the time-line, from the seconds field.
* This is always positive, and never exceeds 999,999,999.
*/
private final int nanos;
As we just have a point in time and we do not know where on the world
this point in time was, we do not know the date and time. This is where
LocalDateTime
comes into play.
In contrast to Instant
it stores the time and date:
/**
* The date part.
*/
private final LocalDate date;
/**
* The time part.
*/
private final LocalTime time;
But as LocalDateTime
does not store any timezone, we again don’t know
where on the world we are, as a date and time like 2025-05-24T15:10 happens
in every timezone after each other.
Therefore, to convert a LocalDateTime
into an Instant
, we need to pass
the timezone:
LocalDateTime dateTime = LocalDateTime.of(2025, 5, 24, 15, 10);
Instant instant = dateTime.atZone(ZoneId.of("Europe/Berlin")).toInstant();
The type on wich the method toInstant()
is called, is a ZonedDateTime
:
LocalDateTime dateTime = LocalDateTime.of(2025, 5, 24, 15, 10);
ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.of("Europe/Berlin"));
Hence, ZonedDateTime
stores internally the LocalDateTime
together with
information about the timezone:
/**
* The local date-time.
*/
private final LocalDateTime dateTime;
/**
* The offset from UTC/Greenwich.
*/
private final ZoneOffset offset;
/**
* The time-zone.
*/
private final ZoneId zone;
OffsetDateTime
is actually only a layer above ZoneDateTime
, as it
does only handle the offset information, but not which timezone it actually is:
/**
* The local date-time.
*/
private final LocalDateTime dateTime;
/**
* The offset from UTC/Greenwich.
*/
private final ZoneOffset offset;
Finally, the type OffsetTime
is just a combination of LocalTime
and ZoneOffset
:
/**
* The local date-time.
*/
private final LocalTime time;
/**
* The offset from UTC/Greenwich.
*/
private final ZoneOffset offset;