8283681: Improve ZonedDateTime offset handling

Reviewed-by: scolebourne, naoto, rriggs
This commit is contained in:
Claes Redestad 2022-03-25 22:37:55 +00:00
parent 2600f99fec
commit 7bac0a878d
5 changed files with 156 additions and 4 deletions

View file

@ -584,6 +584,11 @@ public abstract sealed class ZoneId implements Serializable permits ZoneOffset,
return this;
}
/**
* Get the effective offset for an instant at the given epochSecond.
*/
/* package-private */ abstract ZoneOffset getOffset(long epochSecond);
//-----------------------------------------------------------------------
/**
* Checks if this time-zone ID is equal to another time-zone ID.

View file

@ -86,6 +86,8 @@ import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import jdk.internal.vm.annotation.Stable;
/**
* A time-zone offset from Greenwich/UTC, such as {@code +02:00}.
* <p>
@ -168,6 +170,11 @@ public final class ZoneOffset
* The string form of the time-zone offset.
*/
private final transient String id;
/**
* The zone rules for an offset will always return this offset. Cache it for efficiency.
*/
@Stable
private transient ZoneRules rules;
//-----------------------------------------------------------------------
/**
@ -504,7 +511,21 @@ public final class ZoneOffset
*/
@Override
public ZoneRules getRules() {
return ZoneRules.of(this);
ZoneRules rules = this.rules;
if (rules == null) {
rules = this.rules = ZoneRules.of(this);
}
return rules;
}
@Override
public ZoneId normalized() {
return this;
}
@Override
/* package-private */ ZoneOffset getOffset(long epochSecond) {
return this;
}
//-----------------------------------------------------------------------

View file

@ -178,6 +178,11 @@ final class ZoneRegion extends ZoneId implements Serializable {
return (rules != null ? rules : ZoneRulesProvider.getRules(id, false));
}
@Override
/* package-private */ ZoneOffset getOffset(long epochSecond) {
return getRules().getOffset(Instant.ofEpochSecond(epochSecond));
}
//-----------------------------------------------------------------------
/**
* Writes the object using a

View file

@ -452,9 +452,9 @@ public final class ZonedDateTime
* @throws DateTimeException if the result exceeds the supported range
*/
private static ZonedDateTime create(long epochSecond, int nanoOfSecond, ZoneId zone) {
ZoneRules rules = zone.getRules();
Instant instant = Instant.ofEpochSecond(epochSecond, nanoOfSecond); // TODO: rules should be queryable by epochSeconds
ZoneOffset offset = rules.getOffset(instant);
// nanoOfSecond is in a range that'll not affect epochSecond, validated
// by LocalDateTime.ofEpochSecond
ZoneOffset offset = zone.getOffset(epochSecond);
LocalDateTime ldt = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, offset);
return new ZonedDateTime(ldt, offset, zone);
}