|
|
@@ -0,0 +1,70 @@ |
|
|
/** |
|
|
* 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. |
|
|
*/ |