/** * Gets the valid offsets during this transition. * <p> * A gap will return an empty list, while an overlap will return both offsets. * * @return the list of valid offsets */ List<ZoneOffset> getValidOffsets() { if (isGap()) { return Collections.emptyList(); } return Arrays.asList(getOffsetBefore(), getOffsetAfter()); }
/** * Gets the valid offsets during this transition. * <p> * A gap will return an empty list, while an overlap will return both offsets. * * @return the list of valid offsets */ List<ZoneOffset> getValidOffsets() { if (isGap()) { return Collections.emptyList(); } return Arrays.asList(getOffsetBefore(), getOffsetAfter()); }
/** * Does this transition represent a gap in the local time-line. * <p> * Gaps occur where there are local date-times that simply do not not exist. * An example would be when the offset changes from {@code +01:00} to {@code +02:00}. * This might be described as 'the clocks will move forward one hour tonight at 1am'. * * @return true if this transition is a gap, false if it is an overlap */ public boolean isGap() { return getOffsetAfter().getTotalSeconds() > getOffsetBefore().getTotalSeconds(); }
/** * Does this transition represent a gap in the local time-line. * <p> * Gaps occur where there are local date-times that simply do not not exist. * An example would be when the offset changes from {@code +01:00} to {@code +02:00}. * This might be described as 'the clocks will move forward one hour tonight at 1am'. * * @return true if this transition is a gap, false if it is an overlap */ public boolean isGap() { return getOffsetAfter().getTotalSeconds() > getOffsetBefore().getTotalSeconds(); }
/** * Gets the duration of the transition in seconds. * * @return the duration in seconds */ private int getDurationSeconds() { return getOffsetAfter().getTotalSeconds() - getOffsetBefore().getTotalSeconds(); }
/** * Gets the duration of the transition in seconds. * * @return the duration in seconds */ private int getDurationSeconds() { return getOffsetAfter().getTotalSeconds() - getOffsetBefore().getTotalSeconds(); }
/** * Does this transition represent a gap in the local time-line. * <p> * Overlaps occur where there are local date-times that exist twice. * An example would be when the offset changes from {@code +02:00} to {@code +01:00}. * This might be described as 'the clocks will move back one hour tonight at 2am'. * * @return true if this transition is an overlap, false if it is a gap */ public boolean isOverlap() { return getOffsetAfter().getTotalSeconds() < getOffsetBefore().getTotalSeconds(); }
/** * Does this transition represent a gap in the local time-line. * <p> * Overlaps occur where there are local date-times that exist twice. * An example would be when the offset changes from {@code +02:00} to {@code +01:00}. * This might be described as 'the clocks will move back one hour tonight at 2am'. * * @return true if this transition is an overlap, false if it is a gap */ public boolean isOverlap() { return getOffsetAfter().getTotalSeconds() < getOffsetBefore().getTotalSeconds(); }
/** * Checks if the specified offset is valid during this transition. * <p> * This checks to see if the given offset will be valid at some point in the transition. * A gap will always return false. * An overlap will return true if the offset is either the before or after offset. * * @param offset the offset to check, null returns false * @return true if the offset is valid during the transition */ public boolean isValidOffset(ZoneOffset offset) { return isGap() ? false : (getOffsetBefore().equals(offset) || getOffsetAfter().equals(offset)); }
/** * Checks if the specified offset is valid during this transition. * <p> * This checks to see if the given offset will be valid at some point in the transition. * A gap will always return false. * An overlap will return true if the offset is either the before or after offset. * * @param offset the offset to check, null returns false * @return true if the offset is valid during the transition */ public boolean isValidOffset(ZoneOffset offset) { return isGap() ? false : (getOffsetBefore().equals(offset) || getOffsetAfter().equals(offset)); }
/** * Converts this to a transition rule. * * @param standardOffset the active standard offset, not null * @param savingsBeforeSecs the active savings before the transition in seconds * @return the transition, not null */ ZoneOffsetTransitionRule toTransitionRule(ZoneOffset standardOffset, int savingsBeforeSecs) { // optimize stored format if (dayOfMonthIndicator < 0) { if (month != Month.FEBRUARY) { dayOfMonthIndicator = month.maxLength() - 6; } } // build rule ZoneOffsetTransition trans = toTransition(standardOffset, savingsBeforeSecs); return new ZoneOffsetTransitionRule( month, dayOfMonthIndicator, dayOfWeek, time, adjustDays, timeDefinition, standardOffset, trans.getOffsetBefore(), trans.getOffsetAfter()); }
@Override public ZoneOffset getOffset(Instant instant) { long epochSec = instant.getEpochSecond(); // check if using last rules if (lastRules.length > 0 && epochSec > savingsInstantTransitions[savingsInstantTransitions.length - 1]) { int year = findYear(epochSec, wallOffsets[wallOffsets.length - 1]); ZoneOffsetTransition[] transArray = findTransitionArray(year); ZoneOffsetTransition trans = null; for (int i = 0; i < transArray.length; i++) { trans = transArray[i]; if (epochSec < trans.toEpochSecond()) { return trans.getOffsetBefore(); } } return trans.getOffsetAfter(); } // using historic rules int index = Arrays.binarySearch(savingsInstantTransitions, epochSec); if (index < 0) { // switch negative insert position to start of matched range index = -index - 2; } return wallOffsets[index + 1]; }
/** * Converts this to a transition rule. * * @param standardOffset the active standard offset, not null * @param savingsBeforeSecs the active savings before the transition in seconds * @return the transition, not null */ ZoneOffsetTransitionRule toTransitionRule(ZoneOffset standardOffset, int savingsBeforeSecs) { // optimize stored format if (dayOfMonthIndicator < 0) { if (month != Month.FEBRUARY) { dayOfMonthIndicator = month.maxLength() - 6; } } // build rule ZoneOffsetTransition trans = toTransition(standardOffset, savingsBeforeSecs); return new ZoneOffsetTransitionRule( month, dayOfMonthIndicator, dayOfWeek, time, adjustDays, timeDefinition, standardOffset, trans.getOffsetBefore(), trans.getOffsetAfter()); }
@Override public ZoneOffset getOffset(Instant instant) { long epochSec = instant.getEpochSecond(); // check if using last rules if (lastRules.length > 0 && epochSec > savingsInstantTransitions[savingsInstantTransitions.length - 1]) { int year = findYear(epochSec, wallOffsets[wallOffsets.length - 1]); ZoneOffsetTransition[] transArray = findTransitionArray(year); ZoneOffsetTransition trans = null; for (int i = 0; i < transArray.length; i++) { trans = transArray[i]; if (epochSec < trans.toEpochSecond()) { return trans.getOffsetBefore(); } } return trans.getOffsetAfter(); } // using historic rules int index = Arrays.binarySearch(savingsInstantTransitions, epochSec); if (index < 0) { // switch negative insert position to start of matched range index = -index - 2; } return wallOffsets[index + 1]; }
@Override public ChronoZonedDateTime<D> withLaterOffsetAtOverlap() { ZoneOffsetTransition trans = getZone().getRules().getTransition(LocalDateTime.from(this)); if (trans != null) { ZoneOffset offset = trans.getOffsetAfter(); if (offset.equals(getOffset()) == false) { return new ChronoZonedDateTimeImpl<D>(dateTime, offset, zone); } } return this; }
ZoneOffsetKey offfsetKey = ZoneOffsetKey.of(zoneTransitionRule.getOffsetBefore(), zoneTransitionRule.getOffsetAfter());
@Override public ChronoZonedDateTime<D> withLaterOffsetAtOverlap() { ZoneOffsetTransition trans = getZone().getRules().getTransition(LocalDateTime.from(this)); if (trans != null) { ZoneOffset offset = trans.getOffsetAfter(); if (offset.equals(getOffset()) == false) { return new ChronoZonedDateTimeImpl<D>(dateTime, offset, zone); } } return this; }
/** * Finds the offset info for a local date-time and transition. * * @param dt the date-time, not null * @param trans the transition, not null * @return the offset info, not null */ private Object findOffsetInfo(LocalDateTime dt, ZoneOffsetTransition trans) { LocalDateTime localTransition = trans.getDateTimeBefore(); if (trans.isGap()) { if (dt.isBefore(localTransition)) { return trans.getOffsetBefore(); } if (dt.isBefore(trans.getDateTimeAfter())) { return trans; } else { return trans.getOffsetAfter(); } } else { if (dt.isBefore(localTransition) == false) { return trans.getOffsetAfter(); } if (dt.isBefore(trans.getDateTimeAfter())) { return trans.getOffsetBefore(); } else { return trans; } } }
/** * Returns a copy of this date-time changing the zone offset to the * later of the two valid offsets at a local time-line overlap. * <p> * This method only has any effect when the local time-line overlaps, such as * at an autumn daylight savings cutover. In this scenario, there are two * valid offsets for the local date-time. Calling this method will return * a zoned date-time with the later of the two selected. * <p> * If this method is called when it is not an overlap, {@code this} * is returned. * <p> * This instance is immutable and unaffected by this method call. * * @return a {@code ZonedDateTime} based on this date-time with the later offset, not null */ @Override public ZonedDateTime withLaterOffsetAtOverlap() { ZoneOffsetTransition trans = getZone().getRules().getTransition(toLocalDateTime()); if (trans != null) { ZoneOffset laterOffset = trans.getOffsetAfter(); if (laterOffset.equals(offset) == false) { return new ZonedDateTime(dateTime, laterOffset, zone); } } return this; }
/** * Returns a copy of this date-time changing the zone offset to the * later of the two valid offsets at a local time-line overlap. * <p> * This method only has any effect when the local time-line overlaps, such as * at an autumn daylight savings cutover. In this scenario, there are two * valid offsets for the local date-time. Calling this method will return * a zoned date-time with the later of the two selected. * <p> * If this method is called when it is not an overlap, {@code this} * is returned. * <p> * This instance is immutable and unaffected by this method call. * * @return a {@code ZonedDateTime} based on this date-time with the later offset, not null */ @Override public ZonedDateTime withLaterOffsetAtOverlap() { ZoneOffsetTransition trans = getZone().getRules().getTransition(toLocalDateTime()); if (trans != null) { ZoneOffset laterOffset = trans.getOffsetAfter(); if (laterOffset.equals(offset) == false) { return new ZonedDateTime(dateTime, laterOffset, zone); } } return this; }