src/share/classes/java/time/Instant.java

Print this page

        

*** 59,68 **** --- 59,69 ---- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package java.time; + import static java.time.LocalTime.NANOS_PER_SECOND; import static java.time.LocalTime.SECONDS_PER_DAY; import static java.time.LocalTime.SECONDS_PER_HOUR; import static java.time.LocalTime.SECONDS_PER_MINUTE; import static java.time.temporal.ChronoField.INSTANT_SECONDS; import static java.time.temporal.ChronoField.MICRO_OF_SECOND;
*** 74,95 **** import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectStreamException; import java.io.Serializable; ! import java.time.format.DateTimeFormatters; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; - import java.time.temporal.TemporalAdder; import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; - import java.time.temporal.TemporalSubtractor; import java.time.temporal.TemporalUnit; import java.time.temporal.ValueRange; import java.util.Objects; /** --- 75,95 ---- import java.io.DataOutput; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectStreamException; import java.io.Serializable; ! import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import java.time.temporal.Queries; import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAdjuster; + import java.time.temporal.TemporalAmount; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; import java.time.temporal.TemporalUnit; import java.time.temporal.ValueRange; import java.util.Objects; /**
*** 223,236 **** /** * Serialization version. */ private static final long serialVersionUID = -665713676816604388L; - /** - * Constant for nanos per second. - */ - private static final int NANOS_PER_SECOND = 1000_000_000; /** * The number of seconds from the epoch of 1970-01-01T00:00:00Z. */ private final long seconds; --- 223,232 ----
*** 331,342 **** //----------------------------------------------------------------------- /** * Obtains an instance of {@code Instant} from a temporal object. * <p> ! * A {@code TemporalAccessor} represents some form of date and time information. ! * This factory converts the arbitrary temporal object to an instance of {@code Instant}. * <p> * The conversion extracts the {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS} * and {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} fields. * <p> * This method matches the signature of the functional interface {@link TemporalQuery} --- 327,339 ---- //----------------------------------------------------------------------- /** * Obtains an instance of {@code Instant} from a temporal object. * <p> ! * This obtains an instant based on the specified temporal. ! * A {@code TemporalAccessor} represents an arbitrary set of date and time information, ! * which this factory converts to an instance of {@code Instant}. * <p> * The conversion extracts the {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS} * and {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} fields. * <p> * This method matches the signature of the functional interface {@link TemporalQuery}
*** 356,373 **** /** * Obtains an instance of {@code Instant} from a text string such as * {@code 2007-12-03T10:15:30:00}. * <p> * The string must represent a valid instant in UTC and is parsed using ! * {@link DateTimeFormatters#isoInstant()}. * * @param text the text to parse, not null * @return the parsed instant, not null * @throws DateTimeParseException if the text cannot be parsed */ public static Instant parse(final CharSequence text) { ! return DateTimeFormatters.isoInstant().parse(text, Instant::from); } //----------------------------------------------------------------------- /** * Obtains an instance of {@code Instant} using seconds and nanoseconds. --- 353,370 ---- /** * Obtains an instance of {@code Instant} from a text string such as * {@code 2007-12-03T10:15:30:00}. * <p> * The string must represent a valid instant in UTC and is parsed using ! * {@link DateTimeFormatter#ISO_INSTANT}. * * @param text the text to parse, not null * @return the parsed instant, not null * @throws DateTimeParseException if the text cannot be parsed */ public static Instant parse(final CharSequence text) { ! return DateTimeFormatter.ISO_INSTANT.parse(text, Instant::from); } //----------------------------------------------------------------------- /** * Obtains an instance of {@code Instant} using seconds and nanoseconds.
*** 416,426 **** * <li>{@code INSTANT_SECONDS} * </ul> * All other {@code ChronoField} instances will return false. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)} * passing {@code this} as the argument. * Whether the field is supported is determined by the field. * * @param field the field to check, null returns false * @return true if the field is supported on this instant, false if not --- 413,423 ---- * <li>{@code INSTANT_SECONDS} * </ul> * All other {@code ChronoField} instances will return false. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)} * passing {@code this} as the argument. * Whether the field is supported is determined by the field. * * @param field the field to check, null returns false * @return true if the field is supported on this instant, false if not
*** 428,438 **** @Override public boolean isSupported(TemporalField field) { if (field instanceof ChronoField) { return field == INSTANT_SECONDS || field == NANO_OF_SECOND || field == MICRO_OF_SECOND || field == MILLI_OF_SECOND; } ! return field != null && field.doIsSupported(this); } /** * Gets the range of valid values for the specified field. * <p> --- 425,435 ---- @Override public boolean isSupported(TemporalField field) { if (field instanceof ChronoField) { return field == INSTANT_SECONDS || field == NANO_OF_SECOND || field == MICRO_OF_SECOND || field == MILLI_OF_SECOND; } ! return field != null && field.isSupportedBy(this); } /** * Gets the range of valid values for the specified field. * <p>
*** 445,455 **** * The {@link #isSupported(TemporalField) supported fields} will return * appropriate range instances. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)} * passing {@code this} as the argument. * Whether the range can be obtained is determined by the field. * * @param field the field to query the range for, not null * @return the range of valid values for the field, not null --- 442,452 ---- * The {@link #isSupported(TemporalField) supported fields} will return * appropriate range instances. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)} * passing {@code this} as the argument. * Whether the range can be obtained is determined by the field. * * @param field the field to query the range for, not null * @return the range of valid values for the field, not null
*** 473,483 **** * values based on this date-time, except {@code INSTANT_SECONDS} which is too * large to fit in an {@code int} and throws a {@code DateTimeException}. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field --- 470,480 ---- * values based on this date-time, except {@code INSTANT_SECONDS} which is too * large to fit in an {@code int} and throws a {@code DateTimeException}. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field
*** 493,503 **** case MILLI_OF_SECOND: return nanos / 1000_000; case INSTANT_SECONDS: INSTANT_SECONDS.checkValidIntValue(seconds); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return range(field).checkValidIntValue(field.doGet(this), field); } /** * Gets the value of the specified field from this instant as a {@code long}. * <p> --- 490,500 ---- case MILLI_OF_SECOND: return nanos / 1000_000; case INSTANT_SECONDS: INSTANT_SECONDS.checkValidIntValue(seconds); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return range(field).checkValidIntValue(field.getFrom(this), field); } /** * Gets the value of the specified field from this instant as a {@code long}. * <p>
*** 509,519 **** * The {@link #isSupported(TemporalField) supported fields} will return valid * values based on this date-time. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field --- 506,516 ---- * The {@link #isSupported(TemporalField) supported fields} will return valid * values based on this date-time. * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)} * passing {@code this} as the argument. Whether the value can be obtained, * and what the value represents, is determined by the field. * * @param field the field to get, not null * @return the value for the field
*** 529,539 **** case MILLI_OF_SECOND: return nanos / 1000_000; case INSTANT_SECONDS: return seconds; } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.doGet(this); } //----------------------------------------------------------------------- /** * Gets the number of seconds from the Java epoch of 1970-01-01T00:00:00Z. --- 526,536 ---- case MILLI_OF_SECOND: return nanos / 1000_000; case INSTANT_SECONDS: return seconds; } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.getFrom(this); } //----------------------------------------------------------------------- /** * Gets the number of seconds from the Java epoch of 1970-01-01T00:00:00Z.
*** 563,573 **** //------------------------------------------------------------------------- /** * Returns an adjusted copy of this instant. * <p> ! * This returns a new {@code Instant}, based on this one, with the date adjusted. * The adjustment takes place using the specified adjuster strategy object. * Read the documentation of the adjuster to understand what adjustment will be made. * <p> * The result of this method is obtained by invoking the * {@link TemporalAdjuster#adjustInto(Temporal)} method on the --- 560,570 ---- //------------------------------------------------------------------------- /** * Returns an adjusted copy of this instant. * <p> ! * This returns an {@code Instant}, based on this one, with the instant adjusted. * The adjustment takes place using the specified adjuster strategy object. * Read the documentation of the adjuster to understand what adjustment will be made. * <p> * The result of this method is obtained by invoking the * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
*** 586,596 **** } /** * Returns a copy of this instant with the specified field set to a new value. * <p> ! * This returns a new {@code Instant}, based on this one, with the value * for the specified field changed. * If it is not possible to set the value, because the field is not supported or for * some other reason, an exception is thrown. * <p> * If the field is a {@link ChronoField} then the adjustment is implemented here. --- 583,593 ---- } /** * Returns a copy of this instant with the specified field set to a new value. * <p> ! * This returns an {@code Instant}, based on this one, with the value * for the specified field changed. * If it is not possible to set the value, because the field is not supported or for * some other reason, an exception is thrown. * <p> * If the field is a {@link ChronoField} then the adjustment is implemented here.
*** 614,624 **** * then a {@code DateTimeException} will be thrown. * <p> * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.doWith(Temporal, long)} * passing {@code this} as the argument. In this case, the field determines * whether and how to adjust the instant. * <p> * This instance is immutable and unaffected by this method call. * --- 611,621 ---- * then a {@code DateTimeException} will be thrown. * <p> * All other {@code ChronoField} instances will throw a {@code DateTimeException}. * <p> * If the field is not a {@code ChronoField}, then the result of this method ! * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)} * passing {@code this} as the argument. In this case, the field determines * whether and how to adjust the instant. * <p> * This instance is immutable and unaffected by this method call. *
*** 645,672 **** case NANO_OF_SECOND: return (newValue != nanos ? create(seconds, (int) newValue) : this); case INSTANT_SECONDS: return (newValue != seconds ? create(newValue, nanos) : this); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.doWith(this, newValue); } //----------------------------------------------------------------------- /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override ! public Instant plus(TemporalAdder adder) { ! return (Instant) adder.addTo(this); } /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override public Instant plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) { --- 642,775 ---- case NANO_OF_SECOND: return (newValue != nanos ? create(seconds, (int) newValue) : this); case INSTANT_SECONDS: return (newValue != seconds ? create(newValue, nanos) : this); } throw new DateTimeException("Unsupported field: " + field.getName()); } ! return field.adjustInto(this, newValue); ! } ! ! //----------------------------------------------------------------------- ! /** ! * Returns a copy of this {@code Instant} truncated to the specified unit. ! * <p> ! * Truncating the instant returns a copy of the original with fields ! * smaller than the specified unit set to zero. ! * The fields are calculated on the basis of using a UTC offset as seen ! * in {@code toString}. ! * For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will ! * round down to the nearest minute, setting the seconds and nanoseconds to zero. ! * <p> ! * The unit must have a {@linkplain TemporalUnit#getDuration() duration} ! * that divides into the length of a standard day without remainder. ! * This includes all supplied time units on {@link ChronoUnit} and ! * {@link ChronoUnit#DAYS DAYS}. Other units throw an exception. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param unit the unit to truncate to, not null ! * @return an {@code Instant} based on this instant with the time truncated, not null ! * @throws DateTimeException if the unit is invalid for truncation ! */ ! public Instant truncatedTo(TemporalUnit unit) { ! if (unit == ChronoUnit.NANOS) { ! return this; ! } ! Duration unitDur = unit.getDuration(); ! if (unitDur.getSeconds() > LocalTime.SECONDS_PER_DAY) { ! throw new DateTimeException("Unit is too large to be used for truncation"); ! } ! long dur = unitDur.toNanos(); ! if ((LocalTime.NANOS_PER_DAY % dur) != 0) { ! throw new DateTimeException("Unit must divide into a standard day without remainder"); ! } ! long nod = (seconds % LocalTime.SECONDS_PER_DAY) * LocalTime.NANOS_PER_SECOND + nanos; ! long result = (nod / dur) * dur; ! return plusNanos(result - nod); } //----------------------------------------------------------------------- /** ! * Returns a copy of this instant with the specified amount added. ! * <p> ! * This returns an {@code Instant}, based on this one, with the specified amount added. ! * The amount is typically {@link Duration} but may be any other type implementing ! * the {@link TemporalAmount} interface. ! * <p> ! * The calculation is delegated to the amount object by calling ! * {@link TemporalAmount#addTo(Temporal)}. The amount implementation is free ! * to implement the addition in any way it wishes, however it typically ! * calls back to {@link #plus(long, TemporalUnit)}. Consult the documentation ! * of the amount implementation to determine if it can be successfully added. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToAdd the amount to add, not null ! * @return an {@code Instant} based on this instant with the addition made, not null ! * @throws DateTimeException if the addition cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override ! public Instant plus(TemporalAmount amountToAdd) { ! return (Instant) amountToAdd.addTo(this); } /** ! * Returns a copy of this instant with the specified amount added. ! * <p> ! * This returns an {@code Instant}, based on this one, with the amount ! * in terms of the unit added. If it is not possible to add the amount, because the ! * unit is not supported or for some other reason, an exception is thrown. ! * <p> ! * If the field is a {@link ChronoUnit} then the addition is implemented here. ! * The supported fields behave as follows: ! * <ul> ! * <li>{@code NANOS} - ! * Returns a {@code Instant} with the specified number of nanoseconds added. ! * This is equivalent to {@link #plusNanos(long)}. ! * <li>{@code MICROS} - ! * Returns a {@code Instant} with the specified number of microseconds added. ! * This is equivalent to {@link #plusNanos(long)} with the amount ! * multiplied by 1,000. ! * <li>{@code MILLIS} - ! * Returns a {@code Instant} with the specified number of milliseconds added. ! * This is equivalent to {@link #plusNanos(long)} with the amount ! * multiplied by 1,000,000. ! * <li>{@code SECONDS} - ! * Returns a {@code Instant} with the specified number of seconds added. ! * This is equivalent to {@link #plusSeconds(long)}. ! * <li>{@code MINUTES} - ! * Returns a {@code Instant} with the specified number of minutes added. ! * This is equivalent to {@link #plusSeconds(long)} with the amount ! * multiplied by 60. ! * <li>{@code HOURS} - ! * Returns a {@code Instant} with the specified number of hours added. ! * This is equivalent to {@link #plusSeconds(long)} with the amount ! * multiplied by 3,600. ! * <li>{@code HALF_DAYS} - ! * Returns a {@code Instant} with the specified number of half-days added. ! * This is equivalent to {@link #plusSeconds(long)} with the amount ! * multiplied by 43,200 (12 hours). ! * <li>{@code DAYS} - ! * Returns a {@code Instant} with the specified number of days added. ! * This is equivalent to {@link #plusSeconds(long)} with the amount ! * multiplied by 86,400 (24 hours). ! * </ul> ! * <p> ! * All other {@code ChronoUnit} instances will throw a {@code DateTimeException}. ! * <p> ! * If the field is not a {@code ChronoUnit}, then the result of this method ! * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)} ! * passing {@code this} as the argument. In this case, the unit determines ! * whether and how to perform the addition. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToAdd the amount of the unit to add to the result, may be negative ! * @param unit the unit of the amount to add, not null ! * @return an {@code Instant} based on this instant with the specified amount added, not null ! * @throws DateTimeException if the addition cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override public Instant plus(long amountToAdd, TemporalUnit unit) { if (unit instanceof ChronoUnit) { switch ((ChronoUnit) unit) {
*** 679,689 **** case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2)); case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.doPlus(this, amountToAdd); } //----------------------------------------------------------------------- /** * Returns a copy of this instant with the specified duration in seconds added. --- 782,792 ---- case HALF_DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY / 2)); case DAYS: return plusSeconds(Math.multiplyExact(amountToAdd, SECONDS_PER_DAY)); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.addTo(this, amountToAdd); } //----------------------------------------------------------------------- /** * Returns a copy of this instant with the specified duration in seconds added.
*** 749,771 **** return ofEpochSecond(epochSec, nanoAdjustment); } //----------------------------------------------------------------------- /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override ! public Instant minus(TemporalSubtractor subtractor) { ! return (Instant) subtractor.subtractFrom(this); } /** ! * {@inheritDoc} ! * @throws DateTimeException {@inheritDoc} ! * @throws ArithmeticException {@inheritDoc} */ @Override public Instant minus(long amountToSubtract, TemporalUnit unit) { return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); } --- 852,902 ---- return ofEpochSecond(epochSec, nanoAdjustment); } //----------------------------------------------------------------------- /** ! * Returns a copy of this instant with the specified amount subtracted. ! * <p> ! * This returns an {@code Instant}, based on this one, with the specified amount subtracted. ! * The amount is typically {@link Duration} but may be any other type implementing ! * the {@link TemporalAmount} interface. ! * <p> ! * The calculation is delegated to the amount object by calling ! * {@link TemporalAmount#subtractFrom(Temporal)}. The amount implementation is free ! * to implement the subtraction in any way it wishes, however it typically ! * calls back to {@link #minus(long, TemporalUnit)}. Consult the documentation ! * of the amount implementation to determine if it can be successfully subtracted. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToSubtract the amount to subtract, not null ! * @return an {@code Instant} based on this instant with the subtraction made, not null ! * @throws DateTimeException if the subtraction cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override ! public Instant minus(TemporalAmount amountToSubtract) { ! return (Instant) amountToSubtract.subtractFrom(this); } /** ! * Returns a copy of this instant with the specified amount subtracted. ! * <p> ! * This returns a {@code Instant}, based on this one, with the amount ! * in terms of the unit subtracted. If it is not possible to subtract the amount, ! * because the unit is not supported or for some other reason, an exception is thrown. ! * <p> ! * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated. ! * See that method for a full description of how addition, and thus subtraction, works. ! * <p> ! * This instance is immutable and unaffected by this method call. ! * ! * @param amountToSubtract the amount of the unit to subtract from the result, may be negative ! * @param unit the unit of the amount to subtract, not null ! * @return an {@code Instant} based on this instant with the specified amount subtracted, not null ! * @throws DateTimeException if the subtraction cannot be made ! * @throws ArithmeticException if numeric overflow occurs */ @Override public Instant minus(long amountToSubtract, TemporalUnit unit) { return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit)); }
*** 846,856 **** public <R> R query(TemporalQuery<R> query) { if (query == Queries.precision()) { return (R) NANOS; } // inline TemporalAccessor.super.query(query) as an optimization ! if (query == Queries.chrono() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) { return null; } return query.queryFrom(this); } --- 977,987 ---- public <R> R query(TemporalQuery<R> query) { if (query == Queries.precision()) { return (R) NANOS; } // inline TemporalAccessor.super.query(query) as an optimization ! if (query == Queries.chronology() || query == Queries.zoneId() || query == Queries.zone() || query == Queries.offset()) { return null; } return query.queryFrom(this); }
*** 943,953 **** case HALF_DAYS: return secondsUntil(end) / (12 * SECONDS_PER_HOUR); case DAYS: return secondsUntil(end) / (SECONDS_PER_DAY); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.between(this, endInstant).getAmount(); } private long nanosUntil(Instant end) { long secs = Math.multiplyExact(secondsUntil(end), NANOS_PER_SECOND); return Math.addExact(secs, end.nanos - nanos); --- 1074,1084 ---- case HALF_DAYS: return secondsUntil(end) / (12 * SECONDS_PER_HOUR); case DAYS: return secondsUntil(end) / (SECONDS_PER_DAY); } throw new DateTimeException("Unsupported unit: " + unit.getName()); } ! return unit.between(this, endInstant); } private long nanosUntil(Instant end) { long secs = Math.multiplyExact(secondsUntil(end), NANOS_PER_SECOND); return Math.addExact(secs, end.nanos - nanos);
*** 957,966 **** --- 1088,1134 ---- return Math.subtractExact(end.seconds, seconds); } //----------------------------------------------------------------------- /** + * Combines this instant with an offset to create an {@code OffsetDateTime}. + * <p> + * This returns an {@code OffsetDateTime} formed from this instant at the + * specified offset from UTC/Greenwich. An exception will be thrown if the + * instant is too large to fit into an offset date-time. + * <p> + * This method is equivalent to + * {@link OffsetDateTime#ofInstant(Instant, ZoneId) OffsetDateTime.ofInstant(this, offset)}. + * + * @param offset the offset to combine with, not null + * @return the offset date-time formed from this instant and the specified offset, not null + * @throws DateTimeException if the result exceeds the supported range + */ + public OffsetDateTime atOffset(ZoneOffset offset) { + return OffsetDateTime.ofInstant(this, offset); + } + + /** + * Combines this instant with a time-zone to create a {@code ZonedDateTime}. + * <p> + * This returns an {@code ZonedDateTime} formed from this instant at the + * specified time-zone. An exception will be thrown if the instant is too + * large to fit into a zoned date-time. + * <p> + * This method is equivalent to + * {@link ZonedDateTime#ofInstant(Instant, ZoneId) ZonedDateTime.ofInstant(this, zone)}. + * + * @param zone the zone to combine with, not null + * @return the zoned date-time formed from this instant and the specified zone, not null + * @throws DateTimeException if the result exceeds the supported range + */ + public ZonedDateTime atZone(ZoneId zone) { + return ZonedDateTime.ofInstant(this, zone); + } + + //----------------------------------------------------------------------- + /** * Converts this instant to the number of milliseconds from the epoch * of 1970-01-01T00:00:00Z. * <p> * If this instant represents a point on the time-line too far in the future * or past to fit in a {@code long} milliseconds, then an exception is thrown.
*** 1057,1073 **** //----------------------------------------------------------------------- /** * A string representation of this instant using ISO-8601 representation. * <p> ! * The format used is the same as {@link DateTimeFormatters#isoInstant()}. * * @return an ISO-8601 representation of this instant, not null */ @Override public String toString() { ! return DateTimeFormatters.isoInstant().print(this); } // ----------------------------------------------------------------------- /** * Writes the object using a --- 1225,1241 ---- //----------------------------------------------------------------------- /** * A string representation of this instant using ISO-8601 representation. * <p> ! * The format used is the same as {@link DateTimeFormatter#ISO_INSTANT}. * * @return an ISO-8601 representation of this instant, not null */ @Override public String toString() { ! return DateTimeFormatter.ISO_INSTANT.format(this); } // ----------------------------------------------------------------------- /** * Writes the object using a