Working with dates and times seems to be trivial at first. Getting it right often is not.
Most of the problems that arise when working with datetimes come from the fact that we have so many different time zones on our planet (currently 39). Big countries need several time zones, and even smaller countries often use two different time zones in summer and winter.
The java.time API has four types that can be used to represent a point in time: LocalDateTime, OffsetDateTime, ZonedDatetime and Instant. All of them have their use, depending on the scenario.
- Instant: When the time zone is not needed, or not known, most times Instant is the best choice. Usually, it is used for technical dates (timestamps etc.)
- LocalDateTime: Since it has no time zone information, a LocalDateTime can not be used to exactly specify a point in time. I think that using this type is usually a bad idea, unless you store the zone information somewhere else. For example, if you need to manage special opening hours for your stores spread over the planet, you could store the zone once in your store data, and use LocalDateTimes for the opening hours. Another use might be some calendar app that reminds users at specific times. Using LocalDateTimes here and resolving the time zone according to the current location of the user will automatically adapt the reminders when travelling.
- OffsetDateTime: An OffsetDateTime stores the time zone offset together with the datetime. This way, the actual point in time (UTC) as well as the display time are available for use. The advantage of this type is that it is ISO-8601 compliant. As long as you do no calculations (like adding or subtracting periods of time), this type is sufficient.
- ZonedDateTime: In contrast to OffsetDateTime, ZonedDateTime do not just hold the zone offset (like +01:00), but also the zone id ("Europe/Berlin"). In my opinion, this is the only type that can handle all scenarios correctly. When doing calculations it will correctly adapt the zone offset if time zones are switched (e.g., going from CEST to CET in October). One disadvantage of ZonedDateTime is that the default serialization is not compatible with ISO 8601 (because it also emits the zone id).
For me, in most cases, the decision is between Instant and ZonedDateTime, depending on the need of zone information. OffsetDateTime might often be enough, but I like "correct" better than "enough" if it is affordable. LocalDateTime has its uses, but you need to really be sure that you get the zone information from somewhere else when you need it.