jdk/src/share/classes/java/time/temporal/ChronoZonedDateTime.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.INSTANT_SECONDS;
       
    65 import static java.time.temporal.ChronoField.OFFSET_SECONDS;
       
    66 import static java.time.temporal.ChronoUnit.NANOS;
       
    67 
       
    68 import java.time.DateTimeException;
       
    69 import java.time.Instant;
       
    70 import java.time.LocalTime;
       
    71 import java.time.ZoneId;
       
    72 import java.time.ZoneOffset;
       
    73 import java.time.ZonedDateTime;
       
    74 import java.time.format.DateTimeFormatter;
       
    75 import java.util.Comparator;
       
    76 import java.util.Objects;
       
    77 
       
    78 /**
       
    79  * A date-time with a time-zone in an arbitrary chronology,
       
    80  * intended for advanced globalization use cases.
       
    81  * <p>
       
    82  * <b>Most applications should declare method signatures, fields and variables
       
    83  * as {@link ZonedDateTime}, not this interface.</b>
       
    84  * <p>
       
    85  * A {@code ChronoZonedDateTime} is the abstract representation of an offset date-time
       
    86  * where the {@code Chrono chronology}, or calendar system, is pluggable.
       
    87  * The date-time is defined in terms of fields expressed by {@link TemporalField},
       
    88  * where most common implementations are defined in {@link ChronoField}.
       
    89  * The chronology defines how the calendar system operates and the meaning of
       
    90  * the standard fields.
       
    91  *
       
    92  * <h3>When to use this interface</h3>
       
    93  * The design of the API encourages the use of {@code ZonedDateTime} rather than this
       
    94  * interface, even in the case where the application needs to deal with multiple
       
    95  * calendar systems. The rationale for this is explored in detail in {@link ChronoLocalDate}.
       
    96  * <p>
       
    97  * Ensure that the discussion in {@code ChronoLocalDate} has been read and understood
       
    98  * before using this interface.
       
    99  *
       
   100  * <h3>Specification for implementors</h3>
       
   101  * This interface must be implemented with care to ensure other classes operate correctly.
       
   102  * All implementations that can be instantiated must be final, immutable and thread-safe.
       
   103  * Subclasses should be Serializable wherever possible.
       
   104  *
       
   105  * @param <C> the chronology of this date-time
       
   106  * @since 1.8
       
   107  */
       
   108 public interface ChronoZonedDateTime<C extends Chrono<C>>
       
   109         extends Temporal, Comparable<ChronoZonedDateTime<?>> {
       
   110 
       
   111     /**
       
   112      * Comparator for two {@code ChronoZonedDateTime} instances ignoring the chronology.
       
   113      * <p>
       
   114      * This method differs from the comparison in {@link #compareTo} in that it
       
   115      * only compares the underlying date and not the chronology.
       
   116      * This allows dates in different calendar systems to be compared based
       
   117      * on the time-line position.
       
   118      *
       
   119      * @see #isAfter
       
   120      * @see #isBefore
       
   121      * @see #isEqual
       
   122      */
       
   123     Comparator<ChronoZonedDateTime<?>> INSTANT_COMPARATOR = new Comparator<ChronoZonedDateTime<?>>() {
       
   124         @Override
       
   125         public int compare(ChronoZonedDateTime<?> datetime1, ChronoZonedDateTime<?> datetime2) {
       
   126             int cmp = Long.compare(datetime1.toEpochSecond(), datetime2.toEpochSecond());
       
   127             if (cmp == 0) {
       
   128                 cmp = Long.compare(datetime1.getTime().toNanoOfDay(), datetime2.getTime().toNanoOfDay());
       
   129             }
       
   130             return cmp;
       
   131         }
       
   132     };
       
   133 
       
   134     @Override
       
   135     public default ValueRange range(TemporalField field) {
       
   136         if (field instanceof ChronoField) {
       
   137             if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) {
       
   138                 return field.range();
       
   139             }
       
   140             return getDateTime().range(field);
       
   141         }
       
   142         return field.doRange(this);
       
   143     }
       
   144 
       
   145     @Override
       
   146     public default int get(TemporalField field) {
       
   147         if (field instanceof ChronoField) {
       
   148             switch ((ChronoField) field) {
       
   149                 case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field);
       
   150                 case OFFSET_SECONDS: return getOffset().getTotalSeconds();
       
   151             }
       
   152             return getDateTime().get(field);
       
   153         }
       
   154         return Temporal.super.get(field);
       
   155     }
       
   156 
       
   157     @Override
       
   158     public default long getLong(TemporalField field) {
       
   159         if (field instanceof ChronoField) {
       
   160             switch ((ChronoField) field) {
       
   161                 case INSTANT_SECONDS: return toEpochSecond();
       
   162                 case OFFSET_SECONDS: return getOffset().getTotalSeconds();
       
   163             }
       
   164             return getDateTime().getLong(field);
       
   165         }
       
   166         return field.doGet(this);
       
   167     }
       
   168 
       
   169     /**
       
   170      * Gets the local date part of this date-time.
       
   171      * <p>
       
   172      * This returns a local date with the same year, month and day
       
   173      * as this date-time.
       
   174      *
       
   175      * @return the date part of this date-time, not null
       
   176      */
       
   177     public default ChronoLocalDate<C> getDate() {
       
   178         return getDateTime().getDate();
       
   179     }
       
   180 
       
   181     /**
       
   182      * Gets the local time part of this date-time.
       
   183      * <p>
       
   184      * This returns a local time with the same hour, minute, second and
       
   185      * nanosecond as this date-time.
       
   186      *
       
   187      * @return the time part of this date-time, not null
       
   188      */
       
   189     public default LocalTime getTime() {
       
   190         return getDateTime().getTime();
       
   191     }
       
   192 
       
   193     /**
       
   194      * Gets the local date-time part of this date-time.
       
   195      * <p>
       
   196      * This returns a local date with the same year, month and day
       
   197      * as this date-time.
       
   198      *
       
   199      * @return the local date-time part of this date-time, not null
       
   200      */
       
   201     ChronoLocalDateTime<C> getDateTime();
       
   202 
       
   203     /**
       
   204      * Gets the zone offset, such as '+01:00'.
       
   205      * <p>
       
   206      * This is the offset of the local date-time from UTC/Greenwich.
       
   207      *
       
   208      * @return the zone offset, not null
       
   209      */
       
   210     ZoneOffset getOffset();
       
   211 
       
   212     /**
       
   213      * Gets the zone ID, such as 'Europe/Paris'.
       
   214      * <p>
       
   215      * This returns the stored time-zone id used to determine the time-zone rules.
       
   216      *
       
   217      * @return the zone ID, not null
       
   218      */
       
   219     ZoneId getZone();
       
   220 
       
   221     //-----------------------------------------------------------------------
       
   222     /**
       
   223      * Returns a copy of this date-time changing the zone offset to the
       
   224      * earlier of the two valid offsets at a local time-line overlap.
       
   225      * <p>
       
   226      * This method only has any effect when the local time-line overlaps, such as
       
   227      * at an autumn daylight savings cutover. In this scenario, there are two
       
   228      * valid offsets for the local date-time. Calling this method will return
       
   229      * a zoned date-time with the earlier of the two selected.
       
   230      * <p>
       
   231      * If this method is called when it is not an overlap, {@code this}
       
   232      * is returned.
       
   233      * <p>
       
   234      * This instance is immutable and unaffected by this method call.
       
   235      *
       
   236      * @return a {@code ZoneChronoDateTime} based on this date-time with the earlier offset, not null
       
   237      * @throws DateTimeException if no rules can be found for the zone
       
   238      * @throws DateTimeException if no rules are valid for this date-time
       
   239      */
       
   240     ChronoZonedDateTime<C> withEarlierOffsetAtOverlap();
       
   241 
       
   242     /**
       
   243      * Returns a copy of this date-time changing the zone offset to the
       
   244      * later of the two valid offsets at a local time-line overlap.
       
   245      * <p>
       
   246      * This method only has any effect when the local time-line overlaps, such as
       
   247      * at an autumn daylight savings cutover. In this scenario, there are two
       
   248      * valid offsets for the local date-time. Calling this method will return
       
   249      * a zoned date-time with the later of the two selected.
       
   250      * <p>
       
   251      * If this method is called when it is not an overlap, {@code this}
       
   252      * is returned.
       
   253      * <p>
       
   254      * This instance is immutable and unaffected by this method call.
       
   255      *
       
   256      * @return a {@code ChronoZonedDateTime} based on this date-time with the later offset, not null
       
   257      * @throws DateTimeException if no rules can be found for the zone
       
   258      * @throws DateTimeException if no rules are valid for this date-time
       
   259      */
       
   260     ChronoZonedDateTime<C> withLaterOffsetAtOverlap();
       
   261 
       
   262     /**
       
   263      * Returns a copy of this ZonedDateTime with a different time-zone,
       
   264      * retaining the local date-time if possible.
       
   265      * <p>
       
   266      * This method changes the time-zone and retains the local date-time.
       
   267      * The local date-time is only changed if it is invalid for the new zone.
       
   268      * <p>
       
   269      * To change the zone and adjust the local date-time,
       
   270      * use {@link #withZoneSameInstant(ZoneId)}.
       
   271      * <p>
       
   272      * This instance is immutable and unaffected by this method call.
       
   273      *
       
   274      * @param zone  the time-zone to change to, not null
       
   275      * @return a {@code ChronoZonedDateTime} based on this date-time with the requested zone, not null
       
   276      */
       
   277     ChronoZonedDateTime<C> withZoneSameLocal(ZoneId zone);
       
   278 
       
   279     /**
       
   280      * Returns a copy of this date-time with a different time-zone,
       
   281      * retaining the instant.
       
   282      * <p>
       
   283      * This method changes the time-zone and retains the instant.
       
   284      * This normally results in a change to the local date-time.
       
   285      * <p>
       
   286      * This method is based on retaining the same instant, thus gaps and overlaps
       
   287      * in the local time-line have no effect on the result.
       
   288      * <p>
       
   289      * To change the offset while keeping the local time,
       
   290      * use {@link #withZoneSameLocal(ZoneId)}.
       
   291      *
       
   292      * @param zone  the time-zone to change to, not null
       
   293      * @return a {@code ChronoZonedDateTime} based on this date-time with the requested zone, not null
       
   294      * @throws DateTimeException if the result exceeds the supported date range
       
   295      */
       
   296     ChronoZonedDateTime<C> withZoneSameInstant(ZoneId zone);
       
   297 
       
   298     //-----------------------------------------------------------------------
       
   299     // override for covariant return type
       
   300     /**
       
   301      * {@inheritDoc}
       
   302      * @throws DateTimeException {@inheritDoc}
       
   303      * @throws ArithmeticException {@inheritDoc}
       
   304      */
       
   305     @Override
       
   306     public default ChronoZonedDateTime<C> with(TemporalAdjuster adjuster) {
       
   307         return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.with(adjuster));
       
   308     }
       
   309 
       
   310     /**
       
   311      * {@inheritDoc}
       
   312      * @throws DateTimeException {@inheritDoc}
       
   313      * @throws ArithmeticException {@inheritDoc}
       
   314      */
       
   315     @Override
       
   316     ChronoZonedDateTime<C> with(TemporalField field, long newValue);
       
   317 
       
   318     /**
       
   319      * {@inheritDoc}
       
   320      * @throws DateTimeException {@inheritDoc}
       
   321      * @throws ArithmeticException {@inheritDoc}
       
   322      */
       
   323     @Override
       
   324     public default ChronoZonedDateTime<C> plus(TemporalAdder adder) {
       
   325         return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.plus(adder));
       
   326     }
       
   327 
       
   328     /**
       
   329      * {@inheritDoc}
       
   330      * @throws DateTimeException {@inheritDoc}
       
   331      * @throws ArithmeticException {@inheritDoc}
       
   332      */
       
   333     @Override
       
   334     ChronoZonedDateTime<C> plus(long amountToAdd, TemporalUnit unit);
       
   335 
       
   336     /**
       
   337      * {@inheritDoc}
       
   338      * @throws DateTimeException {@inheritDoc}
       
   339      * @throws ArithmeticException {@inheritDoc}
       
   340      */
       
   341     @Override
       
   342     public default ChronoZonedDateTime<C> minus(TemporalSubtractor subtractor) {
       
   343         return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.minus(subtractor));
       
   344     }
       
   345 
       
   346     /**
       
   347      * {@inheritDoc}
       
   348      * @throws DateTimeException {@inheritDoc}
       
   349      * @throws ArithmeticException {@inheritDoc}
       
   350      */
       
   351     @Override
       
   352     public default ChronoZonedDateTime<C> minus(long amountToSubtract, TemporalUnit unit) {
       
   353         return getDate().getChrono().ensureChronoZonedDateTime(Temporal.super.minus(amountToSubtract, unit));
       
   354     }
       
   355 
       
   356     //-----------------------------------------------------------------------
       
   357     /**
       
   358      * Queries this date-time using the specified query.
       
   359      * <p>
       
   360      * This queries this date-time using the specified query strategy object.
       
   361      * The {@code TemporalQuery} object defines the logic to be used to
       
   362      * obtain the result. Read the documentation of the query to understand
       
   363      * what the result of this method will be.
       
   364      * <p>
       
   365      * The result of this method is obtained by invoking the
       
   366      * {@link java.time.temporal.TemporalQuery#queryFrom(TemporalAccessor)} method on the
       
   367      * specified query passing {@code this} as the argument.
       
   368      *
       
   369      * @param <R> the type of the result
       
   370      * @param query  the query to invoke, not null
       
   371      * @return the query result, null may be returned (defined by the query)
       
   372      * @throws DateTimeException if unable to query (defined by the query)
       
   373      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
       
   374      */
       
   375     @SuppressWarnings("unchecked")
       
   376     @Override
       
   377     public default <R> R query(TemporalQuery<R> query) {
       
   378         if (query == Queries.zone() || query == Queries.zoneId()) {
       
   379             return (R) getZone();
       
   380         } else if (query == Queries.chrono()) {
       
   381             return (R) getDate().getChrono();
       
   382         } else if (query == Queries.precision()) {
       
   383             return (R) NANOS;
       
   384         } else if (query == Queries.offset()) {
       
   385             return (R) getOffset();
       
   386         }
       
   387         // inline TemporalAccessor.super.query(query) as an optimization
       
   388         return query.queryFrom(this);
       
   389     }
       
   390 
       
   391     //-----------------------------------------------------------------------
       
   392     /**
       
   393      * Converts this date-time to an {@code Instant}.
       
   394      * <p>
       
   395      * This combines the {@linkplain #getDateTime() local date-time} and
       
   396      * {@linkplain #getOffset() offset} to form an {@code Instant}.
       
   397      *
       
   398      * @return an {@code Instant} representing the same instant, not null
       
   399      */
       
   400     public default Instant toInstant() {
       
   401         return Instant.ofEpochSecond(toEpochSecond(), getTime().getNano());
       
   402     }
       
   403 
       
   404     /**
       
   405      * Converts this date-time to the number of seconds from the epoch
       
   406      * of 1970-01-01T00:00:00Z.
       
   407      * <p>
       
   408      * This uses the {@linkplain #getDateTime() local date-time} and
       
   409      * {@linkplain #getOffset() offset} to calculate the epoch-second value,
       
   410      * which is the number of elapsed seconds from 1970-01-01T00:00:00Z.
       
   411      * Instants on the time-line after the epoch are positive, earlier are negative.
       
   412      *
       
   413      * @return the number of seconds from the epoch of 1970-01-01T00:00:00Z
       
   414      */
       
   415     public default long toEpochSecond() {
       
   416         long epochDay = getDate().toEpochDay();
       
   417         long secs = epochDay * 86400 + getTime().toSecondOfDay();
       
   418         secs -= getOffset().getTotalSeconds();
       
   419         return secs;
       
   420     }
       
   421 
       
   422     //-----------------------------------------------------------------------
       
   423     /**
       
   424      * Compares this date-time to another date-time, including the chronology.
       
   425      * <p>
       
   426      * The comparison is based first on the instant, then on the local date-time,
       
   427      * then on the zone ID, then on the chronology.
       
   428      * It is "consistent with equals", as defined by {@link Comparable}.
       
   429      * <p>
       
   430      * If all the date-time objects being compared are in the same chronology, then the
       
   431      * additional chronology stage is not required.
       
   432      * <p>
       
   433      * This default implementation performs the comparison defined above.
       
   434      *
       
   435      * @param other  the other date-time to compare to, not null
       
   436      * @return the comparator value, negative if less, positive if greater
       
   437      */
       
   438     @Override
       
   439     public default int compareTo(ChronoZonedDateTime<?> other) {
       
   440         int cmp = Long.compare(toEpochSecond(), other.toEpochSecond());
       
   441         if (cmp == 0) {
       
   442             cmp = getTime().getNano() - other.getTime().getNano();
       
   443             if (cmp == 0) {
       
   444                 cmp = getDateTime().compareTo(other.getDateTime());
       
   445                 if (cmp == 0) {
       
   446                     cmp = getZone().getId().compareTo(other.getZone().getId());
       
   447                     if (cmp == 0) {
       
   448                         cmp = getDate().getChrono().compareTo(other.getDate().getChrono());
       
   449                     }
       
   450                 }
       
   451             }
       
   452         }
       
   453         return cmp;
       
   454     }
       
   455 
       
   456     /**
       
   457      * Checks if the instant of this date-time is before that of the specified date-time.
       
   458      * <p>
       
   459      * This method differs from the comparison in {@link #compareTo} in that it
       
   460      * only compares the instant of the date-time. This is equivalent to using
       
   461      * {@code dateTime1.toInstant().isBefore(dateTime2.toInstant());}.
       
   462      * <p>
       
   463      * This default implementation performs the comparison based on the epoch-second
       
   464      * and nano-of-second.
       
   465      *
       
   466      * @param other  the other date-time to compare to, not null
       
   467      * @return true if this point is before the specified date-time
       
   468      */
       
   469     public default boolean isBefore(ChronoZonedDateTime<?> other) {
       
   470         long thisEpochSec = toEpochSecond();
       
   471         long otherEpochSec = other.toEpochSecond();
       
   472         return thisEpochSec < otherEpochSec ||
       
   473             (thisEpochSec == otherEpochSec && getTime().getNano() < other.getTime().getNano());
       
   474     }
       
   475 
       
   476     /**
       
   477      * Checks if the instant of this date-time is after that of the specified date-time.
       
   478      * <p>
       
   479      * This method differs from the comparison in {@link #compareTo} in that it
       
   480      * only compares the instant of the date-time. This is equivalent to using
       
   481      * {@code dateTime1.toInstant().isAfter(dateTime2.toInstant());}.
       
   482      * <p>
       
   483      * This default implementation performs the comparison based on the epoch-second
       
   484      * and nano-of-second.
       
   485      *
       
   486      * @param other  the other date-time to compare to, not null
       
   487      * @return true if this is after the specified date-time
       
   488      */
       
   489     public default boolean isAfter(ChronoZonedDateTime<?> other) {
       
   490         long thisEpochSec = toEpochSecond();
       
   491         long otherEpochSec = other.toEpochSecond();
       
   492         return thisEpochSec > otherEpochSec ||
       
   493             (thisEpochSec == otherEpochSec && getTime().getNano() > other.getTime().getNano());
       
   494     }
       
   495 
       
   496     /**
       
   497      * Checks if the instant of this date-time is equal to that of the specified date-time.
       
   498      * <p>
       
   499      * This method differs from the comparison in {@link #compareTo} and {@link #equals}
       
   500      * in that it only compares the instant of the date-time. This is equivalent to using
       
   501      * {@code dateTime1.toInstant().equals(dateTime2.toInstant());}.
       
   502      * <p>
       
   503      * This default implementation performs the comparison based on the epoch-second
       
   504      * and nano-of-second.
       
   505      *
       
   506      * @param other  the other date-time to compare to, not null
       
   507      * @return true if the instant equals the instant of the specified date-time
       
   508      */
       
   509     public default boolean isEqual(ChronoZonedDateTime<?> other) {
       
   510         return toEpochSecond() == other.toEpochSecond() &&
       
   511                 getTime().getNano() == other.getTime().getNano();
       
   512     }
       
   513 
       
   514     //-----------------------------------------------------------------------
       
   515     /**
       
   516      * Checks if this date-time is equal to another date-time.
       
   517      * <p>
       
   518      * The comparison is based on the offset date-time and the zone.
       
   519      * To compare for the same instant on the time-line, use {@link #compareTo}.
       
   520      * Only objects of type {@code ChronoZonedDateTime} are compared, other types return false.
       
   521      *
       
   522      * @param obj  the object to check, null returns false
       
   523      * @return true if this is equal to the other date-time
       
   524      */
       
   525     @Override
       
   526     boolean equals(Object obj);
       
   527 
       
   528     /**
       
   529      * A hash code for this date-time.
       
   530      *
       
   531      * @return a suitable hash code
       
   532      */
       
   533     @Override
       
   534     int hashCode();
       
   535 
       
   536     //-----------------------------------------------------------------------
       
   537     /**
       
   538      * Outputs this date-time as a {@code String}.
       
   539      * <p>
       
   540      * The output will include the full zoned date-time and the chronology ID.
       
   541      *
       
   542      * @return a string representation of this date-time, not null
       
   543      */
       
   544     @Override
       
   545     String toString();
       
   546 
       
   547     /**
       
   548      * Outputs this date-time as a {@code String} using the formatter.
       
   549      * <p>
       
   550      * The default implementation must behave as follows:
       
   551      * <pre>
       
   552      *  return formatter.print(this);
       
   553      * </pre>
       
   554      *
       
   555      * @param formatter  the formatter to use, not null
       
   556      * @return the formatted date-time string, not null
       
   557      * @throws DateTimeException if an error occurs during printing
       
   558      */
       
   559     public default String toString(DateTimeFormatter formatter) {
       
   560         Objects.requireNonNull(formatter, "formatter");
       
   561         return formatter.print(this);
       
   562     }
       
   563 
       
   564 }