A service like this has an explicit note that
All times are specified in Local Standard Time (LST). Add 1 hour to adjust for Daylight Saving Time where and when it is observed.
Given a LocalDateTime
object ldt
, creating an instant is as simple as
Instant.of(ldt,zoneId)
. However, if I supply the ZoneId
, then Instant
will assume the daylight-savings (DST) adjustment has already been made, and ldt
is with respect to DST, which is not the case.
What is the most Java-esque way to make the Instant
's constructor apply the "standard" offset rather than taking into account the DST?
EDIT: I mean, short of hard-codedly checking, for the given year, the exact dates of DST transitions? Sure, I can get the offset as
ZoneOffset offset= ZoneOffset.of(zoneId)
and then subtract offset.getTotalSeconds()
from the given timestamp, to move to the "reference" time. But giving that reference-adjusted timestamp to Instant
still
has the same problem of the DST.
EDIT: As has been suggested below, I tried this:
String str = String.format("%04d-%02d-%02dT%s:00", year, month, day, hourMinutes);
LocalDateTime ldt = LocalDateTime.parse(str);
Instant i1= ldt.toInstant(zoneId.getRules().getOffset(ldt));
Instant key= ldt.toInstant(zoneId.getRules().getStandardOffset(i1));
You can get the standard offset of a ZoneId
by calling getRules()
and then getStandardOffset()
.
However, you need an Instant
. Because sometimes the standard offset changes too...
So one way is to first convert the LocalDateTime
to Instant
, using the offset at that LocalDateTime
. Then we get the standard offset at that instant, and use that to get the actual Instant
we want:
LocalDateTime ldt = ...;
Instant i = ldt.toInstant(someZoneId.getRules().getOffset(ldt));
Instant i2 = ldt.toInstant(someZoneId.getRules().getStandardOffset(i));
System.out.println(i2);
I think this wouldn't work for some specific local times if both the standard offset and the DST offset changes at the same time, because the first instant i
is calculated with the offset before the transition. You can calculate i
with the offset after the transition by doing this:
Instant i;
ZoneOffsetTransition transition = someZoneId.getRules().getTransition(ldt)
if (transition == null) {
i = ldt.toInstant(someZoneId.getRules().getOffset(ldt));
} else {
i = ldt.toInstant(transition.getOffsetAfter());
}
Update:
But even still, this will produce the wrong result for some really corner cases. The problem is that java.time does not provide a way of getting the transitions in standard offset.