OffsetDate.java

  1. /*
  2.  * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
  3.  *
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions are met:
  8.  *
  9.  *  * Redistributions of source code must retain the above copyright notice,
  10.  *    this list of conditions and the following disclaimer.
  11.  *
  12.  *  * Redistributions in binary form must reproduce the above copyright notice,
  13.  *    this list of conditions and the following disclaimer in the documentation
  14.  *    and/or other materials provided with the distribution.
  15.  *
  16.  *  * Neither the name of JSR-310 nor the names of its contributors
  17.  *    may be used to endorse or promote products derived from this software
  18.  *    without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24.  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28.  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29.  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30.  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31.  */
  32. package org.threeten.extra;

  33. import static java.time.temporal.ChronoField.EPOCH_DAY;
  34. import static java.time.temporal.ChronoField.OFFSET_SECONDS;
  35. import static java.time.temporal.ChronoUnit.DAYS;

  36. import java.io.Serializable;
  37. import java.time.Clock;
  38. import java.time.DateTimeException;
  39. import java.time.DayOfWeek;
  40. import java.time.Instant;
  41. import java.time.LocalDate;
  42. import java.time.LocalTime;
  43. import java.time.Month;
  44. import java.time.MonthDay;
  45. import java.time.OffsetDateTime;
  46. import java.time.Period;
  47. import java.time.ZoneId;
  48. import java.time.ZoneOffset;
  49. import java.time.chrono.IsoChronology;
  50. import java.time.format.DateTimeFormatter;
  51. import java.time.format.DateTimeParseException;
  52. import java.time.temporal.ChronoField;
  53. import java.time.temporal.ChronoUnit;
  54. import java.time.temporal.Temporal;
  55. import java.time.temporal.TemporalAccessor;
  56. import java.time.temporal.TemporalAdjuster;
  57. import java.time.temporal.TemporalAdjusters;
  58. import java.time.temporal.TemporalAmount;
  59. import java.time.temporal.TemporalField;
  60. import java.time.temporal.TemporalQueries;
  61. import java.time.temporal.TemporalQuery;
  62. import java.time.temporal.TemporalUnit;
  63. import java.time.temporal.UnsupportedTemporalTypeException;
  64. import java.time.temporal.ValueRange;
  65. import java.time.zone.ZoneRules;
  66. import java.util.Objects;

  67. import org.joda.convert.FromString;
  68. import org.joda.convert.ToString;

  69. /**
  70.  * A date with an offset from UTC/Greenwich in the ISO-8601 calendar system,
  71.  * such as {@code 2007-12-03+01:00}.
  72.  * <p>
  73.  * {@code OffsetDate} is an immutable date-time object that represents a date, often viewed
  74.  * as year-month-day-offset. This object can also access other date fields such as
  75.  * day-of-year, day-of-week and week-of-year.
  76.  * <p>
  77.  * This class does not store or represent a time.
  78.  * For example, the value "2nd October 2007 +02:00" can be stored
  79.  * in an {@code OffsetDate}.
  80.  *
  81.  * <h3>Implementation Requirements:</h3>
  82.  * This class is immutable and thread-safe.
  83.  * <p>
  84.  * This class must be treated as a value type. Do not synchronize, rely on the
  85.  * identity hash code or use the distinction between equals() and ==.
  86.  */
  87. public final class OffsetDate
  88.         implements Temporal, TemporalAdjuster, Comparable<OffsetDate>, Serializable {

  89.     /**
  90.      * The minimum supported {@code OffsetDate}, '-999999999-01-01+18:00'.
  91.      * This is the minimum local date in the maximum offset
  92.      * (larger offsets are earlier on the time-line).
  93.      * This combines {@link LocalDate#MIN} and {@link ZoneOffset#MAX}.
  94.      * This could be used by an application as a "far past" date.
  95.      */
  96.     public static final OffsetDate MIN = OffsetDate.of(LocalDate.MIN, ZoneOffset.MAX);
  97.     /**
  98.      * The maximum supported {@code OffsetDate}, '+999999999-12-31-18:00'.
  99.      * This is the maximum local date in the minimum offset
  100.      * (larger negative offsets are later on the time-line).
  101.      * This combines {@link LocalDate#MAX} and {@link ZoneOffset#MIN}.
  102.      * This could be used by an application as a "far future" date.
  103.      */
  104.     public static final OffsetDate MAX = OffsetDate.of(LocalDate.MAX, ZoneOffset.MIN);

  105.     /**
  106.      * Serialization version.
  107.      */
  108.     private static final long serialVersionUID = -4382054179074397774L;

  109.     /**
  110.      * The number of seconds per day.
  111.      */
  112.     private static final long SECONDS_PER_DAY = 86400;

  113.     /**
  114.      * The local date.
  115.      */
  116.     private final LocalDate date;
  117.     /**
  118.      * The offset from UTC/Greenwich.
  119.      */
  120.     private final ZoneOffset offset;

  121.     //-----------------------------------------------------------------------
  122.     /**
  123.      * Obtains the current date from the system clock in the default time-zone.
  124.      * <p>
  125.      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
  126.      * time-zone to obtain the current date.
  127.      * The offset will be calculated from the time-zone in the clock.
  128.      * <p>
  129.      * Using this method will prevent the ability to use an alternate clock for testing
  130.      * because the clock is hard-coded.
  131.      *
  132.      * @return the current date using the system clock, not null
  133.      */
  134.     public static OffsetDate now() {
  135.         return now(Clock.systemDefaultZone());
  136.     }

  137.     /**
  138.      * Obtains the current date from the system clock in the specified time-zone.
  139.      * <p>
  140.      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
  141.      * Specifying the time-zone avoids dependence on the default time-zone.
  142.      * The offset will be calculated from the specified time-zone.
  143.      * <p>
  144.      * Using this method will prevent the ability to use an alternate clock for testing
  145.      * because the clock is hard-coded.
  146.      *
  147.      * @param zone  the zone ID to use, not null
  148.      * @return the current date using the system clock, not null
  149.      */
  150.     public static OffsetDate now(ZoneId zone) {
  151.         return now(Clock.system(zone));
  152.     }

  153.     /**
  154.      * Obtains the current date from the specified clock.
  155.      * <p>
  156.      * This will query the specified clock to obtain the current date - today.
  157.      * The offset will be calculated from the time-zone in the clock.
  158.      * <p>
  159.      * Using this method allows the use of an alternate clock for testing.
  160.      * The alternate clock may be introduced using {@link Clock dependency injection}.
  161.      *
  162.      * @param clock  the clock to use, not null
  163.      * @return the current date, not null
  164.      */
  165.     public static OffsetDate now(Clock clock) {
  166.         Objects.requireNonNull(clock, "clock");
  167.         final Instant now = clock.instant();  // called once
  168.         return ofInstant(now, clock.getZone().getRules().getOffset(now));
  169.     }

  170.     //-----------------------------------------------------------------------
  171.     /**
  172.      * Obtains an instance of {@code OffsetDate} from a local date and an offset.
  173.      *
  174.      * @param date  the local date, not null
  175.      * @param offset  the zone offset, not null
  176.      * @return the offset date, not null
  177.      */
  178.     public static OffsetDate of(LocalDate date, ZoneOffset offset) {
  179.         return new OffsetDate(date, offset);
  180.     }

  181.     /**
  182.      * Obtains an instance of {@code OffsetDate} from a year, month, day
  183.      * and offset.
  184.      * <p>
  185.      * This creates an offset date with the four specified fields.
  186.      * <p>
  187.      * This method exists primarily for writing test cases.
  188.      * Non test-code will typically use other methods to create an offset time.
  189.      *
  190.      * @param year  the year to represent, from MIN_YEAR to MAX_YEAR
  191.      * @param month  the month-of-year to represent, from 1 (January) to 12 (December)
  192.      * @param dayOfMonth  the day-of-month to represent, from 1 to 31
  193.      * @param offset  the zone offset, not null
  194.      * @return the offset date, not null
  195.      * @throws DateTimeException if the value of any field is out of range, or
  196.      *  if the day-of-month is invalid for the month-year
  197.      */
  198.     public static OffsetDate of(int year, int month, int dayOfMonth, ZoneOffset offset) {
  199.         LocalDate d = LocalDate.of(year, month, dayOfMonth);
  200.         return new OffsetDate(d, offset);
  201.     }

  202.     //-----------------------------------------------------------------------
  203.     /**
  204.      * Obtains an instance of {@code OffsetDate} from an {@code Instant} and zone ID.
  205.      * <p>
  206.      * This creates an offset date with the same instant as midnight at the
  207.      * start of day of the instant specified.
  208.      * Finding the offset from UTC/Greenwich is simple as there is only one valid
  209.      * offset for each instant.
  210.      *
  211.      * @param instant  the instant to create the time from, not null
  212.      * @param zone  the time-zone, which may be an offset, not null
  213.      * @return the offset time, not null
  214.      */
  215.     public static OffsetDate ofInstant(Instant instant, ZoneId zone) {
  216.         Objects.requireNonNull(instant, "instant");
  217.         Objects.requireNonNull(zone, "zone");
  218.         ZoneRules rules = zone.getRules();
  219.         ZoneOffset offset = rules.getOffset(instant);
  220.         long epochSec = instant.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
  221.         long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY);
  222.         LocalDate date = LocalDate.ofEpochDay(epochDay);
  223.         return new OffsetDate(date, offset);
  224.     }

  225.     //-----------------------------------------------------------------------
  226.     /**
  227.      * Obtains an instance of {@code OffsetDate} from a temporal object.
  228.      * <p>
  229.      * A {@code TemporalAccessor} represents some form of date and time information.
  230.      * This factory converts the arbitrary temporal object to an instance of {@code OffsetDate}.
  231.      * <p>
  232.      * The conversion extracts and combines {@code LocalDate} and {@code ZoneOffset}.
  233.      * <p>
  234.      * This method matches the signature of the functional interface {@link TemporalQuery}
  235.      * allowing it to be used in queries via method reference, {@code OffsetDate::from}.
  236.      *
  237.      * @param temporal  the temporal object to convert, not null
  238.      * @return the offset date, not null
  239.      * @throws DateTimeException if unable to convert to an {@code OffsetDate}
  240.      */
  241.     public static OffsetDate from(TemporalAccessor temporal) {
  242.         if (temporal instanceof OffsetDate) {
  243.             return (OffsetDate) temporal;
  244.         }
  245.         try {
  246.             LocalDate date = LocalDate.from(temporal);
  247.             ZoneOffset offset = ZoneOffset.from(temporal);
  248.             return new OffsetDate(date, offset);
  249.         } catch (DateTimeException ex) {
  250.             throw new DateTimeException("Unable to obtain OffsetDate from TemporalAccessor: " + temporal.getClass(), ex);
  251.         }
  252.     }

  253.     //-----------------------------------------------------------------------
  254.     /**
  255.      * Obtains an instance of {@code OffsetDate} from a text string such as {@code 2007-12-03+01:00}.
  256.      * <p>
  257.      * The string must represent a valid date and is parsed using
  258.      * {@link DateTimeFormatter#ISO_OFFSET_DATE}.
  259.      *
  260.      * @param text  the text to parse such as "2007-12-03+01:00", not null
  261.      * @return the parsed offset date, not null
  262.      * @throws DateTimeParseException if the text cannot be parsed
  263.      */
  264.     @FromString
  265.     public static OffsetDate parse(CharSequence text) {
  266.         return parse(text, DateTimeFormatter.ISO_OFFSET_DATE);
  267.     }

  268.     /**
  269.      * Obtains an instance of {@code OffsetDate} from a text string using a specific formatter.
  270.      * <p>
  271.      * The text is parsed using the formatter, returning a date.
  272.      *
  273.      * @param text  the text to parse, not null
  274.      * @param formatter  the formatter to use, not null
  275.      * @return the parsed offset date, not null
  276.      * @throws DateTimeParseException if the text cannot be parsed
  277.      */
  278.     public static OffsetDate parse(CharSequence text, DateTimeFormatter formatter) {
  279.         Objects.requireNonNull(formatter, "formatter");
  280.         return formatter.parse(text, OffsetDate::from);
  281.     }

  282.     //-----------------------------------------------------------------------
  283.     /**
  284.      * Constructor.
  285.      *
  286.      * @param date  the local date, not null
  287.      * @param offset  the zone offset, not null
  288.      */
  289.     private OffsetDate(LocalDate date, ZoneOffset offset) {
  290.         this.date = Objects.requireNonNull(date, "date");
  291.         this.offset = Objects.requireNonNull(offset, "offset");
  292.     }

  293.     /**
  294.      * Validates the input.
  295.      *
  296.      * @return the valid object, not null
  297.      */
  298.     private Object readResolve() {
  299.         return of(date, offset);
  300.     }

  301.     /**
  302.      * Returns a new date based on this one, returning {@code this} where possible.
  303.      *
  304.      * @param date  the date to create with, not null
  305.      * @param offset  the zone offset to create with, not null
  306.      */
  307.     private OffsetDate with(LocalDate date, ZoneOffset offset) {
  308.         if (this.date == date && this.offset.equals(offset)) {
  309.             return this;
  310.         }
  311.         return new OffsetDate(date, offset);
  312.     }

  313.     //-----------------------------------------------------------------------
  314.     /**
  315.      * Checks if the specified field is supported.
  316.      * <p>
  317.      * This checks if this date can be queried for the specified field.
  318.      * If false, then calling the {@link #range(TemporalField) range},
  319.      * {@link #get(TemporalField) get} and {@link #with(TemporalField, long)}
  320.      * methods will throw an exception.
  321.      * <p>
  322.      * If the field is a {@link ChronoField} then the query is implemented here.
  323.      * The supported fields are:
  324.      * <ul>
  325.      * <li>{@code DAY_OF_WEEK}
  326.      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}
  327.      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}
  328.      * <li>{@code DAY_OF_MONTH}
  329.      * <li>{@code DAY_OF_YEAR}
  330.      * <li>{@code EPOCH_DAY}
  331.      * <li>{@code ALIGNED_WEEK_OF_MONTH}
  332.      * <li>{@code ALIGNED_WEEK_OF_YEAR}
  333.      * <li>{@code MONTH_OF_YEAR}
  334.      * <li>{@code PROLEPTIC_MONTH}
  335.      * <li>{@code YEAR_OF_ERA}
  336.      * <li>{@code YEAR}
  337.      * <li>{@code ERA}
  338.      * <li>{@code OFFSET_SECONDS}
  339.      * </ul>
  340.      * All other {@code ChronoField} instances will return false.
  341.      * <p>
  342.      * If the field is not a {@code ChronoField}, then the result of this method
  343.      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
  344.      * passing {@code this} as the argument.
  345.      * Whether the field is supported is determined by the field.
  346.      *
  347.      * @param field  the field to check, null returns false
  348.      * @return true if the field is supported on this date, false if not
  349.      */
  350.     @Override
  351.     public boolean isSupported(TemporalField field) {
  352.         if (field instanceof ChronoField) {
  353.             return field.isDateBased() || field == OFFSET_SECONDS;
  354.         }
  355.         return field != null && field.isSupportedBy(this);
  356.     }

  357.     /**
  358.      * Checks if the specified unit is supported.
  359.      * <p>
  360.      * This checks if the specified unit can be added to, or subtracted from, this date.
  361.      * If false, then calling the {@link #plus(long, TemporalUnit)} and
  362.      * {@link #minus(long, TemporalUnit) minus} methods will throw an exception.
  363.      * <p>
  364.      * If the unit is a {@link ChronoUnit} then the query is implemented here.
  365.      * The supported units are:
  366.      * <ul>
  367.      * <li>{@code DAYS}
  368.      * <li>{@code WEEKS}
  369.      * <li>{@code MONTHS}
  370.      * <li>{@code YEARS}
  371.      * <li>{@code DECADES}
  372.      * <li>{@code CENTURIES}
  373.      * <li>{@code MILLENNIA}
  374.      * <li>{@code ERAS}
  375.      * </ul>
  376.      * All other {@code ChronoUnit} instances will return false.
  377.      * <p>
  378.      * If the unit is not a {@code ChronoUnit}, then the result of this method
  379.      * is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}
  380.      * passing {@code this} as the argument.
  381.      * Whether the unit is supported is determined by the unit.
  382.      *
  383.      * @param unit  the unit to check, null returns false
  384.      * @return true if the unit can be added/subtracted, false if not
  385.      */
  386.     @Override
  387.     public boolean isSupported(TemporalUnit unit) {
  388.         if (unit instanceof ChronoUnit) {
  389.             return unit.isDateBased();
  390.         }
  391.         return unit != null && unit.isSupportedBy(this);
  392.     }

  393.     //-----------------------------------------------------------------------
  394.     /**
  395.      * Gets the range of valid values for the specified field.
  396.      * <p>
  397.      * The range object expresses the minimum and maximum valid values for a field.
  398.      * This date is used to enhance the accuracy of the returned range.
  399.      * If it is not possible to return the range, because the field is not supported
  400.      * or for some other reason, an exception is thrown.
  401.      * <p>
  402.      * If the field is a {@link ChronoField} then the query is implemented here.
  403.      * The {@link #isSupported(TemporalField) supported fields} will return
  404.      * appropriate range instances.
  405.      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
  406.      * <p>
  407.      * If the field is not a {@code ChronoField}, then the result of this method
  408.      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
  409.      * passing {@code this} as the argument.
  410.      * Whether the range can be obtained is determined by the field.
  411.      *
  412.      * @param field  the field to query the range for, not null
  413.      * @return the range of valid values for the field, not null
  414.      * @throws DateTimeException if the range for the field cannot be obtained
  415.      * @throws UnsupportedTemporalTypeException if the field is not supported
  416.      */
  417.     @Override
  418.     public ValueRange range(TemporalField field) {
  419.         if (field instanceof ChronoField) {
  420.             if (field == OFFSET_SECONDS) {
  421.                 return field.range();
  422.             }
  423.             return date.range(field);
  424.         }
  425.         return field.rangeRefinedBy(this);
  426.     }

  427.     /**
  428.      * Gets the value of the specified field from this date as an {@code int}.
  429.      * <p>
  430.      * This queries this date for the value for the specified field.
  431.      * The returned value will always be within the valid range of values for the field.
  432.      * If it is not possible to return the value, because the field is not supported
  433.      * or for some other reason, an exception is thrown.
  434.      * <p>
  435.      * If the field is a {@link ChronoField} then the query is implemented here.
  436.      * The {@link #isSupported(TemporalField) supported fields} will return valid
  437.      * values based on this date, except {@code EPOCH_DAY} and {@code PROLEPTIC_MONTH}
  438.      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
  439.      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
  440.      * <p>
  441.      * If the field is not a {@code ChronoField}, then the result of this method
  442.      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
  443.      * passing {@code this} as the argument. Whether the value can be obtained,
  444.      * and what the value represents, is determined by the field.
  445.      *
  446.      * @param field  the field to get, not null
  447.      * @return the value for the field
  448.      * @throws DateTimeException if a value for the field cannot be obtained or
  449.      *  the value is outside the range of valid values for the field
  450.      * @throws UnsupportedTemporalTypeException if the field is not supported or
  451.      *  the range of values exceeds an {@code int}
  452.      * @throws ArithmeticException if numeric overflow occurs
  453.      */
  454.     @Override  // override for Javadoc
  455.     public int get(TemporalField field) {
  456.         return Temporal.super.get(field);
  457.     }

  458.     /**
  459.      * Gets the value of the specified field from this date as a {@code long}.
  460.      * <p>
  461.      * This queries this date for the value for the specified field.
  462.      * If it is not possible to return the value, because the field is not supported
  463.      * or for some other reason, an exception is thrown.
  464.      * <p>
  465.      * If the field is a {@link ChronoField} then the query is implemented here.
  466.      * The {@link #isSupported(TemporalField) supported fields} will return valid
  467.      * values based on this date.
  468.      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
  469.      * <p>
  470.      * If the field is not a {@code ChronoField}, then the result of this method
  471.      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
  472.      * passing {@code this} as the argument. Whether the value can be obtained,
  473.      * and what the value represents, is determined by the field.
  474.      *
  475.      * @param field  the field to get, not null
  476.      * @return the value for the field
  477.      * @throws DateTimeException if a value for the field cannot be obtained
  478.      * @throws UnsupportedTemporalTypeException if the field is not supported
  479.      * @throws ArithmeticException if numeric overflow occurs
  480.      */
  481.     @Override
  482.     public long getLong(TemporalField field) {
  483.         if (field instanceof ChronoField) {
  484.             if (field == OFFSET_SECONDS) {
  485.                 return getOffset().getTotalSeconds();
  486.             }
  487.             return date.getLong(field);
  488.         }
  489.         return field.getFrom(this);
  490.     }

  491.     //-----------------------------------------------------------------------
  492.     /**
  493.      * Gets the zone offset, such as '+01:00'.
  494.      * <p>
  495.      * This is the offset of the local date from UTC/Greenwich.
  496.      *
  497.      * @return the zone offset, not null
  498.      */
  499.     public ZoneOffset getOffset() {
  500.         return offset;
  501.     }

  502.     /**
  503.      * Returns a copy of this {@code OffsetDate} with the specified offset ensuring
  504.      * that the result has the same local date.
  505.      * <p>
  506.      * This method returns an object with the same {@code LocalDate} and the specified {@code ZoneOffset}.
  507.      * No calculation is needed or performed.
  508.      * For example, if this time represents {@code 2007-12-03+02:00} and the offset specified is
  509.      * {@code +03:00}, then this method will return {@code 2007-12-03+03:00}.
  510.      * <p>
  511.      * This instance is immutable and unaffected by this method call.
  512.      *
  513.      * @param offset  the zone offset to change to, not null
  514.      * @return an {@code OffsetDate} based on this date with the requested offset, not null
  515.      */
  516.     public OffsetDate withOffsetSameLocal(ZoneOffset offset) {
  517.         Objects.requireNonNull(offset, "offset");
  518.         return with(date, offset);
  519.     }

  520.     //-----------------------------------------------------------------------
  521.     /**
  522.      * Gets the {@code LocalDate} part of this date.
  523.      * <p>
  524.      * This returns a {@code LocalDate} with the same year, month and day
  525.      * as this date.
  526.      *
  527.      * @return the date part of this date, not null
  528.      */
  529.     public LocalDate toLocalDate() {
  530.         return date;
  531.     }

  532.     //-----------------------------------------------------------------------
  533.     /**
  534.      * Gets the year field.
  535.      * <p>
  536.      * This method returns the primitive {@code int} value for the year.
  537.      * <p>
  538.      * The year returned by this method is proleptic as per {@code get(YEAR)}.
  539.      * To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}.
  540.      *
  541.      * @return the year, from MIN_YEAR to MAX_YEAR
  542.      */
  543.     public int getYear() {
  544.         return date.getYear();
  545.     }

  546.     /**
  547.      * Gets the month-of-year field from 1 to 12.
  548.      * <p>
  549.      * This method returns the month as an {@code int} from 1 to 12.
  550.      * Application code is frequently clearer if the enum {@link Month}
  551.      * is used by calling {@link #getMonth()}.
  552.      *
  553.      * @return the month-of-year, from 1 to 12
  554.      * @see #getMonth()
  555.      */
  556.     public int getMonthValue() {
  557.         return date.getMonthValue();
  558.     }

  559.     /**
  560.      * Gets the month-of-year field using the {@code Month} enum.
  561.      * <p>
  562.      * This method returns the enum {@link Month} for the month.
  563.      * This avoids confusion as to what {@code int} values mean.
  564.      * If you need access to the primitive {@code int} value then the enum
  565.      * provides the {@link Month#getValue() int value}.
  566.      *
  567.      * @return the month-of-year, not null
  568.      * @see #getMonthValue()
  569.      */
  570.     public Month getMonth() {
  571.         return date.getMonth();
  572.     }

  573.     /**
  574.      * Gets the day-of-month field.
  575.      * <p>
  576.      * This method returns the primitive {@code int} value for the day-of-month.
  577.      *
  578.      * @return the day-of-month, from 1 to 31
  579.      */
  580.     public int getDayOfMonth() {
  581.         return date.getDayOfMonth();
  582.     }

  583.     /**
  584.      * Gets the day-of-year field.
  585.      * <p>
  586.      * This method returns the primitive {@code int} value for the day-of-year.
  587.      *
  588.      * @return the day-of-year, from 1 to 365, or 366 in a leap year
  589.      */
  590.     public int getDayOfYear() {
  591.         return date.getDayOfYear();
  592.     }

  593.     /**
  594.      * Gets the day-of-week field, which is an enum {@code DayOfWeek}.
  595.      * <p>
  596.      * This method returns the enum {@link DayOfWeek} for the day-of-week.
  597.      * This avoids confusion as to what {@code int} values mean.
  598.      * If you need access to the primitive {@code int} value then the enum
  599.      * provides the {@link DayOfWeek#getValue() int value}.
  600.      * <p>
  601.      * Additional information can be obtained from the {@code DayOfWeek}.
  602.      * This includes textual names of the values.
  603.      *
  604.      * @return the day-of-week, not null
  605.      */
  606.     public DayOfWeek getDayOfWeek() {
  607.         return date.getDayOfWeek();
  608.     }

  609.     //-----------------------------------------------------------------------
  610.     /**
  611.      * Returns an adjusted copy of this date.
  612.      * <p>
  613.      * This returns an {@code OffsetDate} based on this one, with the date adjusted.
  614.      * The adjustment takes place using the specified adjuster strategy object.
  615.      * Read the documentation of the adjuster to understand what adjustment will be made.
  616.      * <p>
  617.      * A simple adjuster might simply set the one of the fields, such as the year field.
  618.      * A more complex adjuster might set the date to the last day of the month.
  619.      * A selection of common adjustments is provided in {@link TemporalAdjusters}.
  620.      * These include finding the "last day of the month" and "next Wednesday".
  621.      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
  622.      * such as {@link Month} and {@link MonthDay MonthDay}.
  623.      * The adjuster is responsible for handling special cases, such as the varying
  624.      * lengths of month and leap years.
  625.      * <p>
  626.      * For example this code returns a date on the last day of July:
  627.      * <pre>
  628.      *  import static java.time.Month.*;
  629.      *  import static java.time.temporal.TemporalAdjusters.*;
  630.      *
  631.      *  result = offsetDate.with(JULY).with(lastDayOfMonth());
  632.      * </pre>
  633.      * <p>
  634.      * The classes {@link LocalDate} and {@link ZoneOffset} implement {@code TemporalAdjuster},
  635.      * thus this method can be used to change the date or offset:
  636.      * <pre>
  637.      *  result = offsetDate.with(date);
  638.      *  result = offsetDate.with(offset);
  639.      * </pre>
  640.      * <p>
  641.      * The result of this method is obtained by invoking the
  642.      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
  643.      * specified adjuster passing {@code this} as the argument.
  644.      * <p>
  645.      * This instance is immutable and unaffected by this method call.
  646.      *
  647.      * @param adjuster the adjuster to use, not null
  648.      * @return an {@code OffsetDate} based on {@code this} with the adjustment made, not null
  649.      * @throws DateTimeException if the adjustment cannot be made
  650.      * @throws ArithmeticException if numeric overflow occurs
  651.      */
  652.     @Override
  653.     public OffsetDate with(TemporalAdjuster adjuster) {
  654.         // optimizations
  655.         if (adjuster instanceof LocalDate) {
  656.             return with((LocalDate) adjuster, offset);
  657.         } else if (adjuster instanceof ZoneOffset) {
  658.             return with(date, (ZoneOffset) adjuster);
  659.         } else if (adjuster instanceof OffsetDate) {
  660.             return (OffsetDate) adjuster;
  661.         }
  662.         return (OffsetDate) adjuster.adjustInto(this);
  663.     }

  664.     /**
  665.      * Returns a copy of this date with the specified field set to a new value.
  666.      * <p>
  667.      * This returns an {@code OffsetDate} based on this one, with the value
  668.      * for the specified field changed.
  669.      * This can be used to change any supported field, such as the year, month or day-of-month.
  670.      * If it is not possible to set the value, because the field is not supported or for
  671.      * some other reason, an exception is thrown.
  672.      * <p>
  673.      * In some cases, changing the specified field can cause the resulting date to become invalid,
  674.      * such as changing the month from 31st January to February would make the day-of-month invalid.
  675.      * In cases like this, the field is responsible for resolving the date. Typically it will choose
  676.      * the previous valid date, which would be the last valid day of February in this example.
  677.      * <p>
  678.      * If the field is a {@link ChronoField} then the adjustment is implemented here.
  679.      * <p>
  680.      * The {@code OFFSET_SECONDS} field will return a date with the specified offset.
  681.      * The local date is unaltered. If the new offset value is outside the valid range
  682.      * then a {@code DateTimeException} will be thrown.
  683.      * <p>
  684.      * The other {@link #isSupported(TemporalField) supported fields} will behave as per
  685.      * the matching method on {@link LocalDate#with(TemporalField, long)} LocalDate}.
  686.      * In this case, the offset is not part of the calculation and will be unchanged.
  687.      * <p>
  688.      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
  689.      * <p>
  690.      * If the field is not a {@code ChronoField}, then the result of this method
  691.      * is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
  692.      * passing {@code this} as the argument. In this case, the field determines
  693.      * whether and how to adjust the instant.
  694.      * <p>
  695.      * This instance is immutable and unaffected by this method call.
  696.      *
  697.      * @param field  the field to set in the result, not null
  698.      * @param newValue  the new value of the field in the result
  699.      * @return an {@code OffsetDate} based on {@code this} with the specified field set, not null
  700.      * @throws DateTimeException if the field cannot be set
  701.      * @throws UnsupportedTemporalTypeException if the field is not supported
  702.      * @throws ArithmeticException if numeric overflow occurs
  703.      */
  704.     @Override
  705.     public OffsetDate with(TemporalField field, long newValue) {
  706.         if (field instanceof ChronoField) {
  707.             if (field == OFFSET_SECONDS) {
  708.                 ChronoField f = (ChronoField) field;
  709.                 return with(date, ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue)));
  710.             }
  711.             return with(date.with(field, newValue), offset);
  712.         }
  713.         return field.adjustInto(this, newValue);
  714.     }

  715.     //-----------------------------------------------------------------------
  716.     /**
  717.      * Returns a copy of this {@code OffsetDate} with the year altered.
  718.      * <p>
  719.      * The offset does not affect the calculation and will be the same in the result.
  720.      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
  721.      * <p>
  722.      * This instance is immutable and unaffected by this method call.
  723.      *
  724.      * @param year  the year to set in the result, from MIN_YEAR to MAX_YEAR
  725.      * @return an {@code OffsetDate} based on this date with the requested year, not null
  726.      * @throws DateTimeException if the year value is invalid
  727.      */
  728.     public OffsetDate withYear(int year) {
  729.         return with(date.withYear(year), offset);
  730.     }

  731.     /**
  732.      * Returns a copy of this {@code OffsetDate} with the month-of-year altered.
  733.      * <p>
  734.      * The offset does not affect the calculation and will be the same in the result.
  735.      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
  736.      * <p>
  737.      * This instance is immutable and unaffected by this method call.
  738.      *
  739.      * @param month  the month-of-year to set in the result, from 1 (January) to 12 (December)
  740.      * @return an {@code OffsetDate} based on this date with the requested month, not null
  741.      * @throws DateTimeException if the month-of-year value is invalid
  742.      */
  743.     public OffsetDate withMonth(int month) {
  744.         return with(date.withMonth(month), offset);
  745.     }

  746.     /**
  747.      * Returns a copy of this {@code OffsetDate} with the day-of-month altered.
  748.      * <p>
  749.      * If the resulting date is invalid, an exception is thrown.
  750.      * The offset does not affect the calculation and will be the same in the result.
  751.      * <p>
  752.      * This instance is immutable and unaffected by this method call.
  753.      *
  754.      * @param dayOfMonth  the day-of-month to set in the result, from 1 to 28-31
  755.      * @return an {@code OffsetDate} based on this date with the requested day, not null
  756.      * @throws DateTimeException if the day-of-month value is invalid,
  757.      *  or if the day-of-month is invalid for the month-year
  758.      */
  759.     public OffsetDate withDayOfMonth(int dayOfMonth) {
  760.         return with(date.withDayOfMonth(dayOfMonth), offset);
  761.     }

  762.     /**
  763.      * Returns a copy of this {@code OffsetDate} with the day-of-year altered.
  764.      * <p>
  765.      * If the resulting date is invalid, an exception is thrown.
  766.      * <p>
  767.      * This instance is immutable and unaffected by this method call.
  768.      *
  769.      * @param dayOfYear  the day-of-year to set in the result, from 1 to 365-366
  770.      * @return an {@code OffsetDate} based on this date with the requested day, not null
  771.      * @throws DateTimeException if the day-of-year value is invalid,
  772.      *  or if the day-of-year is invalid for the year
  773.      */
  774.     public OffsetDate withDayOfYear(int dayOfYear) {
  775.         return with(date.withDayOfYear(dayOfYear), offset);
  776.     }

  777.     //-----------------------------------------------------------------------
  778.     /**
  779.      * Returns a copy of this date with the specified period added.
  780.      * <p>
  781.      * This returns an {@code OffsetDate} based on this one, with the specified amount added.
  782.      * The amount is typically {@link Period} but may be any other type implementing
  783.      * the {@link TemporalAmount} interface.
  784.      * <p>
  785.      * This uses {@link TemporalAmount#addTo(Temporal)} to perform the calculation.
  786.      * <p>
  787.      * This instance is immutable and unaffected by this method call.
  788.      *
  789.      * @param amountToAdd  the amount to add, not null
  790.      * @return an {@code OffsetDate} based on this date with the addition made, not null
  791.      * @throws DateTimeException if the addition cannot be made
  792.      * @throws ArithmeticException if numeric overflow occurs
  793.      */
  794.     @Override
  795.     public OffsetDate plus(TemporalAmount amountToAdd) {
  796.         return (OffsetDate) amountToAdd.addTo(this);
  797.     }

  798.     /**
  799.      * Returns a copy of this date with the specified amount added.
  800.      * <p>
  801.      * This returns an {@code OffsetDate} based on this one, with the amount
  802.      * in terms of the unit added. If it is not possible to add the amount, because the
  803.      * unit is not supported or for some other reason, an exception is thrown.
  804.      * <p>
  805.      * If the field is a {@link ChronoUnit} then the addition is implemented by
  806.      * {@link LocalDate#plus(long, TemporalUnit)}.
  807.      * The offset is not part of the calculation and will be unchanged in the result.
  808.      * <p>
  809.      * If the field is not a {@code ChronoUnit}, then the result of this method
  810.      * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
  811.      * passing {@code this} as the argument. In this case, the unit determines
  812.      * whether and how to perform the addition.
  813.      * <p>
  814.      * This instance is immutable and unaffected by this method call.
  815.      *
  816.      * @param amountToAdd  the amount of the unit to add to the result, may be negative
  817.      * @param unit  the unit of the amount to add, not null
  818.      * @return an {@code OffsetDate} based on this date with the specified amount added, not null
  819.      * @throws DateTimeException if the addition cannot be made
  820.      * @throws UnsupportedTemporalTypeException if the unit is not supported
  821.      * @throws ArithmeticException if numeric overflow occurs
  822.      */
  823.     @Override
  824.     public OffsetDate plus(long amountToAdd, TemporalUnit unit) {
  825.         if (unit instanceof ChronoUnit) {
  826.             return with(date.plus(amountToAdd, unit), offset);
  827.         }
  828.         return unit.addTo(this, amountToAdd);
  829.     }

  830.     //-----------------------------------------------------------------------
  831.     /**
  832.      * Returns a copy of this {@code OffsetDate} with the specified number of years added.
  833.      * <p>
  834.      * This uses {@link LocalDate#plusYears(long)} to add the years.
  835.      * The offset does not affect the calculation and will be the same in the result.
  836.      * <p>
  837.      * This instance is immutable and unaffected by this method call.
  838.      *
  839.      * @param years  the years to add, may be negative
  840.      * @return an {@code OffsetDate} based on this date with the years added, not null
  841.      * @throws DateTimeException if the result exceeds the supported date range
  842.      */
  843.     public OffsetDate plusYears(long years) {
  844.         return with(date.plusYears(years), offset);
  845.     }

  846.     /**
  847.      * Returns a copy of this {@code OffsetDate} with the specified number of months added.
  848.      * <p>
  849.      * This uses {@link LocalDate#plusMonths(long)} to add the months.
  850.      * The offset does not affect the calculation and will be the same in the result.
  851.      * <p>
  852.      * This instance is immutable and unaffected by this method call.
  853.      *
  854.      * @param months  the months to add, may be negative
  855.      * @return an {@code OffsetDate} based on this date with the months added, not null
  856.      * @throws DateTimeException if the result exceeds the supported date range
  857.      */
  858.     public OffsetDate plusMonths(long months) {
  859.         return with(date.plusMonths(months), offset);
  860.     }

  861.     /**
  862.      * Returns a copy of this {@code OffsetDate} with the specified number of weeks added.
  863.      * <p>
  864.      * This uses {@link LocalDate#plusWeeks(long)} to add the weeks.
  865.      * The offset does not affect the calculation and will be the same in the result.
  866.      * <p>
  867.      * This instance is immutable and unaffected by this method call.
  868.      *
  869.      * @param weeks  the weeks to add, may be negative
  870.      * @return an {@code OffsetDate} based on this date with the weeks added, not null
  871.      * @throws DateTimeException if the result exceeds the supported date range
  872.      */
  873.     public OffsetDate plusWeeks(long weeks) {
  874.         return with(date.plusWeeks(weeks), offset);
  875.     }

  876.     /**
  877.      * Returns a copy of this {@code OffsetDate} with the specified number of days added.
  878.      * <p>
  879.      * This uses {@link LocalDate#plusDays(long)} to add the days.
  880.      * The offset does not affect the calculation and will be the same in the result.
  881.      * <p>
  882.      * This instance is immutable and unaffected by this method call.
  883.      *
  884.      * @param days  the days to add, may be negative
  885.      * @return an {@code OffsetDate} based on this date with the days added, not null
  886.      * @throws DateTimeException if the result exceeds the supported date range
  887.      */
  888.     public OffsetDate plusDays(long days) {
  889.         return with(date.plusDays(days), offset);
  890.     }

  891.     //-----------------------------------------------------------------------
  892.     /**
  893.      * Returns a copy of this date with the specified amount subtracted.
  894.      * <p>
  895.      * This returns am {@code OffsetDate} based on this one, with the specified amount subtracted.
  896.      * The amount is typically {@link Period} but may be any other type implementing
  897.      * the {@link TemporalAmount} interface.
  898.      * <p>
  899.      * This uses {@link TemporalAmount#subtractFrom(Temporal)} to perform the calculation.
  900.      * <p>
  901.      * This instance is immutable and unaffected by this method call.
  902.      *
  903.      * @param amountToSubtract  the amount to subtract, not null
  904.      * @return an {@code OffsetDate} based on this date with the subtraction made, not null
  905.      * @throws DateTimeException if the subtraction cannot be made
  906.      * @throws ArithmeticException if numeric overflow occurs
  907.      */
  908.     @Override
  909.     public OffsetDate minus(TemporalAmount amountToSubtract) {
  910.         return (OffsetDate) amountToSubtract.subtractFrom(this);
  911.     }

  912.     /**
  913.      * Returns a copy of this date with the specified amount subtracted.
  914.      * <p>
  915.      * This returns an {@code OffsetDate} based on this one, with the amount
  916.      * in terms of the unit subtracted. If it is not possible to subtract the amount,
  917.      * because the unit is not supported or for some other reason, an exception is thrown.
  918.      * <p>
  919.      * This method is equivalent to {@link #plus(long, TemporalUnit)} with the amount negated.
  920.      * See that method for a full description of how addition, and thus subtraction, works.
  921.      * <p>
  922.      * This instance is immutable and unaffected by this method call.
  923.      *
  924.      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
  925.      * @param unit  the unit of the amount to subtract, not null
  926.      * @return an {@code OffsetDate} based on this date with the specified amount subtracted, not null
  927.      * @throws DateTimeException if the subtraction cannot be made
  928.      * @throws UnsupportedTemporalTypeException if the unit is not supported
  929.      * @throws ArithmeticException if numeric overflow occurs
  930.      */
  931.     @Override
  932.     public OffsetDate minus(long amountToSubtract, TemporalUnit unit) {
  933.         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
  934.     }

  935.     //-----------------------------------------------------------------------
  936.     /**
  937.      * Returns a copy of this {@code OffsetDate} with the specified number of years subtracted.
  938.      * <p>
  939.      * This uses {@link LocalDate#minusYears(long)} to subtract the years.
  940.      * The offset does not affect the calculation and will be the same in the result.
  941.      * <p>
  942.      * This instance is immutable and unaffected by this method call.
  943.      *
  944.      * @param years  the years to subtract, may be negative
  945.      * @return an {@code OffsetDate} based on this date with the years subtracted, not null
  946.      * @throws DateTimeException if the result exceeds the supported date range
  947.      */
  948.     public OffsetDate minusYears(long years) {
  949.         return with(date.minusYears(years), offset);
  950.     }

  951.     /**
  952.      * Returns a copy of this {@code OffsetDate} with the specified number of months subtracted.
  953.      * <p>
  954.      * This uses {@link LocalDate#minusMonths(long)} to subtract the months.
  955.      * The offset does not affect the calculation and will be the same in the result.
  956.      * <p>
  957.      * This instance is immutable and unaffected by this method call.
  958.      *
  959.      * @param months  the months to subtract, may be negative
  960.      * @return an {@code OffsetDate} based on this date with the months subtracted, not null
  961.      * @throws DateTimeException if the result exceeds the supported date range
  962.      */
  963.     public OffsetDate minusMonths(long months) {
  964.         return with(date.minusMonths(months), offset);
  965.     }

  966.     /**
  967.      * Returns a copy of this {@code OffsetDate} with the specified number of weeks subtracted.
  968.      * <p>
  969.      * This uses {@link LocalDate#minusWeeks(long)} to subtract the weeks.
  970.      * The offset does not affect the calculation and will be the same in the result.
  971.      * <p>
  972.      * This instance is immutable and unaffected by this method call.
  973.      *
  974.      * @param weeks  the weeks to subtract, may be negative
  975.      * @return an {@code OffsetDate} based on this date with the weeks subtracted, not null
  976.      * @throws DateTimeException if the result exceeds the supported date range
  977.      */
  978.     public OffsetDate minusWeeks(long weeks) {
  979.         return with(date.minusWeeks(weeks), offset);
  980.     }

  981.     /**
  982.      * Returns a copy of this {@code OffsetDate} with the specified number of days subtracted.
  983.      * <p>
  984.      * This uses {@link LocalDate#minusDays(long)} to subtract the days.
  985.      * The offset does not affect the calculation and will be the same in the result.
  986.      * <p>
  987.      * This instance is immutable and unaffected by this method call.
  988.      *
  989.      * @param days  the days to subtract, may be negative
  990.      * @return an {@code OffsetDate} based on this date with the days subtracted, not null
  991.      * @throws DateTimeException if the result exceeds the supported date range
  992.      */
  993.     public OffsetDate minusDays(long days) {
  994.         return with(date.minusDays(days), offset);
  995.     }

  996.     //-----------------------------------------------------------------------
  997.     /**
  998.      * Queries this date using the specified query.
  999.      * <p>
  1000.      * This queries this date using the specified query strategy object.
  1001.      * The {@code TemporalQuery} object defines the logic to be used to
  1002.      * obtain the result. Read the documentation of the query to understand
  1003.      * what the result of this method will be.
  1004.      * <p>
  1005.      * The result of this method is obtained by invoking the
  1006.      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
  1007.      * specified query passing {@code this} as the argument.
  1008.      *
  1009.      * @param <R> the type of the result
  1010.      * @param query  the query to invoke, not null
  1011.      * @return the query result, null may be returned (defined by the query)
  1012.      * @throws DateTimeException if unable to query (defined by the query)
  1013.      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
  1014.      */
  1015.     @SuppressWarnings("unchecked")
  1016.     @Override
  1017.     public <R> R query(TemporalQuery<R> query) {
  1018.         if (query == TemporalQueries.chronology()) {
  1019.             return (R) IsoChronology.INSTANCE;
  1020.         } else if (query == TemporalQueries.precision()) {
  1021.             return (R) DAYS;
  1022.         } else if (query == TemporalQueries.offset() || query == TemporalQueries.zone()) {
  1023.             return (R) getOffset();
  1024.         }
  1025.         return Temporal.super.query(query);
  1026.     }

  1027.     /**
  1028.      * Adjusts the specified temporal object to have the same offset and date
  1029.      * as this object.
  1030.      * <p>
  1031.      * This returns a temporal object of the same observable type as the input
  1032.      * with the offset and date changed to be the same as this.
  1033.      * <p>
  1034.      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
  1035.      * twice, passing {@link ChronoField#OFFSET_SECONDS} and
  1036.      * {@link ChronoField#EPOCH_DAY} as the fields.
  1037.      * <p>
  1038.      * In most cases, it is clearer to reverse the calling pattern by using
  1039.      * {@link Temporal#with(TemporalAdjuster)}:
  1040.      * <pre>
  1041.      *   // these two lines are equivalent, but the second approach is recommended
  1042.      *   temporal = thisOffsetDate.adjustInto(temporal);
  1043.      *   temporal = temporal.with(thisOffsetDate);
  1044.      * </pre>
  1045.      * <p>
  1046.      * This instance is immutable and unaffected by this method call.
  1047.      *
  1048.      * @param temporal  the target object to be adjusted, not null
  1049.      * @return the adjusted object, not null
  1050.      * @throws DateTimeException if unable to make the adjustment
  1051.      * @throws ArithmeticException if numeric overflow occurs
  1052.      */
  1053.     @Override
  1054.     public Temporal adjustInto(Temporal temporal) {
  1055.         return temporal
  1056.                 .with(OFFSET_SECONDS, getOffset().getTotalSeconds())
  1057.                 .with(EPOCH_DAY, toLocalDate().toEpochDay());
  1058.     }

  1059.     /**
  1060.      * Calculates the period between this date and another date in
  1061.      * terms of the specified unit.
  1062.      * <p>
  1063.      * This calculates the period between two dates in terms of a single unit.
  1064.      * The start and end points are {@code this} and the specified date.
  1065.      * The result will be negative if the end is before the start.
  1066.      * For example, the period in days between two dates can be calculated
  1067.      * using {@code startDate.until(endDate, DAYS)}.
  1068.      * <p>
  1069.      * The {@code Temporal} passed to this method is converted to a
  1070.      * {@code OffsetDate} using {@link #from(TemporalAccessor)}.
  1071.      * If the offset differs between the two times, then the specified
  1072.      * end time is normalized to have the same offset as this time.
  1073.      * <p>
  1074.      * The calculation returns a whole number, representing the number of
  1075.      * complete units between the two dates.
  1076.      * For example, the period in months between 2012-06-15Z and 2012-08-14Z
  1077.      * will only be one month as it is one day short of two months.
  1078.      * <p>
  1079.      * There are two equivalent ways of using this method.
  1080.      * The first is to invoke this method.
  1081.      * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
  1082.      * <pre>
  1083.      *   // these two lines are equivalent
  1084.      *   amount = start.until(end, DAYS);
  1085.      *   amount = DAYS.between(start, end);
  1086.      * </pre>
  1087.      * The choice should be made based on which makes the code more readable.
  1088.      * <p>
  1089.      * The calculation is implemented in this method for {@link ChronoUnit}.
  1090.      * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
  1091.      * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
  1092.      * are supported. Other {@code ChronoUnit} values will throw an exception.
  1093.      * <p>
  1094.      * If the unit is not a {@code ChronoUnit}, then the result of this method
  1095.      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
  1096.      * passing {@code this} as the first argument and the converted input temporal
  1097.      * as the second argument.
  1098.      * <p>
  1099.      * This instance is immutable and unaffected by this method call.
  1100.      *
  1101.      * @param endExclusive  the end time, exclusive, which is converted to an {@code OffsetDate}, not null
  1102.      * @param unit  the unit to measure the amount in, not null
  1103.      * @return the amount of time between this date and the end date
  1104.      * @throws DateTimeException if the amount cannot be calculated, or the end
  1105.      *  temporal cannot be converted to an {@code OffsetDate}
  1106.      * @throws UnsupportedTemporalTypeException if the unit is not supported
  1107.      * @throws ArithmeticException if numeric overflow occurs
  1108.      */
  1109.     @Override
  1110.     public long until(Temporal endExclusive, TemporalUnit unit) {
  1111.         OffsetDate end = OffsetDate.from(endExclusive);
  1112.         if (unit instanceof ChronoUnit) {
  1113.             long offsetDiff = end.offset.getTotalSeconds() - offset.getTotalSeconds();
  1114.             LocalDate endLocal = end.date.plusDays(Math.floorDiv(-offsetDiff, SECONDS_PER_DAY));
  1115.             return date.until(endLocal, unit);
  1116.         }
  1117.         return unit.between(this, end);
  1118.     }

  1119.     /**
  1120.      * Formats this date using the specified formatter.
  1121.      * <p>
  1122.      * This date will be passed to the formatter to produce a string.
  1123.      *
  1124.      * @param formatter  the formatter to use, not null
  1125.      * @return the formatted date string, not null
  1126.      * @throws DateTimeException if an error occurs during printing
  1127.      */
  1128.     public String format(DateTimeFormatter formatter) {
  1129.         Objects.requireNonNull(formatter, "formatter");
  1130.         return formatter.format(this);
  1131.     }

  1132.     //-----------------------------------------------------------------------
  1133.     /**
  1134.      * Returns an offset date-time formed from this date at the specified time.
  1135.      * <p>
  1136.      * This combines this date with the specified time to form an {@code OffsetDateTime}.
  1137.      * All possible combinations of date and time are valid.
  1138.      * <p>
  1139.      * This instance is immutable and unaffected by this method call.
  1140.      *
  1141.      * @param time  the time to combine with, not null
  1142.      * @return the offset date-time formed from this date and the specified time, not null
  1143.      */
  1144.     public OffsetDateTime atTime(LocalTime time) {
  1145.         return OffsetDateTime.of(date, time, offset);
  1146.     }

  1147.     //-----------------------------------------------------------------------
  1148.     /**
  1149.      * Converts this date to midnight at the start of day in epoch seconds.
  1150.      *
  1151.      * @return the epoch seconds value
  1152.      */
  1153.     private long toEpochSecond() {
  1154.         long epochDay = date.toEpochDay();
  1155.         long secs = epochDay * SECONDS_PER_DAY;
  1156.         return secs - offset.getTotalSeconds();
  1157.     }

  1158.     /**
  1159.      * Converts this {@code OffsetDate} to the number of seconds since the epoch
  1160.      * of 1970-01-01T00:00:00Z.
  1161.      * <p>
  1162.      * This combines this offset date with the specified time
  1163.      * to calculate the epoch-second value, which is the
  1164.      * number of elapsed seconds from 1970-01-01T00:00:00Z.
  1165.      * Instants on the time-line after the epoch are positive, earlier
  1166.      * are negative.
  1167.      *
  1168.      * @param time the local time, not null
  1169.      * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
  1170.      */
  1171.     public long toEpochSecond(LocalTime time) {
  1172.         Objects.requireNonNull(time, "time");
  1173.         return toEpochSecond() + time.toSecondOfDay();
  1174.     }

  1175.     //-----------------------------------------------------------------------
  1176.     /**
  1177.      * Compares this {@code OffsetDate} to another date.
  1178.      * <p>
  1179.      * The comparison is based first on the UTC equivalent instant, then on the local date.
  1180.      * It is "consistent with equals", as defined by {@link Comparable}.
  1181.      * <p>
  1182.      * For example, the following is the comparator order:
  1183.      * <ol>
  1184.      * <li>2008-06-29-11:00</li>
  1185.      * <li>2008-06-29-12:00</li>
  1186.      * <li>2008-06-30+12:00</li>
  1187.      * <li>2008-06-29-13:00</li>
  1188.      * </ol>
  1189.      * Values #2 and #3 represent the same instant on the time-line.
  1190.      * When two values represent the same instant, the local date is compared
  1191.      * to distinguish them. This step is needed to make the ordering
  1192.      * consistent with {@code equals()}.
  1193.      * <p>
  1194.      * To compare the underlying local date of two {@code TemporalAccessor} instances,
  1195.      * use {@link ChronoField#EPOCH_DAY} as a comparator.
  1196.      *
  1197.      * @param other  the other date to compare to, not null
  1198.      * @return the comparator value, negative if less, positive if greater
  1199.      */
  1200.     @Override
  1201.     public int compareTo(OffsetDate other) {
  1202.         if (offset.equals(other.offset)) {
  1203.             return date.compareTo(other.date);
  1204.         }
  1205.         int compare = Long.compare(toEpochSecond(), other.toEpochSecond());
  1206.         if (compare == 0) {
  1207.             compare = date.compareTo(other.date);
  1208.         }
  1209.         return compare;
  1210.     }

  1211.     //-----------------------------------------------------------------------
  1212.     /**
  1213.      * Checks if the instant of midnight at the start of this {@code OffsetDate}
  1214.      * is after midnight at the start of the specified date.
  1215.      * <p>
  1216.      * This method differs from the comparison in {@link #compareTo} in that it
  1217.      * only compares the instant of the date. This is equivalent to using
  1218.      * {@code date1.toEpochSecond().isAfter(date2.toEpochSecond())}.
  1219.      *
  1220.      * @param other  the other date to compare to, not null
  1221.      * @return true if this is after the instant of the specified date
  1222.      */
  1223.     public boolean isAfter(OffsetDate other) {
  1224.         return toEpochSecond() > other.toEpochSecond();
  1225.     }

  1226.     /**
  1227.      * Checks if the instant of midnight at the start of this {@code OffsetDate}
  1228.      * is before midnight at the start of the specified date.
  1229.      * <p>
  1230.      * This method differs from the comparison in {@link #compareTo} in that it
  1231.      * only compares the instant of the date. This is equivalent to using
  1232.      * {@code date1.toEpochSecond().isBefore(date2.toEpochSecond())}.
  1233.      *
  1234.      * @param other  the other date to compare to, not null
  1235.      * @return true if this is before the instant of the specified date
  1236.      */
  1237.     public boolean isBefore(OffsetDate other) {
  1238.         return toEpochSecond() < other.toEpochSecond();
  1239.     }

  1240.     /**
  1241.      * Checks if the instant of midnight at the start of this {@code OffsetDate}
  1242.      * equals midnight at the start of the specified date.
  1243.      * <p>
  1244.      * This method differs from the comparison in {@link #compareTo} and {@link #equals}
  1245.      * in that it only compares the instant of the date. This is equivalent to using
  1246.      * {@code date1.toEpochSecond().equals(date2.toEpochSecond())}.
  1247.      *
  1248.      * @param other  the other date to compare to, not null
  1249.      * @return true if the instant equals the instant of the specified date
  1250.      */
  1251.     public boolean isEqual(OffsetDate other) {
  1252.         return toEpochSecond() == other.toEpochSecond();
  1253.     }

  1254.     //-----------------------------------------------------------------------
  1255.     /**
  1256.      * Checks if this date is equal to another date.
  1257.      * <p>
  1258.      * The comparison is based on the local-date and the offset.
  1259.      * To compare for the same instant on the time-line, use {@link #isEqual(OffsetDate)}.
  1260.      * <p>
  1261.      * Only objects of type {@code OffsetDate} are compared, other types return false.
  1262.      * To compare the underlying local date of two {@code TemporalAccessor} instances,
  1263.      * use {@link ChronoField#EPOCH_DAY} as a comparator.
  1264.      *
  1265.      * @param obj  the object to check, null returns false
  1266.      * @return true if this is equal to the other date
  1267.      */
  1268.     @Override
  1269.     public boolean equals(Object obj) {
  1270.         if (this == obj) {
  1271.             return true;
  1272.         }
  1273.         if (obj instanceof OffsetDate) {
  1274.             OffsetDate other = (OffsetDate) obj;
  1275.             return date.equals(other.date) && offset.equals(other.offset);
  1276.         }
  1277.         return false;
  1278.     }

  1279.     /**
  1280.      * A hash code for this date.
  1281.      *
  1282.      * @return a suitable hash code
  1283.      */
  1284.     @Override
  1285.     public int hashCode() {
  1286.         return date.hashCode() ^ offset.hashCode();
  1287.     }

  1288.     //-----------------------------------------------------------------------
  1289.     /**
  1290.      * Outputs this date as a {@code String}, such as {@code 2007-12-03+01:00}.
  1291.      * <p>
  1292.      * The output will be in the ISO-8601 format {@code yyyy-MM-ddXXXXX}.
  1293.      *
  1294.      * @return a string representation of this date, not null
  1295.      */
  1296.     @Override
  1297.     @ToString
  1298.     public String toString() {
  1299.         return date.toString() + offset.toString();
  1300.     }

  1301. }