jdk/src/share/classes/java/time/temporal/OffsetDate.java
changeset 15658 55b829ca2334
parent 15657 c588664d547e
child 15659 e575dab44ff5
equal deleted inserted replaced
15657:c588664d547e 15658:55b829ca2334
     1 /*
       
     2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /*
       
    27  * This file is available under and governed by the GNU General Public
       
    28  * License version 2 only, as published by the Free Software Foundation.
       
    29  * However, the following notice accompanied the original version of this
       
    30  * file:
       
    31  *
       
    32  * Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
       
    33  *
       
    34  * All rights reserved.
       
    35  *
       
    36  * Redistribution and use in source and binary forms, with or without
       
    37  * modification, are permitted provided that the following conditions are met:
       
    38  *
       
    39  *  * Redistributions of source code must retain the above copyright notice,
       
    40  *    this list of conditions and the following disclaimer.
       
    41  *
       
    42  *  * Redistributions in binary form must reproduce the above copyright notice,
       
    43  *    this list of conditions and the following disclaimer in the documentation
       
    44  *    and/or other materials provided with the distribution.
       
    45  *
       
    46  *  * Neither the name of JSR-310 nor the names of its contributors
       
    47  *    may be used to endorse or promote products derived from this software
       
    48  *    without specific prior written permission.
       
    49  *
       
    50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
       
    54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
       
    58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
       
    59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
       
    60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    61  */
       
    62 package java.time.temporal;
       
    63 
       
    64 import static java.time.temporal.ChronoField.EPOCH_DAY;
       
    65 import static java.time.temporal.ChronoField.OFFSET_SECONDS;
       
    66 import static java.time.temporal.ChronoLocalDateTimeImpl.SECONDS_PER_DAY;
       
    67 import static java.time.temporal.ChronoUnit.DAYS;
       
    68 
       
    69 import java.io.IOException;
       
    70 import java.io.InvalidObjectException;
       
    71 import java.io.ObjectInput;
       
    72 import java.io.ObjectOutput;
       
    73 import java.io.ObjectStreamException;
       
    74 import java.io.Serializable;
       
    75 import java.time.Clock;
       
    76 import java.time.DateTimeException;
       
    77 import java.time.DayOfWeek;
       
    78 import java.time.Instant;
       
    79 import java.time.LocalDate;
       
    80 import java.time.LocalTime;
       
    81 import java.time.Month;
       
    82 import java.time.ZoneId;
       
    83 import java.time.ZoneOffset;
       
    84 import java.time.format.DateTimeFormatter;
       
    85 import java.time.format.DateTimeFormatters;
       
    86 import java.time.format.DateTimeParseException;
       
    87 import java.time.zone.ZoneRules;
       
    88 import java.util.Objects;
       
    89 
       
    90 /**
       
    91  * A date with an offset from UTC/Greenwich in the ISO-8601 calendar system,
       
    92  * such as {@code 2007-12-03+01:00}.
       
    93  * <p>
       
    94  * {@code OffsetDate} is an immutable date-time object that represents a date, often viewed
       
    95  * as year-month-day-offset. This object can also access other date fields such as
       
    96  * day-of-year, day-of-week and week-of-year.
       
    97  * <p>
       
    98  * This class does not store or represent a time.
       
    99  * For example, the value "2nd October 2007 +02:00" can be stored
       
   100  * in an {@code OffsetDate}.
       
   101  *
       
   102  * <h3>Specification for implementors</h3>
       
   103  * This class is immutable and thread-safe.
       
   104  *
       
   105  * @since 1.8
       
   106  */
       
   107 public final class OffsetDate
       
   108         implements Temporal, TemporalAdjuster, Comparable<OffsetDate>, Serializable {
       
   109 
       
   110     /**
       
   111      * The minimum supported {@code OffsetDate}, '-999999999-01-01+18:00'.
       
   112      * This is the minimum local date in the maximum offset
       
   113      * (larger offsets are earlier on the time-line).
       
   114      * This combines {@link LocalDate#MIN} and {@link ZoneOffset#MAX}.
       
   115      * This could be used by an application as a "far past" date.
       
   116      */
       
   117     public static final OffsetDate MIN = LocalDate.MIN.atOffset(ZoneOffset.MAX);
       
   118     /**
       
   119      * The maximum supported {@code OffsetDate}, '+999999999-12-31-18:00'.
       
   120      * This is the maximum local date in the minimum offset
       
   121      * (larger negative offsets are later on the time-line).
       
   122      * This combines {@link LocalDate#MAX} and {@link ZoneOffset#MIN}.
       
   123      * This could be used by an application as a "far future" date.
       
   124      */
       
   125     public static final OffsetDate MAX = LocalDate.MAX.atOffset(ZoneOffset.MIN);
       
   126 
       
   127     /**
       
   128      * Serialization version.
       
   129      */
       
   130     private static final long serialVersionUID = -4382054179074397774L;
       
   131 
       
   132     /**
       
   133      * The local date.
       
   134      */
       
   135     private final LocalDate date;
       
   136     /**
       
   137      * The offset from UTC/Greenwich.
       
   138      */
       
   139     private final ZoneOffset offset;
       
   140 
       
   141     //-----------------------------------------------------------------------
       
   142     /**
       
   143      * Obtains the current date from the system clock in the default time-zone.
       
   144      * <p>
       
   145      * This will query the {@link java.time.Clock#systemDefaultZone() system clock} in the default
       
   146      * time-zone to obtain the current date.
       
   147      * The offset will be calculated from the time-zone in the clock.
       
   148      * <p>
       
   149      * Using this method will prevent the ability to use an alternate clock for testing
       
   150      * because the clock is hard-coded.
       
   151      *
       
   152      * @return the current date using the system clock, not null
       
   153      */
       
   154     public static OffsetDate now() {
       
   155         return now(Clock.systemDefaultZone());
       
   156     }
       
   157 
       
   158     /**
       
   159      * Obtains the current date from the system clock in the specified time-zone.
       
   160      * <p>
       
   161      * This will query the {@link Clock#system(java.time.ZoneId) system clock} to obtain the current date.
       
   162      * Specifying the time-zone avoids dependence on the default time-zone.
       
   163      * The offset will be calculated from the specified time-zone.
       
   164      * <p>
       
   165      * Using this method will prevent the ability to use an alternate clock for testing
       
   166      * because the clock is hard-coded.
       
   167      *
       
   168      * @param zone  the zone ID to use, not null
       
   169      * @return the current date using the system clock, not null
       
   170      */
       
   171     public static OffsetDate now(ZoneId zone) {
       
   172         return now(Clock.system(zone));
       
   173     }
       
   174 
       
   175     /**
       
   176      * Obtains the current date from the specified clock.
       
   177      * <p>
       
   178      * This will query the specified clock to obtain the current date - today.
       
   179      * The offset will be calculated from the time-zone in the clock.
       
   180      * <p>
       
   181      * Using this method allows the use of an alternate clock for testing.
       
   182      * The alternate clock may be introduced using {@link Clock dependency injection}.
       
   183      *
       
   184      * @param clock  the clock to use, not null
       
   185      * @return the current date, not null
       
   186      */
       
   187     public static OffsetDate now(Clock clock) {
       
   188         Objects.requireNonNull(clock, "clock");
       
   189         final Instant now = clock.instant();  // called once
       
   190         return ofInstant(now, clock.getZone().getRules().getOffset(now));
       
   191     }
       
   192 
       
   193     //-----------------------------------------------------------------------
       
   194     /**
       
   195      * Obtains an instance of {@code OffsetDate} from a local date and an offset.
       
   196      *
       
   197      * @param date  the local date, not null
       
   198      * @param offset  the zone offset, not null
       
   199      * @return the offset date, not null
       
   200      */
       
   201     public static OffsetDate of(LocalDate date, ZoneOffset offset) {
       
   202         return new OffsetDate(date, offset);
       
   203     }
       
   204 
       
   205     //-----------------------------------------------------------------------
       
   206     /**
       
   207      * Obtains an instance of {@code OffsetDate} from an {@code Instant} and zone ID.
       
   208      * <p>
       
   209      * This creates an offset date with the same instant as midnight at the
       
   210      * start of day of the instant specified.
       
   211      * Finding the offset from UTC/Greenwich is simple as there is only one valid
       
   212      * offset for each instant.
       
   213      *
       
   214      * @param instant  the instant to create the time from, not null
       
   215      * @param zone  the time-zone, which may be an offset, not null
       
   216      * @return the offset time, not null
       
   217      */
       
   218     public static OffsetDate ofInstant(Instant instant, ZoneId zone) {
       
   219         Objects.requireNonNull(instant, "instant");
       
   220         Objects.requireNonNull(zone, "zone");
       
   221         ZoneRules rules = zone.getRules();
       
   222         ZoneOffset offset = rules.getOffset(instant);
       
   223         long epochSec = instant.getEpochSecond() + offset.getTotalSeconds();  // overflow caught later
       
   224         long epochDay = Math.floorDiv(epochSec, SECONDS_PER_DAY);
       
   225         LocalDate date = LocalDate.ofEpochDay(epochDay);
       
   226         return new OffsetDate(date, offset);
       
   227     }
       
   228 
       
   229     //-----------------------------------------------------------------------
       
   230     /**
       
   231      * Obtains an instance of {@code OffsetDate} from a temporal object.
       
   232      * <p>
       
   233      * A {@code TemporalAccessor} represents some form of date and time information.
       
   234      * This factory converts the arbitrary temporal object to an instance of {@code OffsetDate}.
       
   235      * <p>
       
   236      * The conversion extracts and combines {@code LocalDate} and {@code ZoneOffset}.
       
   237      * <p>
       
   238      * This method matches the signature of the functional interface {@link TemporalQuery}
       
   239      * allowing it to be used in queries via method reference, {@code OffsetDate::from}.
       
   240      *
       
   241      * @param temporal  the temporal object to convert, not null
       
   242      * @return the offset date, not null
       
   243      * @throws DateTimeException if unable to convert to an {@code OffsetDate}
       
   244      */
       
   245     public static OffsetDate from(TemporalAccessor temporal) {
       
   246         if (temporal instanceof OffsetDate) {
       
   247             return (OffsetDate) temporal;
       
   248         }
       
   249         try {
       
   250             LocalDate date = LocalDate.from(temporal);
       
   251             ZoneOffset offset = ZoneOffset.from(temporal);
       
   252             return new OffsetDate(date, offset);
       
   253         } catch (DateTimeException ex) {
       
   254             throw new DateTimeException("Unable to obtain OffsetDate from TemporalAccessor: " + temporal.getClass(), ex);
       
   255         }
       
   256     }
       
   257 
       
   258     //-----------------------------------------------------------------------
       
   259     /**
       
   260      * Obtains an instance of {@code OffsetDate} from a text string such as {@code 2007-12-03+01:00}.
       
   261      * <p>
       
   262      * The string must represent a valid date and is parsed using
       
   263      * {@link java.time.format.DateTimeFormatters#isoOffsetDate()}.
       
   264      *
       
   265      * @param text  the text to parse such as "2007-12-03+01:00", not null
       
   266      * @return the parsed offset date, not null
       
   267      * @throws DateTimeParseException if the text cannot be parsed
       
   268      */
       
   269     public static OffsetDate parse(CharSequence text) {
       
   270         return parse(text, DateTimeFormatters.isoOffsetDate());
       
   271     }
       
   272 
       
   273     /**
       
   274      * Obtains an instance of {@code OffsetDate} from a text string using a specific formatter.
       
   275      * <p>
       
   276      * The text is parsed using the formatter, returning a date.
       
   277      *
       
   278      * @param text  the text to parse, not null
       
   279      * @param formatter  the formatter to use, not null
       
   280      * @return the parsed offset date, not null
       
   281      * @throws DateTimeParseException if the text cannot be parsed
       
   282      */
       
   283     public static OffsetDate parse(CharSequence text, DateTimeFormatter formatter) {
       
   284         Objects.requireNonNull(formatter, "formatter");
       
   285         return formatter.parse(text, OffsetDate::from);
       
   286     }
       
   287 
       
   288     //-----------------------------------------------------------------------
       
   289     /**
       
   290      * Constructor.
       
   291      *
       
   292      * @param date  the local date, not null
       
   293      * @param offset  the zone offset, not null
       
   294      */
       
   295     private OffsetDate(LocalDate date, ZoneOffset offset) {
       
   296         this.date = Objects.requireNonNull(date, "date");
       
   297         this.offset = Objects.requireNonNull(offset, "offset");
       
   298     }
       
   299 
       
   300     /**
       
   301      * Returns a new date based on this one, returning {@code this} where possible.
       
   302      *
       
   303      * @param date  the date to create with, not null
       
   304      * @param offset  the zone offset to create with, not null
       
   305      */
       
   306     private OffsetDate with(LocalDate date, ZoneOffset offset) {
       
   307         if (this.date == date && this.offset.equals(offset)) {
       
   308             return this;
       
   309         }
       
   310         return new OffsetDate(date, offset);
       
   311     }
       
   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} and
       
   319      * {@link #get(TemporalField) get} methods will throw an exception.
       
   320      * <p>
       
   321      * If the field is a {@link ChronoField} then the query is implemented here.
       
   322      * The {@link #isSupported(TemporalField) supported fields} will return valid
       
   323      * values based on this date-time.
       
   324      * The supported fields are:
       
   325      * <ul>
       
   326      * <li>{@code DAY_OF_WEEK}
       
   327      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_MONTH}
       
   328      * <li>{@code ALIGNED_DAY_OF_WEEK_IN_YEAR}
       
   329      * <li>{@code DAY_OF_MONTH}
       
   330      * <li>{@code DAY_OF_YEAR}
       
   331      * <li>{@code EPOCH_DAY}
       
   332      * <li>{@code ALIGNED_WEEK_OF_MONTH}
       
   333      * <li>{@code ALIGNED_WEEK_OF_YEAR}
       
   334      * <li>{@code MONTH_OF_YEAR}
       
   335      * <li>{@code EPOCH_MONTH}
       
   336      * <li>{@code YEAR_OF_ERA}
       
   337      * <li>{@code YEAR}
       
   338      * <li>{@code ERA}
       
   339      * <li>{@code OFFSET_SECONDS}
       
   340      * </ul>
       
   341      * All other {@code ChronoField} instances will return false.
       
   342      * <p>
       
   343      * If the field is not a {@code ChronoField}, then the result of this method
       
   344      * is obtained by invoking {@code TemporalField.doIsSupported(TemporalAccessor)}
       
   345      * passing {@code this} as the argument.
       
   346      * Whether the field is supported is determined by the field.
       
   347      *
       
   348      * @param field  the field to check, null returns false
       
   349      * @return true if the field is supported on this date, false if not
       
   350      */
       
   351     @Override
       
   352     public boolean isSupported(TemporalField field) {
       
   353         if (field instanceof ChronoField) {
       
   354             return ((ChronoField) field).isDateField() || field == OFFSET_SECONDS;
       
   355         }
       
   356         return field != null && field.doIsSupported(this);
       
   357     }
       
   358 
       
   359     /**
       
   360      * Gets the range of valid values for the specified field.
       
   361      * <p>
       
   362      * The range object expresses the minimum and maximum valid values for a field.
       
   363      * This date is used to enhance the accuracy of the returned range.
       
   364      * If it is not possible to return the range, because the field is not supported
       
   365      * or for some other reason, an exception is thrown.
       
   366      * <p>
       
   367      * If the field is a {@link ChronoField} then the query is implemented here.
       
   368      * The {@link #isSupported(TemporalField) supported fields} will return
       
   369      * appropriate range instances.
       
   370      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   371      * <p>
       
   372      * If the field is not a {@code ChronoField}, then the result of this method
       
   373      * is obtained by invoking {@code TemporalField.doRange(TemporalAccessor)}
       
   374      * passing {@code this} as the argument.
       
   375      * Whether the range can be obtained is determined by the field.
       
   376      *
       
   377      * @param field  the field to query the range for, not null
       
   378      * @return the range of valid values for the field, not null
       
   379      * @throws DateTimeException if the range for the field cannot be obtained
       
   380      */
       
   381     @Override
       
   382     public ValueRange range(TemporalField field) {
       
   383         if (field instanceof ChronoField) {
       
   384             if (field == OFFSET_SECONDS) {
       
   385                 return field.range();
       
   386             }
       
   387             return date.range(field);
       
   388         }
       
   389         return field.doRange(this);
       
   390     }
       
   391 
       
   392     /**
       
   393      * Gets the value of the specified field from this date as an {@code int}.
       
   394      * <p>
       
   395      * This queries this date for the value for the specified field.
       
   396      * The returned value will always be within the valid range of values for the field.
       
   397      * If it is not possible to return the value, because the field is not supported
       
   398      * or for some other reason, an exception is thrown.
       
   399      * <p>
       
   400      * If the field is a {@link ChronoField} then the query is implemented here.
       
   401      * The {@link #isSupported(TemporalField) supported fields} will return valid
       
   402      * values based on this date, except {@code EPOCH_DAY} and {@code EPOCH_MONTH}
       
   403      * which are too large to fit in an {@code int} and throw a {@code DateTimeException}.
       
   404      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   405      * <p>
       
   406      * If the field is not a {@code ChronoField}, then the result of this method
       
   407      * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
       
   408      * passing {@code this} as the argument. Whether the value can be obtained,
       
   409      * and what the value represents, is determined by the field.
       
   410      *
       
   411      * @param field  the field to get, not null
       
   412      * @return the value for the field
       
   413      * @throws DateTimeException if a value for the field cannot be obtained
       
   414      * @throws ArithmeticException if numeric overflow occurs
       
   415      */
       
   416     @Override  // override for Javadoc
       
   417     public int get(TemporalField field) {
       
   418         return Temporal.super.get(field);
       
   419     }
       
   420 
       
   421     /**
       
   422      * Gets the value of the specified field from this date as a {@code long}.
       
   423      * <p>
       
   424      * This queries this date for the value for the specified field.
       
   425      * If it is not possible to return the value, because the field is not supported
       
   426      * or for some other reason, an exception is thrown.
       
   427      * <p>
       
   428      * If the field is a {@link ChronoField} then the query is implemented here.
       
   429      * The {@link #isSupported(TemporalField) supported fields} will return valid
       
   430      * values based on this date.
       
   431      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   432      * <p>
       
   433      * If the field is not a {@code ChronoField}, then the result of this method
       
   434      * is obtained by invoking {@code TemporalField.doGet(TemporalAccessor)}
       
   435      * passing {@code this} as the argument. Whether the value can be obtained,
       
   436      * and what the value represents, is determined by the field.
       
   437      *
       
   438      * @param field  the field to get, not null
       
   439      * @return the value for the field
       
   440      * @throws DateTimeException if a value for the field cannot be obtained
       
   441      * @throws ArithmeticException if numeric overflow occurs
       
   442      */
       
   443     @Override
       
   444     public long getLong(TemporalField field) {
       
   445         if (field instanceof ChronoField) {
       
   446             if (field == OFFSET_SECONDS) {
       
   447                 return getOffset().getTotalSeconds();
       
   448             }
       
   449             return date.getLong(field);
       
   450         }
       
   451         return field.doGet(this);
       
   452     }
       
   453 
       
   454     //-----------------------------------------------------------------------
       
   455     /**
       
   456      * Gets the zone offset, such as '+01:00'.
       
   457      * <p>
       
   458      * This is the offset of the local date from UTC/Greenwich.
       
   459      *
       
   460      * @return the zone offset, not null
       
   461      */
       
   462     public ZoneOffset getOffset() {
       
   463         return offset;
       
   464     }
       
   465 
       
   466     /**
       
   467      * Returns a copy of this {@code OffsetDate} with the specified offset.
       
   468      * <p>
       
   469      * This method returns an object with the same {@code LocalDate} and the specified {@code ZoneOffset}.
       
   470      * No calculation is needed or performed.
       
   471      * For example, if this time represents {@code 2007-12-03+02:00} and the offset specified is
       
   472      * {@code +03:00}, then this method will return {@code 2007-12-03+03:00}.
       
   473      * <p>
       
   474      * This instance is immutable and unaffected by this method call.
       
   475      *
       
   476      * @param offset  the zone offset to change to, not null
       
   477      * @return an {@code OffsetDate} based on this date with the requested offset, not null
       
   478      */
       
   479     public OffsetDate withOffset(ZoneOffset offset) {
       
   480         Objects.requireNonNull(offset, "offset");
       
   481         return with(date, offset);
       
   482     }
       
   483 
       
   484     //-----------------------------------------------------------------------
       
   485     /**
       
   486      * Gets the {@code LocalDate} part of this date-time.
       
   487      * <p>
       
   488      * This returns a {@code LocalDate} with the same year, month and day
       
   489      * as this date-time.
       
   490      *
       
   491      * @return the date part of this date-time, not null
       
   492      */
       
   493     public LocalDate getDate() {
       
   494         return date;
       
   495     }
       
   496 
       
   497     //-----------------------------------------------------------------------
       
   498     /**
       
   499      * Gets the year field.
       
   500      * <p>
       
   501      * This method returns the primitive {@code int} value for the year.
       
   502      * <p>
       
   503      * The year returned by this method is proleptic as per {@code get(YEAR)}.
       
   504      * To obtain the year-of-era, use {@code get(YEAR_OF_ERA}.
       
   505      *
       
   506      * @return the year, from MIN_YEAR to MAX_YEAR
       
   507      */
       
   508     public int getYear() {
       
   509         return date.getYear();
       
   510     }
       
   511 
       
   512     /**
       
   513      * Gets the month-of-year field from 1 to 12.
       
   514      * <p>
       
   515      * This method returns the month as an {@code int} from 1 to 12.
       
   516      * Application code is frequently clearer if the enum {@link Month}
       
   517      * is used by calling {@link #getMonth()}.
       
   518      *
       
   519      * @return the month-of-year, from 1 to 12
       
   520      * @see #getMonth()
       
   521      */
       
   522     public int getMonthValue() {
       
   523         return date.getMonthValue();
       
   524     }
       
   525 
       
   526     /**
       
   527      * Gets the month-of-year field using the {@code Month} enum.
       
   528      * <p>
       
   529      * This method returns the enum {@link Month} for the month.
       
   530      * This avoids confusion as to what {@code int} values mean.
       
   531      * If you need access to the primitive {@code int} value then the enum
       
   532      * provides the {@link Month#getValue() int value}.
       
   533      *
       
   534      * @return the month-of-year, not null
       
   535      * @see #getMonthValue()
       
   536      */
       
   537     public Month getMonth() {
       
   538         return date.getMonth();
       
   539     }
       
   540 
       
   541     /**
       
   542      * Gets the day-of-month field.
       
   543      * <p>
       
   544      * This method returns the primitive {@code int} value for the day-of-month.
       
   545      *
       
   546      * @return the day-of-month, from 1 to 31
       
   547      */
       
   548     public int getDayOfMonth() {
       
   549         return date.getDayOfMonth();
       
   550     }
       
   551 
       
   552     /**
       
   553      * Gets the day-of-year field.
       
   554      * <p>
       
   555      * This method returns the primitive {@code int} value for the day-of-year.
       
   556      *
       
   557      * @return the day-of-year, from 1 to 365, or 366 in a leap year
       
   558      */
       
   559     public int getDayOfYear() {
       
   560         return date.getDayOfYear();
       
   561     }
       
   562 
       
   563     /**
       
   564      * Gets the day-of-week field, which is an enum {@code DayOfWeek}.
       
   565      * <p>
       
   566      * This method returns the enum {@link java.time.DayOfWeek} for the day-of-week.
       
   567      * This avoids confusion as to what {@code int} values mean.
       
   568      * If you need access to the primitive {@code int} value then the enum
       
   569      * provides the {@link java.time.DayOfWeek#getValue() int value}.
       
   570      * <p>
       
   571      * Additional information can be obtained from the {@code DayOfWeek}.
       
   572      * This includes textual names of the values.
       
   573      *
       
   574      * @return the day-of-week, not null
       
   575      */
       
   576     public DayOfWeek getDayOfWeek() {
       
   577         return date.getDayOfWeek();
       
   578     }
       
   579 
       
   580     //-----------------------------------------------------------------------
       
   581     /**
       
   582      * Returns an adjusted copy of this date.
       
   583      * <p>
       
   584      * This returns a new {@code OffsetDate}, based on this one, with the date adjusted.
       
   585      * The adjustment takes place using the specified adjuster strategy object.
       
   586      * Read the documentation of the adjuster to understand what adjustment will be made.
       
   587      * <p>
       
   588      * A simple adjuster might simply set the one of the fields, such as the year field.
       
   589      * A more complex adjuster might set the date to the last day of the month.
       
   590      * A selection of common adjustments is provided in {@link java.time.temporal.Adjusters}.
       
   591      * These include finding the "last day of the month" and "next Wednesday".
       
   592      * Key date-time classes also implement the {@code TemporalAdjuster} interface,
       
   593      * such as {@link Month} and {@link java.time.temporal.MonthDay MonthDay}.
       
   594      * The adjuster is responsible for handling special cases, such as the varying
       
   595      * lengths of month and leap years.
       
   596      * <p>
       
   597      * For example this code returns a date on the last day of July:
       
   598      * <pre>
       
   599      *  import static java.time.Month.*;
       
   600      *  import static java.time.temporal.Adjusters.*;
       
   601      *
       
   602      *  result = offsetDate.with(JULY).with(lastDayOfMonth());
       
   603      * </pre>
       
   604      * <p>
       
   605      * The classes {@link LocalDate} and {@link ZoneOffset} implement {@code TemporalAdjuster},
       
   606      * thus this method can be used to change the date or offset:
       
   607      * <pre>
       
   608      *  result = offsetDate.with(date);
       
   609      *  result = offsetDate.with(offset);
       
   610      * </pre>
       
   611      * <p>
       
   612      * The result of this method is obtained by invoking the
       
   613      * {@link TemporalAdjuster#adjustInto(Temporal)} method on the
       
   614      * specified adjuster passing {@code this} as the argument.
       
   615      * <p>
       
   616      * This instance is immutable and unaffected by this method call.
       
   617      *
       
   618      * @param adjuster the adjuster to use, not null
       
   619      * @return an {@code OffsetDate} based on {@code this} with the adjustment made, not null
       
   620      * @throws DateTimeException if the adjustment cannot be made
       
   621      * @throws ArithmeticException if numeric overflow occurs
       
   622      */
       
   623     @Override
       
   624     public OffsetDate with(TemporalAdjuster adjuster) {
       
   625         // optimizations
       
   626         if (adjuster instanceof LocalDate) {
       
   627             return with((LocalDate) adjuster, offset);
       
   628         } else if (adjuster instanceof ZoneOffset) {
       
   629             return with(date, (ZoneOffset) adjuster);
       
   630         } else if (adjuster instanceof OffsetDate) {
       
   631             return (OffsetDate) adjuster;
       
   632         }
       
   633         return (OffsetDate) adjuster.adjustInto(this);
       
   634     }
       
   635 
       
   636     /**
       
   637      * Returns a copy of this date with the specified field set to a new value.
       
   638      * <p>
       
   639      * This returns a new {@code OffsetDate}, based on this one, with the value
       
   640      * for the specified field changed.
       
   641      * This can be used to change any supported field, such as the year, month or day-of-month.
       
   642      * If it is not possible to set the value, because the field is not supported or for
       
   643      * some other reason, an exception is thrown.
       
   644      * <p>
       
   645      * In some cases, changing the specified field can cause the resulting date to become invalid,
       
   646      * such as changing the month from 31st January to February would make the day-of-month invalid.
       
   647      * In cases like this, the field is responsible for resolving the date. Typically it will choose
       
   648      * the previous valid date, which would be the last valid day of February in this example.
       
   649      * <p>
       
   650      * If the field is a {@link ChronoField} then the adjustment is implemented here.
       
   651      * <p>
       
   652      * The {@code OFFSET_SECONDS} field will return a date with the specified offset.
       
   653      * The local date is unaltered. If the new offset value is outside the valid range
       
   654      * then a {@code DateTimeException} will be thrown.
       
   655      * <p>
       
   656      * The other {@link #isSupported(TemporalField) supported fields} will behave as per
       
   657      * the matching method on {@link LocalDate#with(TemporalField, long)} LocalDate}.
       
   658      * In this case, the offset is not part of the calculation and will be unchanged.
       
   659      * <p>
       
   660      * All other {@code ChronoField} instances will throw a {@code DateTimeException}.
       
   661      * <p>
       
   662      * If the field is not a {@code ChronoField}, then the result of this method
       
   663      * is obtained by invoking {@code TemporalField.doWith(Temporal, long)}
       
   664      * passing {@code this} as the argument. In this case, the field determines
       
   665      * whether and how to adjust the instant.
       
   666      * <p>
       
   667      * This instance is immutable and unaffected by this method call.
       
   668      *
       
   669      * @param field  the field to set in the result, not null
       
   670      * @param newValue  the new value of the field in the result
       
   671      * @return an {@code OffsetDate} based on {@code this} with the specified field set, not null
       
   672      * @throws DateTimeException if the field cannot be set
       
   673      * @throws ArithmeticException if numeric overflow occurs
       
   674      */
       
   675     @Override
       
   676     public OffsetDate with(TemporalField field, long newValue) {
       
   677         if (field instanceof ChronoField) {
       
   678             if (field == OFFSET_SECONDS) {
       
   679                 ChronoField f = (ChronoField) field;
       
   680                 return with(date, ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue)));
       
   681             }
       
   682             return with(date.with(field, newValue), offset);
       
   683         }
       
   684         return field.doWith(this, newValue);
       
   685     }
       
   686 
       
   687     //-----------------------------------------------------------------------
       
   688     /**
       
   689      * Returns a copy of this {@code OffsetDate} with the year altered.
       
   690      * The offset does not affect the calculation and will be the same in the result.
       
   691      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
       
   692      * <p>
       
   693      * This instance is immutable and unaffected by this method call.
       
   694      *
       
   695      * @param year  the year to set in the result, from MIN_YEAR to MAX_YEAR
       
   696      * @return an {@code OffsetDate} based on this date with the requested year, not null
       
   697      * @throws DateTimeException if the year value is invalid
       
   698      */
       
   699     public OffsetDate withYear(int year) {
       
   700         return with(date.withYear(year), offset);
       
   701     }
       
   702 
       
   703     /**
       
   704      * Returns a copy of this {@code OffsetDate} with the month-of-year altered.
       
   705      * The offset does not affect the calculation and will be the same in the result.
       
   706      * If the day-of-month is invalid for the year, it will be changed to the last valid day of the month.
       
   707      * <p>
       
   708      * This instance is immutable and unaffected by this method call.
       
   709      *
       
   710      * @param month  the month-of-year to set in the result, from 1 (January) to 12 (December)
       
   711      * @return an {@code OffsetDate} based on this date with the requested month, not null
       
   712      * @throws DateTimeException if the month-of-year value is invalid
       
   713      */
       
   714     public OffsetDate withMonth(int month) {
       
   715         return with(date.withMonth(month), offset);
       
   716     }
       
   717 
       
   718     /**
       
   719      * Returns a copy of this {@code OffsetDate} with the day-of-month altered.
       
   720      * If the resulting date is invalid, an exception is thrown.
       
   721      * The offset does not affect the calculation and will be the same in the result.
       
   722      * <p>
       
   723      * This instance is immutable and unaffected by this method call.
       
   724      *
       
   725      * @param dayOfMonth  the day-of-month to set in the result, from 1 to 28-31
       
   726      * @return an {@code OffsetDate} based on this date with the requested day, not null
       
   727      * @throws DateTimeException if the day-of-month value is invalid
       
   728      * @throws DateTimeException if the day-of-month is invalid for the month-year
       
   729      */
       
   730     public OffsetDate withDayOfMonth(int dayOfMonth) {
       
   731         return with(date.withDayOfMonth(dayOfMonth), offset);
       
   732     }
       
   733 
       
   734     /**
       
   735      * Returns a copy of this {@code OffsetDate} with the day-of-year altered.
       
   736      * If the resulting date is invalid, an exception is thrown.
       
   737      * <p>
       
   738      * This instance is immutable and unaffected by this method call.
       
   739      *
       
   740      * @param dayOfYear  the day-of-year to set in the result, from 1 to 365-366
       
   741      * @return an {@code OffsetDate} based on this date with the requested day, not null
       
   742      * @throws DateTimeException if the day-of-year value is invalid
       
   743      * @throws DateTimeException if the day-of-year is invalid for the year
       
   744      */
       
   745     public OffsetDate withDayOfYear(int dayOfYear) {
       
   746         return with(date.withDayOfYear(dayOfYear), offset);
       
   747     }
       
   748 
       
   749     //-----------------------------------------------------------------------
       
   750     /**
       
   751      * Returns a copy of this date with the specified period added.
       
   752      * <p>
       
   753      * This method returns a new date based on this date with the specified period added.
       
   754      * The adder is typically {@link java.time.Period} but may be any other type implementing
       
   755      * the {@link TemporalAdder} interface.
       
   756      * The calculation is delegated to the specified adjuster, which typically calls
       
   757      * back to {@link #plus(long, TemporalUnit)}.
       
   758      * The offset is not part of the calculation and will be unchanged in the result.
       
   759      * <p>
       
   760      * This instance is immutable and unaffected by this method call.
       
   761      *
       
   762      * @param adder  the adder to use, not null
       
   763      * @return an {@code OffsetDate} based on this date with the addition made, not null
       
   764      * @throws DateTimeException if the addition cannot be made
       
   765      * @throws ArithmeticException if numeric overflow occurs
       
   766      */
       
   767     @Override
       
   768     public OffsetDate plus(TemporalAdder adder) {
       
   769         return (OffsetDate) adder.addTo(this);
       
   770     }
       
   771 
       
   772     /**
       
   773      * Returns a copy of this date with the specified period added.
       
   774      * <p>
       
   775      * This method returns a new date based on this date with the specified period added.
       
   776      * This can be used to add any period that is defined by a unit, for example to add years, months or days.
       
   777      * The unit is responsible for the details of the calculation, including the resolution
       
   778      * of any edge cases in the calculation.
       
   779      * The offset is not part of the calculation and will be unchanged in the result.
       
   780      * <p>
       
   781      * This instance is immutable and unaffected by this method call.
       
   782      *
       
   783      * @param amountToAdd  the amount of the unit to add to the result, may be negative
       
   784      * @param unit  the unit of the period to add, not null
       
   785      * @return an {@code OffsetDate} based on this date with the specified period added, not null
       
   786      * @throws DateTimeException if the unit cannot be added to this type
       
   787      */
       
   788     @Override
       
   789     public OffsetDate plus(long amountToAdd, TemporalUnit unit) {
       
   790         if (unit instanceof ChronoUnit) {
       
   791             return with(date.plus(amountToAdd, unit), offset);
       
   792         }
       
   793         return unit.doPlus(this, amountToAdd);
       
   794     }
       
   795 
       
   796     //-----------------------------------------------------------------------
       
   797     /**
       
   798      * Returns a copy of this {@code OffsetDate} with the specified period in years added.
       
   799      * <p>
       
   800      * This method adds the specified amount to the years field in three steps:
       
   801      * <ol>
       
   802      * <li>Add the input years to the year field</li>
       
   803      * <li>Check if the resulting date would be invalid</li>
       
   804      * <li>Adjust the day-of-month to the last valid day if necessary</li>
       
   805      * </ol>
       
   806      * <p>
       
   807      * For example, 2008-02-29 (leap year) plus one year would result in the
       
   808      * invalid date 2009-02-29 (standard year). Instead of returning an invalid
       
   809      * result, the last valid day of the month, 2009-02-28, is selected instead.
       
   810      * <p>
       
   811      * This instance is immutable and unaffected by this method call.
       
   812      *
       
   813      * @param years  the years to add, may be negative
       
   814      * @return an {@code OffsetDate} based on this date with the years added, not null
       
   815      * @throws DateTimeException if the result exceeds the supported date range
       
   816      */
       
   817     public OffsetDate plusYears(long years) {
       
   818         return with(date.plusYears(years), offset);
       
   819     }
       
   820 
       
   821     /**
       
   822      * Returns a copy of this {@code OffsetDate} with the specified period in months added.
       
   823      * <p>
       
   824      * This method adds the specified amount to the months field in three steps:
       
   825      * <ol>
       
   826      * <li>Add the input months to the month-of-year field</li>
       
   827      * <li>Check if the resulting date would be invalid</li>
       
   828      * <li>Adjust the day-of-month to the last valid day if necessary</li>
       
   829      * </ol>
       
   830      * <p>
       
   831      * For example, 2007-03-31 plus one month would result in the invalid date
       
   832      * 2007-04-31. Instead of returning an invalid result, the last valid day
       
   833      * of the month, 2007-04-30, is selected instead.
       
   834      * <p>
       
   835      * This instance is immutable and unaffected by this method call.
       
   836      *
       
   837      * @param months  the months to add, may be negative
       
   838      * @return an {@code OffsetDate} based on this date with the months added, not null
       
   839      * @throws DateTimeException if the result exceeds the supported date range
       
   840      */
       
   841     public OffsetDate plusMonths(long months) {
       
   842         return with(date.plusMonths(months), offset);
       
   843     }
       
   844 
       
   845     /**
       
   846      * Returns a copy of this {@code OffsetDate} with the specified period in weeks added.
       
   847      * <p>
       
   848      * This method adds the specified amount in weeks to the days field incrementing
       
   849      * the month and year fields as necessary to ensure the result remains valid.
       
   850      * The result is only invalid if the maximum/minimum year is exceeded.
       
   851      * <p>
       
   852      * For example, 2008-12-31 plus one week would result in 2009-01-07.
       
   853      * <p>
       
   854      * This instance is immutable and unaffected by this method call.
       
   855      *
       
   856      * @param weeks  the weeks to add, may be negative
       
   857      * @return an {@code OffsetDate} based on this date with the weeks added, not null
       
   858      * @throws DateTimeException if the result exceeds the supported date range
       
   859      */
       
   860     public OffsetDate plusWeeks(long weeks) {
       
   861         return with(date.plusWeeks(weeks), offset);
       
   862     }
       
   863 
       
   864     /**
       
   865      * Returns a copy of this {@code OffsetDate} with the specified period in days added.
       
   866      * <p>
       
   867      * This method adds the specified amount to the days field incrementing the
       
   868      * month and year fields as necessary to ensure the result remains valid.
       
   869      * The result is only invalid if the maximum/minimum year is exceeded.
       
   870      * <p>
       
   871      * For example, 2008-12-31 plus one day would result in 2009-01-01.
       
   872      * <p>
       
   873      * This instance is immutable and unaffected by this method call.
       
   874      *
       
   875      * @param days  the days to add, may be negative
       
   876      * @return an {@code OffsetDate} based on this date with the days added, not null
       
   877      * @throws DateTimeException if the result exceeds the supported date range
       
   878      */
       
   879     public OffsetDate plusDays(long days) {
       
   880         return with(date.plusDays(days), offset);
       
   881     }
       
   882 
       
   883     //-----------------------------------------------------------------------
       
   884     /**
       
   885      * Returns a copy of this date with the specified period subtracted.
       
   886      * <p>
       
   887      * This method returns a new date based on this date with the specified period subtracted.
       
   888      * The subtractor is typically {@link java.time.Period} but may be any other type implementing
       
   889      * the {@link TemporalSubtractor} interface.
       
   890      * The calculation is delegated to the specified adjuster, which typically calls
       
   891      * back to {@link #minus(long, TemporalUnit)}.
       
   892      * The offset is not part of the calculation and will be unchanged in the result.
       
   893      * <p>
       
   894      * This instance is immutable and unaffected by this method call.
       
   895      *
       
   896      * @param subtractor  the subtractor to use, not null
       
   897      * @return an {@code OffsetDate} based on this date with the subtraction made, not null
       
   898      * @throws DateTimeException if the subtraction cannot be made
       
   899      * @throws ArithmeticException if numeric overflow occurs
       
   900      */
       
   901     @Override
       
   902     public OffsetDate minus(TemporalSubtractor subtractor) {
       
   903         return (OffsetDate) subtractor.subtractFrom(this);
       
   904     }
       
   905 
       
   906     /**
       
   907      * Returns a copy of this date with the specified period subtracted.
       
   908      * <p>
       
   909      * This method returns a new date based on this date with the specified period subtracted.
       
   910      * This can be used to subtract any period that is defined by a unit, for example to subtract years, months or days.
       
   911      * The unit is responsible for the details of the calculation, including the resolution
       
   912      * of any edge cases in the calculation.
       
   913      * The offset is not part of the calculation and will be unchanged in the result.
       
   914      * <p>
       
   915      * This instance is immutable and unaffected by this method call.
       
   916      *
       
   917      * @param amountToSubtract  the amount of the unit to subtract from the result, may be negative
       
   918      * @param unit  the unit of the period to subtract, not null
       
   919      * @return an {@code OffsetDate} based on this date with the specified period subtracted, not null
       
   920      * @throws DateTimeException if the unit cannot be added to this type
       
   921      */
       
   922     @Override
       
   923     public OffsetDate minus(long amountToSubtract, TemporalUnit unit) {
       
   924         return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
       
   925     }
       
   926 
       
   927     //-----------------------------------------------------------------------
       
   928     /**
       
   929      * Returns a copy of this {@code OffsetDate} with the specified period in years subtracted.
       
   930      * <p>
       
   931      * This method subtracts the specified amount from the years field in three steps:
       
   932      * <ol>
       
   933      * <li>Subtract the input years to the year field</li>
       
   934      * <li>Check if the resulting date would be invalid</li>
       
   935      * <li>Adjust the day-of-month to the last valid day if necessary</li>
       
   936      * </ol>
       
   937      * <p>
       
   938      * For example, 2008-02-29 (leap year) minus one year would result in the
       
   939      * invalid date 2007-02-29 (standard year). Instead of returning an invalid
       
   940      * result, the last valid day of the month, 2007-02-28, is selected instead.
       
   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     /**
       
   953      * Returns a copy of this {@code OffsetDate} with the specified period in months subtracted.
       
   954      * <p>
       
   955      * This method subtracts the specified amount from the months field in three steps:
       
   956      * <ol>
       
   957      * <li>Subtract the input months to the month-of-year field</li>
       
   958      * <li>Check if the resulting date would be invalid</li>
       
   959      * <li>Adjust the day-of-month to the last valid day if necessary</li>
       
   960      * </ol>
       
   961      * <p>
       
   962      * For example, 2007-03-31 minus one month would result in the invalid date
       
   963      * 2007-02-31. Instead of returning an invalid result, the last valid day
       
   964      * of the month, 2007-02-28, is selected instead.
       
   965      * <p>
       
   966      * This instance is immutable and unaffected by this method call.
       
   967      *
       
   968      * @param months  the months to subtract, may be negative
       
   969      * @return an {@code OffsetDate} based on this date with the months subtracted, not null
       
   970      * @throws DateTimeException if the result exceeds the supported date range
       
   971      */
       
   972     public OffsetDate minusMonths(long months) {
       
   973         return with(date.minusMonths(months), offset);
       
   974     }
       
   975 
       
   976     /**
       
   977      * Returns a copy of this {@code OffsetDate} with the specified period in weeks subtracted.
       
   978      * <p>
       
   979      * This method subtracts the specified amount in weeks from the days field decrementing
       
   980      * the month and year fields as necessary to ensure the result remains valid.
       
   981      * The result is only invalid if the maximum/minimum year is exceeded.
       
   982      * <p>
       
   983      * For example, 2009-01-07 minus one week would result in 2008-12-31.
       
   984      * <p>
       
   985      * This instance is immutable and unaffected by this method call.
       
   986      *
       
   987      * @param weeks  the weeks to subtract, may be negative
       
   988      * @return an {@code OffsetDate} based on this date with the weeks subtracted, not null
       
   989      * @throws DateTimeException if the result exceeds the supported date range
       
   990      */
       
   991     public OffsetDate minusWeeks(long weeks) {
       
   992         return with(date.minusWeeks(weeks), offset);
       
   993     }
       
   994 
       
   995     /**
       
   996      * Returns a copy of this {@code OffsetDate} with the specified number of days subtracted.
       
   997      * <p>
       
   998      * This method subtracts the specified amount from the days field decrementing the
       
   999      * month and year fields as necessary to ensure the result remains valid.
       
  1000      * The result is only invalid if the maximum/minimum year is exceeded.
       
  1001      * <p>
       
  1002      * For example, 2009-01-01 minus one day would result in 2008-12-31.
       
  1003      * <p>
       
  1004      * This instance is immutable and unaffected by this method call.
       
  1005      *
       
  1006      * @param days  the days to subtract, may be negative
       
  1007      * @return an {@code OffsetDate} based on this date with the days subtracted, not null
       
  1008      * @throws DateTimeException if the result exceeds the supported date range
       
  1009      */
       
  1010     public OffsetDate minusDays(long days) {
       
  1011         return with(date.minusDays(days), offset);
       
  1012     }
       
  1013 
       
  1014     //-----------------------------------------------------------------------
       
  1015     /**
       
  1016      * Queries this date using the specified query.
       
  1017      * <p>
       
  1018      * This queries this date using the specified query strategy object.
       
  1019      * The {@code TemporalQuery} object defines the logic to be used to
       
  1020      * obtain the result. Read the documentation of the query to understand
       
  1021      * what the result of this method will be.
       
  1022      * <p>
       
  1023      * The result of this method is obtained by invoking the
       
  1024      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
       
  1025      * specified query passing {@code this} as the argument.
       
  1026      *
       
  1027      * @param <R> the type of the result
       
  1028      * @param query  the query to invoke, not null
       
  1029      * @return the query result, null may be returned (defined by the query)
       
  1030      * @throws DateTimeException if unable to query (defined by the query)
       
  1031      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
       
  1032      */
       
  1033     @SuppressWarnings("unchecked")
       
  1034     @Override
       
  1035     public <R> R query(TemporalQuery<R> query) {
       
  1036         if (query == Queries.chrono()) {
       
  1037             return (R) ISOChrono.INSTANCE;
       
  1038         } else if (query == Queries.precision()) {
       
  1039             return (R) DAYS;
       
  1040         } else if (query == Queries.offset() || query == Queries.zone()) {
       
  1041             return (R) getOffset();
       
  1042         }
       
  1043         return Temporal.super.query(query);
       
  1044     }
       
  1045 
       
  1046     /**
       
  1047      * Adjusts the specified temporal object to have the same offset and date
       
  1048      * as this object.
       
  1049      * <p>
       
  1050      * This returns a temporal object of the same observable type as the input
       
  1051      * with the offset and date changed to be the same as this.
       
  1052      * <p>
       
  1053      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
       
  1054      * twice, passing {@link ChronoField#OFFSET_SECONDS} and
       
  1055      * {@link ChronoField#EPOCH_DAY} as the fields.
       
  1056      * <p>
       
  1057      * In most cases, it is clearer to reverse the calling pattern by using
       
  1058      * {@link Temporal#with(TemporalAdjuster)}:
       
  1059      * <pre>
       
  1060      *   // these two lines are equivalent, but the second approach is recommended
       
  1061      *   temporal = thisOffsetDate.adjustInto(temporal);
       
  1062      *   temporal = temporal.with(thisOffsetDate);
       
  1063      * </pre>
       
  1064      * <p>
       
  1065      * This instance is immutable and unaffected by this method call.
       
  1066      *
       
  1067      * @param temporal  the target object to be adjusted, not null
       
  1068      * @return the adjusted object, not null
       
  1069      * @throws DateTimeException if unable to make the adjustment
       
  1070      * @throws ArithmeticException if numeric overflow occurs
       
  1071      */
       
  1072     @Override
       
  1073     public Temporal adjustInto(Temporal temporal) {
       
  1074         return temporal
       
  1075                 .with(OFFSET_SECONDS, getOffset().getTotalSeconds())
       
  1076                 .with(EPOCH_DAY, getDate().toEpochDay());
       
  1077     }
       
  1078 
       
  1079     /**
       
  1080      * Calculates the period between this date and another date in
       
  1081      * terms of the specified unit.
       
  1082      * <p>
       
  1083      * This calculates the period between two dates in terms of a single unit.
       
  1084      * The start and end points are {@code this} and the specified date.
       
  1085      * The result will be negative if the end is before the start.
       
  1086      * For example, the period in days between two dates can be calculated
       
  1087      * using {@code startDate.periodUntil(endDate, DAYS)}.
       
  1088      * <p>
       
  1089      * The {@code Temporal} passed to this method must be an {@code OffsetDate}.
       
  1090      * If the offset differs between the two times, then the specified
       
  1091      * end time is normalized to have the same offset as this time.
       
  1092      * <p>
       
  1093      * The calculation returns a whole number, representing the number of
       
  1094      * complete units between the two dates.
       
  1095      * For example, the period in months between 2012-06-15Z and 2012-08-14Z
       
  1096      * will only be one month as it is one day short of two months.
       
  1097      * <p>
       
  1098      * This method operates in association with {@link TemporalUnit#between}.
       
  1099      * The result of this method is a {@code long} representing the amount of
       
  1100      * the specified unit. By contrast, the result of {@code between} is an
       
  1101      * object that can be used directly in addition/subtraction:
       
  1102      * <pre>
       
  1103      *   long period = start.periodUntil(end, MONTHS);   // this method
       
  1104      *   dateTime.plus(MONTHS.between(start, end));      // use in plus/minus
       
  1105      * </pre>
       
  1106      * <p>
       
  1107      * The calculation is implemented in this method for {@link ChronoUnit}.
       
  1108      * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS},
       
  1109      * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS}
       
  1110      * are supported. Other {@code ChronoUnit} values will throw an exception.
       
  1111      * <p>
       
  1112      * If the unit is not a {@code ChronoUnit}, then the result of this method
       
  1113      * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
       
  1114      * passing {@code this} as the first argument and the input temporal as
       
  1115      * the second argument.
       
  1116      * <p>
       
  1117      * This instance is immutable and unaffected by this method call.
       
  1118      *
       
  1119      * @param endDate  the end date, which must be an {@code OffsetDate}, not null
       
  1120      * @param unit  the unit to measure the period in, not null
       
  1121      * @return the amount of the period between this date and the end date
       
  1122      * @throws DateTimeException if the period cannot be calculated
       
  1123      * @throws ArithmeticException if numeric overflow occurs
       
  1124      */
       
  1125     @Override
       
  1126     public long periodUntil(Temporal endDate, TemporalUnit unit) {
       
  1127         if (endDate instanceof OffsetDate == false) {
       
  1128             Objects.requireNonNull(endDate, "endDate");
       
  1129             throw new DateTimeException("Unable to calculate period between objects of two different types");
       
  1130         }
       
  1131         if (unit instanceof ChronoUnit) {
       
  1132             OffsetDate end = (OffsetDate) endDate;
       
  1133             long offsetDiff = end.offset.getTotalSeconds() - offset.getTotalSeconds();
       
  1134             LocalDate endLocal = end.date.plusDays(Math.floorDiv(-offsetDiff, SECONDS_PER_DAY));
       
  1135             return date.periodUntil(endLocal, unit);
       
  1136         }
       
  1137         return unit.between(this, endDate).getAmount();
       
  1138     }
       
  1139 
       
  1140     //-----------------------------------------------------------------------
       
  1141     /**
       
  1142      * Returns an offset date-time formed from this date at the specified time.
       
  1143      * <p>
       
  1144      * This combines this date with the specified time to form an {@code OffsetDateTime}.
       
  1145      * All possible combinations of date and time are valid.
       
  1146      * <p>
       
  1147      * This instance is immutable and unaffected by this method call.
       
  1148      *
       
  1149      * @param time  the time to combine with, not null
       
  1150      * @return the offset date-time formed from this date and the specified time, not null
       
  1151      */
       
  1152     public OffsetDateTime atTime(LocalTime time) {
       
  1153         return OffsetDateTime.of(date, time, offset);
       
  1154     }
       
  1155 
       
  1156     //-----------------------------------------------------------------------
       
  1157     /**
       
  1158      * Converts this date to midnight at the start of day in epoch seconds.
       
  1159      *
       
  1160      * @return the epoch seconds value
       
  1161      */
       
  1162     private long toEpochSecond() {
       
  1163         long epochDay = date.toEpochDay();
       
  1164         long secs = epochDay * SECONDS_PER_DAY;
       
  1165         return secs - offset.getTotalSeconds();
       
  1166     }
       
  1167 
       
  1168     //-----------------------------------------------------------------------
       
  1169     /**
       
  1170      * Compares this {@code OffsetDate} to another date.
       
  1171      * <p>
       
  1172      * The comparison is based first on the UTC equivalent instant, then on the local date.
       
  1173      * It is "consistent with equals", as defined by {@link Comparable}.
       
  1174      * <p>
       
  1175      * For example, the following is the comparator order:
       
  1176      * <ol>
       
  1177      * <li>2008-06-29-11:00</li>
       
  1178      * <li>2008-06-29-12:00</li>
       
  1179      * <li>2008-06-30+12:00</li>
       
  1180      * <li>2008-06-29-13:00</li>
       
  1181      * </ol>
       
  1182      * Values #2 and #3 represent the same instant on the time-line.
       
  1183      * When two values represent the same instant, the local date is compared
       
  1184      * to distinguish them. This step is needed to make the ordering
       
  1185      * consistent with {@code equals()}.
       
  1186      * <p>
       
  1187      * To compare the underlying local date of two {@code TemporalAccessor} instances,
       
  1188      * use {@link ChronoField#EPOCH_DAY} as a comparator.
       
  1189      *
       
  1190      * @param other  the other date to compare to, not null
       
  1191      * @return the comparator value, negative if less, positive if greater
       
  1192      */
       
  1193     @Override
       
  1194     public int compareTo(OffsetDate other) {
       
  1195         if (offset.equals(other.offset)) {
       
  1196             return date.compareTo(other.date);
       
  1197         }
       
  1198         int compare = Long.compare(toEpochSecond(), other.toEpochSecond());
       
  1199         if (compare == 0) {
       
  1200             compare = date.compareTo(other.date);
       
  1201         }
       
  1202         return compare;
       
  1203     }
       
  1204 
       
  1205     //-----------------------------------------------------------------------
       
  1206     /**
       
  1207      * Checks if the instant of midnight at the start of this {@code OffsetDate}
       
  1208      * is after midnight at the start of the specified date.
       
  1209      * <p>
       
  1210      * This method differs from the comparison in {@link #compareTo} in that it
       
  1211      * only compares the instant of the date. This is equivalent to using
       
  1212      * {@code date1.toEpochSecond().isAfter(date2.toEpochSecond())}.
       
  1213      *
       
  1214      * @param other  the other date to compare to, not null
       
  1215      * @return true if this is after the instant of the specified date
       
  1216      */
       
  1217     public boolean isAfter(OffsetDate other) {
       
  1218         return toEpochSecond() > other.toEpochSecond();
       
  1219     }
       
  1220 
       
  1221     /**
       
  1222      * Checks if the instant of midnight at the start of this {@code OffsetDate}
       
  1223      * is before midnight at the start of the specified date.
       
  1224      * <p>
       
  1225      * This method differs from the comparison in {@link #compareTo} in that it
       
  1226      * only compares the instant of the date. This is equivalent to using
       
  1227      * {@code date1.toEpochSecond().isBefore(date2.toEpochSecond())}.
       
  1228      *
       
  1229      * @param other  the other date to compare to, not null
       
  1230      * @return true if this is before the instant of the specified date
       
  1231      */
       
  1232     public boolean isBefore(OffsetDate other) {
       
  1233         return toEpochSecond() < other.toEpochSecond();
       
  1234     }
       
  1235 
       
  1236     /**
       
  1237      * Checks if the instant of midnight at the start of this {@code OffsetDate}
       
  1238      * equals midnight at the start of the specified date.
       
  1239      * <p>
       
  1240      * This method differs from the comparison in {@link #compareTo} and {@link #equals}
       
  1241      * in that it only compares the instant of the date. This is equivalent to using
       
  1242      * {@code date1.toEpochSecond().equals(date2.toEpochSecond())}.
       
  1243      *
       
  1244      * @param other  the other date to compare to, not null
       
  1245      * @return true if the instant equals the instant of the specified date
       
  1246      */
       
  1247     public boolean isEqual(OffsetDate other) {
       
  1248         return toEpochSecond() == other.toEpochSecond();
       
  1249     }
       
  1250 
       
  1251     //-----------------------------------------------------------------------
       
  1252     /**
       
  1253      * Checks if this date is equal to another date.
       
  1254      * <p>
       
  1255      * The comparison is based on the local-date and the offset.
       
  1256      * To compare for the same instant on the time-line, use {@link #isEqual(OffsetDate)}.
       
  1257      * <p>
       
  1258      * Only objects of type {@code OffsetDate} are compared, other types return false.
       
  1259      * To compare the underlying local date of two {@code TemporalAccessor} instances,
       
  1260      * use {@link ChronoField#EPOCH_DAY} as a comparator.
       
  1261      *
       
  1262      * @param obj  the object to check, null returns false
       
  1263      * @return true if this is equal to the other date
       
  1264      */
       
  1265     @Override
       
  1266     public boolean equals(Object obj) {
       
  1267         if (this == obj) {
       
  1268             return true;
       
  1269         }
       
  1270         if (obj instanceof OffsetDate) {
       
  1271             OffsetDate other = (OffsetDate) obj;
       
  1272             return date.equals(other.date) && offset.equals(other.offset);
       
  1273         }
       
  1274         return false;
       
  1275     }
       
  1276 
       
  1277     /**
       
  1278      * A hash code for this date.
       
  1279      *
       
  1280      * @return a suitable hash code
       
  1281      */
       
  1282     @Override
       
  1283     public int hashCode() {
       
  1284         return date.hashCode() ^ offset.hashCode();
       
  1285     }
       
  1286 
       
  1287     //-----------------------------------------------------------------------
       
  1288     /**
       
  1289      * Outputs this date as a {@code String}, such as {@code 2007-12-03+01:00}.
       
  1290      * <p>
       
  1291      * The output will be in the ISO-8601 format {@code yyyy-MM-ddXXXXX}.
       
  1292      *
       
  1293      * @return a string representation of this date, not null
       
  1294      */
       
  1295     @Override
       
  1296     public String toString() {
       
  1297         return date.toString() + offset.toString();
       
  1298     }
       
  1299 
       
  1300     /**
       
  1301      * Outputs this date as a {@code String} using the formatter.
       
  1302      * <p>
       
  1303      * This date will be passed to the formatter
       
  1304      * {@link DateTimeFormatter#print(TemporalAccessor) print method}.
       
  1305      *
       
  1306      * @param formatter  the formatter to use, not null
       
  1307      * @return the formatted date string, not null
       
  1308      * @throws DateTimeException if an error occurs during printing
       
  1309      */
       
  1310     public String toString(DateTimeFormatter formatter) {
       
  1311         Objects.requireNonNull(formatter, "formatter");
       
  1312         return formatter.print(this);
       
  1313     }
       
  1314 
       
  1315     //-----------------------------------------------------------------------
       
  1316     /**
       
  1317      * Writes the object using a
       
  1318      * <a href="../../../serialized-form.html#java.time.temporal.Ser">dedicated serialized form</a>.
       
  1319      * <pre>
       
  1320      *  out.writeByte(1);  // identifies this as a OffsetDateTime
       
  1321      *  out.writeObject(date);
       
  1322      *  out.writeObject(offset);
       
  1323      * </pre>
       
  1324      *
       
  1325      * @return the instance of {@code Ser}, not null
       
  1326      */
       
  1327     private Object writeReplace() {
       
  1328         return new Ser(Ser.OFFSET_DATE_TYPE, this);
       
  1329     }
       
  1330 
       
  1331     /**
       
  1332      * Defend against malicious streams.
       
  1333      * @return never
       
  1334      * @throws InvalidObjectException always
       
  1335      */
       
  1336     private Object readResolve() throws ObjectStreamException {
       
  1337         throw new InvalidObjectException("Deserialization via serialization delegate");
       
  1338     }
       
  1339 
       
  1340     void writeExternal(ObjectOutput out) throws IOException {
       
  1341         out.writeObject(date);
       
  1342         out.writeObject(offset);
       
  1343     }
       
  1344 
       
  1345     static OffsetDate readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
       
  1346         LocalDate date = (LocalDate) in.readObject();
       
  1347         ZoneOffset offset = (ZoneOffset) in.readObject();
       
  1348         return OffsetDate.of(date, offset);
       
  1349     }
       
  1350 
       
  1351 }