/** * Here is the jdk8 datetime cheatsheet and explanation why we use ZonedDateTime and Instant in TimeService. */ // this is the 01.03.2016 00:00 in server timezone (Europe/Warsaw) == EXACTLY THE SAME AS THE SYSTEM TIME ZonedDateTime zonedDateTime = ZonedDateTime.of(2016, 3, 1, 0, 0, 0, 0, ZoneId.systemDefault()); System.out.println(zonedDateTime); // 2016-03-01T00:00+01:00[Europe/Warsaw] // this is the same 01.03.2016 00:00 but doesn't carry timezone information LocalDateTime localDateTime = zonedDateTime.toLocalDateTime(); System.out.println(localDateTime); // 2016-03-01T00:00 // the important info about ZonedDateTime and LocalDateTime - they are exactly the same after conversion, just LocalDateTime // doesn't carry timezone part; no time part recalculation is done on such conversion System.out.println(localDateTime.atZone(ZoneId.systemDefault())); // back to 2016-03-01T00:00+01:00[Europe/Warsaw] /* Should application use LocalDateTime or ZonedDateTime? Short answer: ZonedDateTime. Long answer: For internal calculations both can be used, having in mind that: - LocalDateTime shouldn't ever be passed outside the service, for example to the browser or to other service possibly working in different time zone. Browser will consider this is UTC time or browser timezone time (depending on parser implementation) while the other service will consider it a timestamp in its timezone. If the timezone of browser or other service will be different than timezone of your service, the timestamp information will be broken. - LocalDateTime shouldn't ever be saved to database, because it will be considered a timestamp with UTC timezone, what is not true. For both above usages you should use ZonedDateTime, so the cheat answer for "should application use LocalDateTime or ZonedDateTime?" question is: use ZonedDateTime and it will be safer. */ // instant also doesn't carry timezone information but IT DIFFERS from LocalDateTime because it is considered to be in UTC Instant instant = Instant.from(zonedDateTime); System.out.println(instant); // 2016-02-29T23:00:00Z (!!!) // the important info about ZonedDateTime and Instant - they will have different time parts after conversion // for example for Europe/Warsaw timezone Instant will be an hour back from the ZonedDateTime System.out.println(instant.atZone(ZoneId.systemDefault())); // 2016-03-01T00:00+01:00[Europe/Warsaw] // instant can't be obtained from LocalDateTime because LocalDateTime without timezone has unknown time try { instant = Instant.from(localDateTime); } catch (DateTimeException e) { System.out.println(String.format("%s: %s", e.getClass().getSimpleName(), e.getMessage())); // DateTimeException: Unable to obtain Instant from TemporalAccessor: 2016-03-01T00:00 of type java.time.LocalDateTime } /* Should application use Instant or ZonedDateTime? Short answer: both. Long answer: Instant and ZonedDateTime can be used interchangeably, because you can always recover one from another. Instant is just without timezone but always in UTC, while ZonedDateTime is always with timezone. Hibernate/mongo driver will recognize both fields - Instant will be considered UTF while ZonedDateTime will be recogniez as timestamp with timezone. Mongo driver anyway stores everything in UTC (so ZonedDateTime will be recalculated to UTC), please refer to {@code AuditableDocument} for the example. Hibernate will do the same, however we should store all timestamps with timezone, while default JPA {@code @Temporal} declaration doesn't have the timezone. This is why we need additional annotation {@code @Column(columnDefinition = POSTGRES_TIMEZONE_TIMESTAMP)} on timestamp entity fields. Please refer to {@code AuditableEntity} for the example. Regarding Jackson, both Instant and ZonedDateTime returned to the browser will be well interpreted by the JavaScript. Please check examples in {@code TimeController} from {@code ax} service. */