-
Notifications
You must be signed in to change notification settings - Fork 84
Description
I just migrated from Charts 3.2.1 and wanted to convert to the setters that take a java.time.Instant instead of a java.util.Date - not least because all the setters with java.util.Date are deprecated now.
However, the logic for the converting a java.time.Instant to a Highchart time is not consistent with the previous behavior and other parts of the API. All the corresponding setters call Util::toHighchartsTS(Instant) which just returns the epoch milliseconds. Setters taking a java.util.Date call Util::toHighchartsTS(Date) which returns
date.getTime() - date.getTimezoneOffset() * 60000;
java.util.Date does not have a time zone, Date::getTimezoneOffset() just refers to the default time zone. Just like java.time.Instant, its getTime() method returns the same value as Instant::toEpochMilli(), namely the epoch in milliseconds. Adding the time zone offset is important, though, because Highchart will subtract it again to convert to UTC.
What happens now is this:
- With the Date-based setters, the chart will show server times. In my opinion, this is the desirable behavior and this is how it worked before 4.0.
- With the Instant-based setters, the chart will show UTC times. However, you cannot implement this consistently, because there are still (undeprecated) Date-based setters without an Instant-based equivalent, such as
Axis::setMax/setMinand those are still transmitted with the timezone offset.
To solve this issue, the implementation of Util::toHighchartsTS(Instant) should be changed to
public static long toHighchartsTS(Instant date) {
long epochMilli = date.toEpochMilli();
return epochMilli + TimeZone.getDefault().getOffset(epochMilli);
}
To convince yourself of the relationships between Date and Instant, run the following code:
Instant instant = Instant.now();
Date date = Date.from(instant);
long epochMilli = instant.toEpochMilli();
long time = date.getTime();
System.out.println("instant epochMills = " + epochMilli);
System.out.println("date time = " + time);
System.out.println("equals " + (epochMilli == time));
long instantPlusOffset = epochMilli + TimeZone.getDefault().getOffset(epochMilli);
System.out.println("instant + offset = " + instantPlusOffset);
long datePlusOffset = time - date.getTimezoneOffset() * 60000;
System.out.println("date + offset = " + datePlusOffset);
System.out.println("equals " + (datePlusOffset == instantPlusOffset));