src/java.base/share/classes/java/time/chrono/AbstractChronology.java
author chegar
Thu, 17 Oct 2019 20:54:25 +0100
branchdatagramsocketimpl-branch
changeset 58679 9c3209ff7550
parent 58678 9cf78a70fa4f
parent 58362 628c12967b02
permissions -rw-r--r--
datagramsocketimpl-branch: merge with default
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     1
/*
57956
e0b8b019d2f5 8229997: Apply java.io.Serial annotations in java.base
darcy
parents: 52078
diff changeset
     2
 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     4
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    10
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    15
 * accompanied this code).
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    16
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    20
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    23
 * questions.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    24
 */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    25
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    26
/*
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    27
 * This file is available under and governed by the GNU General Public
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    28
 * License version 2 only, as published by the Free Software Foundation.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    29
 * However, the following notice accompanied the original version of this
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    30
 * file:
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    31
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    32
 * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    33
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    34
 * All rights reserved.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    35
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    36
 * Redistribution and use in source and binary forms, with or without
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    37
 * modification, are permitted provided that the following conditions are met:
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    38
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    39
 *  * Redistributions of source code must retain the above copyright notice,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    40
 *    this list of conditions and the following disclaimer.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    41
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    42
 *  * Redistributions in binary form must reproduce the above copyright notice,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    43
 *    this list of conditions and the following disclaimer in the documentation
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    44
 *    and/or other materials provided with the distribution.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    45
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    46
 *  * Neither the name of JSR-310 nor the names of its contributors
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    47
 *    may be used to endorse or promote products derived from this software
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    48
 *    without specific prior written permission.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    49
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    50
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    51
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    52
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    53
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    54
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    55
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    56
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    57
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    58
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    59
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    60
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    61
 */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    62
package java.time.chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    63
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    64
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    65
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    66
import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    67
import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    68
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    69
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    70
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    71
import static java.time.temporal.ChronoField.EPOCH_DAY;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    72
import static java.time.temporal.ChronoField.ERA;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    73
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    74
import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    75
import static java.time.temporal.ChronoField.YEAR;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    76
import static java.time.temporal.ChronoField.YEAR_OF_ERA;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    77
import static java.time.temporal.ChronoUnit.DAYS;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    78
import static java.time.temporal.ChronoUnit.MONTHS;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    79
import static java.time.temporal.ChronoUnit.WEEKS;
20795
8ec9e5b79828 8025722: TemporalAdjusters and TemporalQueries
rriggs
parents: 20794
diff changeset
    80
import static java.time.temporal.TemporalAdjusters.nextOrSame;
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    81
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    82
import java.io.DataInput;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    83
import java.io.DataOutput;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    84
import java.io.IOException;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    85
import java.io.InvalidObjectException;
22081
86eb26ff8f2b 8030002: Enhance deserialization using readObject
rriggs
parents: 20795
diff changeset
    86
import java.io.ObjectInputStream;
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    87
import java.io.ObjectStreamException;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    88
import java.io.Serializable;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    89
import java.time.DateTimeException;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    90
import java.time.DayOfWeek;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    91
import java.time.format.ResolverStyle;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    92
import java.time.temporal.ChronoField;
20795
8ec9e5b79828 8025722: TemporalAdjusters and TemporalQueries
rriggs
parents: 20794
diff changeset
    93
import java.time.temporal.TemporalAdjusters;
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    94
import java.time.temporal.TemporalField;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    95
import java.time.temporal.ValueRange;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    96
import java.util.Comparator;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    97
import java.util.HashSet;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    98
import java.util.List;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
    99
import java.util.Locale;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   100
import java.util.Map;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   101
import java.util.Objects;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   102
import java.util.ServiceLoader;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   103
import java.util.Set;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   104
import java.util.concurrent.ConcurrentHashMap;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   105
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   106
import sun.util.logging.PlatformLogger;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   107
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   108
/**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   109
 * An abstract implementation of a calendar system, used to organize and identify dates.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   110
 * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   111
 * The main date and time API is built on the ISO calendar system.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   112
 * The chronology operates behind the scenes to represent the general concept of a calendar system.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   113
 * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   114
 * See {@link Chronology} for more details.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   115
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   116
 * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   117
 * This class is separated from the {@code Chronology} interface so that the static methods
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   118
 * are not inherited. While {@code Chronology} can be implemented directly, it is strongly
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   119
 * recommended to extend this abstract class instead.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   120
 * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   121
 * This class must be implemented with care to ensure other classes operate correctly.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   122
 * All implementations that can be instantiated must be final, immutable and thread-safe.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   123
 * Subclasses should be Serializable wherever possible.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   124
 *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   125
 * @since 1.8
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   126
 */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   127
public abstract class AbstractChronology implements Chronology {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   128
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   129
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   130
     * Map of available calendars by ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   131
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   132
    private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_ID = new ConcurrentHashMap<>();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   133
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   134
     * Map of available calendars by calendar type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   135
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   136
    private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_TYPE = new ConcurrentHashMap<>();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   137
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   138
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   139
     * Register a Chronology by its ID and type for lookup by {@link #of(String)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   140
     * Chronologies must not be registered until they are completely constructed.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   141
     * Specifically, not in the constructor of Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   142
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   143
     * @param chrono the chronology to register; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   144
     * @return the already registered Chronology if any, may be null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   145
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   146
    static Chronology registerChrono(Chronology chrono) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   147
        return registerChrono(chrono, chrono.getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   148
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   149
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   150
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   151
     * Register a Chronology by ID and type for lookup by {@link #of(String)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   152
     * Chronos must not be registered until they are completely constructed.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   153
     * Specifically, not in the constructor of Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   154
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   155
     * @param chrono the chronology to register; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   156
     * @param id the ID to register the chronology; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   157
     * @return the already registered Chronology if any, may be null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   158
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   159
    static Chronology registerChrono(Chronology chrono, String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   160
        Chronology prev = CHRONOS_BY_ID.putIfAbsent(id, chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   161
        if (prev == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   162
            String type = chrono.getCalendarType();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   163
            if (type != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   164
                CHRONOS_BY_TYPE.putIfAbsent(type, chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   165
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   166
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   167
        return prev;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   168
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   169
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   170
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   171
     * Initialization of the maps from id and type to Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   172
     * The ServiceLoader is used to find and register any implementations
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   173
     * of {@link java.time.chrono.AbstractChronology} found in the bootclass loader.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   174
     * The built-in chronologies are registered explicitly.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   175
     * Calendars configured via the Thread's context classloader are local
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   176
     * to that thread and are ignored.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   177
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   178
     * The initialization is done only once using the registration
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   179
     * of the IsoChronology as the test and the final step.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   180
     * Multiple threads may perform the initialization concurrently.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   181
     * Only the first registration of each Chronology is retained by the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   182
     * ConcurrentHashMap.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   183
     * @return true if the cache was initialized
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   184
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   185
    private static boolean initCache() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   186
        if (CHRONOS_BY_ID.get("ISO") == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   187
            // Initialization is incomplete
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   188
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   189
            // Register built-in Chronologies
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   190
            registerChrono(HijrahChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   191
            registerChrono(JapaneseChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   192
            registerChrono(MinguoChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   193
            registerChrono(ThaiBuddhistChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   194
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   195
            // Register Chronologies from the ServiceLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   196
            @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   197
            ServiceLoader<AbstractChronology> loader =  ServiceLoader.load(AbstractChronology.class, null);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   198
            for (AbstractChronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   199
                String id = chrono.getId();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   200
                if (id.equals("ISO") || registerChrono(chrono) != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   201
                    // Log the attempt to replace an existing Chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   202
                    PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   203
                    logger.warning("Ignoring duplicate Chronology, from ServiceLoader configuration "  + id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   204
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   205
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   206
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   207
            // finally, register IsoChronology to mark initialization is complete
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   208
            registerChrono(IsoChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   209
            return true;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   210
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   211
        return false;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   212
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   213
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   214
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   215
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   216
     * Obtains an instance of {@code Chronology} from a locale.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   217
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   218
     * See {@link Chronology#ofLocale(Locale)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   219
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   220
     * @param locale  the locale to use to obtain the calendar system, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   221
     * @return the calendar system associated with the locale, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   222
     * @throws java.time.DateTimeException if the locale-specified calendar cannot be found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   223
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   224
    static Chronology ofLocale(Locale locale) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   225
        Objects.requireNonNull(locale, "locale");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   226
        String type = locale.getUnicodeLocaleType("ca");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   227
        if (type == null || "iso".equals(type) || "iso8601".equals(type)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   228
            return IsoChronology.INSTANCE;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   229
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   230
        // Not pre-defined; lookup by the type
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   231
        do {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   232
            Chronology chrono = CHRONOS_BY_TYPE.get(type);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   233
            if (chrono != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   234
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   235
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   236
            // If not found, do the initialization (once) and repeat the lookup
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   237
        } while (initCache());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   238
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   239
        // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   240
        // Application provided Chronologies must not be cached
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   241
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   242
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   243
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   244
            if (type.equals(chrono.getCalendarType())) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   245
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   246
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   247
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   248
        throw new DateTimeException("Unknown calendar system: " + type);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   249
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   250
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   251
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   252
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   253
     * Obtains an instance of {@code Chronology} from a chronology ID or
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   254
     * calendar system type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   255
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   256
     * See {@link Chronology#of(String)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   257
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   258
     * @param id  the chronology ID or calendar system type, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   259
     * @return the chronology with the identifier requested, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   260
     * @throws java.time.DateTimeException if the chronology cannot be found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   261
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   262
    static Chronology of(String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   263
        Objects.requireNonNull(id, "id");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   264
        do {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   265
            Chronology chrono = of0(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   266
            if (chrono != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   267
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   268
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   269
            // If not found, do the initialization (once) and repeat the lookup
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   270
        } while (initCache());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   271
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   272
        // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   273
        // Application provided Chronologies must not be cached
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   274
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   275
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   276
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   277
            if (id.equals(chrono.getId()) || id.equals(chrono.getCalendarType())) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   278
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   279
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   280
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   281
        throw new DateTimeException("Unknown chronology: " + id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   282
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   283
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   284
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   285
     * Obtains an instance of {@code Chronology} from a chronology ID or
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   286
     * calendar system type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   287
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   288
     * @param id  the chronology ID or calendar system type, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   289
     * @return the chronology with the identifier requested, or {@code null} if not found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   290
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   291
    private static Chronology of0(String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   292
        Chronology chrono = CHRONOS_BY_ID.get(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   293
        if (chrono == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   294
            chrono = CHRONOS_BY_TYPE.get(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   295
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   296
        return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   297
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   298
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   299
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   300
     * Returns the available chronologies.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   301
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   302
     * Each returned {@code Chronology} is available for use in the system.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   303
     * The set of chronologies includes the system chronologies and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   304
     * any chronologies provided by the application via ServiceLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   305
     * configuration.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   306
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   307
     * @return the independent, modifiable set of the available chronology IDs, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   308
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   309
    static Set<Chronology> getAvailableChronologies() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   310
        initCache();       // force initialization
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   311
        HashSet<Chronology> chronos = new HashSet<>(CHRONOS_BY_ID.values());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   312
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   313
        /// Add in Chronologies from the ServiceLoader configuration
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   314
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   315
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   316
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   317
            chronos.add(chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   318
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   319
        return chronos;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   320
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   321
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   322
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   323
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   324
     * Creates an instance.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   325
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   326
    protected AbstractChronology() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   327
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   328
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   329
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   330
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   331
     * Resolves parsed {@code ChronoField} values into a date during parsing.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   332
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   333
     * Most {@code TemporalField} implementations are resolved using the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   334
     * resolve method on the field. By contrast, the {@code ChronoField} class
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   335
     * defines fields that only have meaning relative to the chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   336
     * As such, {@code ChronoField} date fields are resolved here in the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   337
     * context of a specific chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   338
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   339
     * {@code ChronoField} instances are resolved by this method, which may
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   340
     * be overridden in subclasses.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   341
     * <ul>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   342
     * <li>{@code EPOCH_DAY} - If present, this is converted to a date and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   343
     *  all other date fields are then cross-checked against the date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   344
     * <li>{@code PROLEPTIC_MONTH} - If present, then it is split into the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   345
     *  {@code YEAR} and {@code MONTH_OF_YEAR}. If the mode is strict or smart
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   346
     *  then the field is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   347
     * <li>{@code YEAR_OF_ERA} and {@code ERA} - If both are present, then they
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   348
     *  are combined to form a {@code YEAR}. In lenient mode, the {@code YEAR_OF_ERA}
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   349
     *  range is not validated, in smart and strict mode it is. The {@code ERA} is
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   350
     *  validated for range in all three modes. If only the {@code YEAR_OF_ERA} is
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   351
     *  present, and the mode is smart or lenient, then the last available era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   352
     *  is assumed. In strict mode, no era is assumed and the {@code YEAR_OF_ERA} is
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   353
     *  left untouched. If only the {@code ERA} is present, then it is left untouched.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   354
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   355
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   356
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   357
     *  If the mode is smart or strict, then the month and day are validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   358
     *  If the mode is lenient, then the date is combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   359
     *  creating a date on the first day of the first month in the requested year,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   360
     *  then adding the difference in months, then the difference in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   361
     *  If the mode is smart, and the day-of-month is greater than the maximum for
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   362
     *  the year-month, then the day-of-month is adjusted to the last day-of-month.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   363
     *  If the mode is strict, then the three fields must form a valid date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   364
     * <li>{@code YEAR} and {@code DAY_OF_YEAR} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   365
     *  If both are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   366
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   367
     *  If the mode is lenient, then the date is combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   368
     *  creating a date on the first day of the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   369
     *  the difference in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   370
     *  If the mode is smart or strict, then the two fields must form a valid date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   371
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   372
     *  {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   373
     *  If all four are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   374
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   375
     *  If the mode is lenient, then the date is combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   376
     *  creating a date on the first day of the first month in the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   377
     *  the difference in months, then the difference in weeks, then in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   378
     *  If the mode is smart or strict, then the all four fields are validated to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   379
     *  their outer ranges. The date is then combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   380
     *  creating a date on the first day of the requested year and month, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   381
     *  the amount in weeks and days to reach their values. If the mode is strict,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   382
     *  the date is additionally validated to check that the day and week adjustment
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   383
     *  did not change the month.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   384
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   385
     *  {@code DAY_OF_WEEK} - If all four are present, then they are combined to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   386
     *  form a date. The approach is the same as described above for
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   387
     *  years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   388
     *  The day-of-week is adjusted as the next or same matching day-of-week once
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   389
     *  the years, months and weeks have been handled.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   390
     * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   391
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   392
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   393
     *  If the mode is lenient, then the date is combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   394
     *  creating a date on the first day of the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   395
     *  the difference in weeks, then in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   396
     *  If the mode is smart or strict, then the all three fields are validated to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   397
     *  their outer ranges. The date is then combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   398
     *  creating a date on the first day of the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   399
     *  the amount in weeks and days to reach their values. If the mode is strict,
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   400
     *  the date is additionally validated to check that the day and week adjustment
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   401
     *  did not change the year.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   402
     * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   403
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   404
     *  The approach is the same as described above for years and weeks in
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   405
     *  {@code ALIGNED_DAY_OF_WEEK_IN_YEAR}. The day-of-week is adjusted as the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   406
     *  next or same matching day-of-week once the years and weeks have been handled.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   407
     * </ul>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   408
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   409
     * The default implementation is suitable for most calendar systems.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   410
     * If {@link java.time.temporal.ChronoField#YEAR_OF_ERA} is found without an {@link java.time.temporal.ChronoField#ERA}
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   411
     * then the last era in {@link #eras()} is used.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   412
     * The implementation assumes a 7 day week, that the first day-of-month
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   413
     * has the value 1, that first day-of-year has the value 1, and that the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   414
     * first of the month and year always exists.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   415
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   416
     * @param fieldValues  the map of fields to values, which can be updated, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   417
     * @param resolverStyle  the requested type of resolve, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   418
     * @return the resolved date, null if insufficient information to create a date
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   419
     * @throws java.time.DateTimeException if the date cannot be resolved, typically
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   420
     *  because of a conflict in the input data
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   421
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   422
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   423
    public ChronoLocalDate resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   424
        // check epoch-day before inventing era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   425
        if (fieldValues.containsKey(EPOCH_DAY)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   426
            return dateEpochDay(fieldValues.remove(EPOCH_DAY));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   427
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   428
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   429
        // fix proleptic month before inventing era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   430
        resolveProlepticMonth(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   431
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   432
        // invent era if necessary to resolve year-of-era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   433
        ChronoLocalDate resolved = resolveYearOfEra(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   434
        if (resolved != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   435
            return resolved;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   436
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   437
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   438
        // build date
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   439
        if (fieldValues.containsKey(YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   440
            if (fieldValues.containsKey(MONTH_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   441
                if (fieldValues.containsKey(DAY_OF_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   442
                    return resolveYMD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   443
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   444
                if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   445
                    if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   446
                        return resolveYMAA(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   447
                    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   448
                    if (fieldValues.containsKey(DAY_OF_WEEK)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   449
                        return resolveYMAD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   450
                    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   451
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   452
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   453
            if (fieldValues.containsKey(DAY_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   454
                return resolveYD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   455
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   456
            if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   457
                if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   458
                    return resolveYAA(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   459
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   460
                if (fieldValues.containsKey(DAY_OF_WEEK)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   461
                    return resolveYAD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   462
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   463
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   464
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   465
        return null;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   466
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   467
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   468
    void resolveProlepticMonth(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   469
        Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   470
        if (pMonth != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   471
            if (resolverStyle != ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   472
                PROLEPTIC_MONTH.checkValidValue(pMonth);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   473
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   474
            // first day-of-month is likely to be safest for setting proleptic-month
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   475
            // cannot add to year zero, as not all chronologies have a year zero
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   476
            ChronoLocalDate chronoDate = dateNow()
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   477
                    .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   478
            addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   479
            addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   480
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   481
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   482
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   483
    ChronoLocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   484
        Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   485
        if (yoeLong != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   486
            Long eraLong = fieldValues.remove(ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   487
            int yoe;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   488
            if (resolverStyle != ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   489
                yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   490
            } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   491
                yoe = Math.toIntExact(yoeLong);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   492
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   493
            if (eraLong != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   494
                Era eraObj = eraOf(range(ERA).checkValidIntValue(eraLong, ERA));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   495
                addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   496
            } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   497
                if (fieldValues.containsKey(YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   498
                    int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   499
                    ChronoLocalDate chronoDate = dateYearDay(year, 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   500
                    addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   501
                } else if (resolverStyle == ResolverStyle.STRICT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   502
                    // do not invent era if strict
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   503
                    // reinstate the field removed earlier, no cross-check issues
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   504
                    fieldValues.put(YEAR_OF_ERA, yoeLong);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   505
                } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   506
                    List<Era> eras = eras();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   507
                    if (eras.isEmpty()) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   508
                        addFieldValue(fieldValues, YEAR, yoe);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   509
                    } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   510
                        Era eraObj = eras.get(eras.size() - 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   511
                        addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   512
                    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   513
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   514
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   515
        } else if (fieldValues.containsKey(ERA)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   516
            range(ERA).checkValidValue(fieldValues.get(ERA), ERA);  // always validated
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   517
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   518
        return null;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   519
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   520
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   521
    ChronoLocalDate resolveYMD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   522
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   523
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   524
            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   525
            long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   526
            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   527
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   528
        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   529
        ValueRange domRange = range(DAY_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   530
        int dom = domRange.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   531
        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   532
            try {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   533
                return date(y, moy, dom);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   534
            } catch (DateTimeException ex) {
20795
8ec9e5b79828 8025722: TemporalAdjusters and TemporalQueries
rriggs
parents: 20794
diff changeset
   535
                return date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   536
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   537
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   538
        return date(y, moy, dom);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   539
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   540
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   541
    ChronoLocalDate resolveYD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   542
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   543
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   544
            long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   545
            return dateYearDay(y, 1).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   546
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   547
        int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   548
        return dateYearDay(y, doy);  // smart is same as strict
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   549
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   550
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   551
    ChronoLocalDate resolveYMAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   552
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   553
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   554
            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   555
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   556
            long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   557
            return date(y, 1, 1).plus(months, MONTHS).plus(weeks, WEEKS).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   558
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   559
        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   560
        int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   561
        int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   562
        ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   563
        if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   564
            throw new DateTimeException("Strict mode rejected resolved date as it is in a different month");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   565
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   566
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   567
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   568
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   569
    ChronoLocalDate resolveYMAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   570
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   571
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   572
            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   573
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   574
            long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   575
            return resolveAligned(date(y, 1, 1), months, weeks, dow);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   576
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   577
        int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   578
        int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   579
        int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   580
        ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow)));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   581
        if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   582
            throw new DateTimeException("Strict mode rejected resolved date as it is in a different month");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   583
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   584
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   585
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   586
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   587
    ChronoLocalDate resolveYAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   588
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   589
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   590
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   591
            long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   592
            return dateYearDay(y, 1).plus(weeks, WEEKS).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   593
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   594
        int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   595
        int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   596
        ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   597
        if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   598
            throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   599
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   600
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   601
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   602
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   603
    ChronoLocalDate resolveYAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   604
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   605
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   606
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   607
            long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   608
            return resolveAligned(dateYearDay(y, 1), 0, weeks, dow);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   609
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   610
        int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   611
        int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   612
        ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow)));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   613
        if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   614
            throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   615
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   616
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   617
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   618
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   619
    ChronoLocalDate resolveAligned(ChronoLocalDate base, long months, long weeks, long dow) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   620
        ChronoLocalDate date = base.plus(months, MONTHS).plus(weeks, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   621
        if (dow > 7) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   622
            date = date.plus((dow - 1) / 7, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   623
            dow = ((dow - 1) % 7) + 1;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   624
        } else if (dow < 1) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   625
            date = date.plus(Math.subtractExact(dow,  7) / 7, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   626
            dow = ((dow + 6) % 7) + 1;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   627
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   628
        return date.with(nextOrSame(DayOfWeek.of((int) dow)));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   629
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   630
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   631
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   632
     * Adds a field-value pair to the map, checking for conflicts.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   633
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   634
     * If the field is not already present, then the field-value pair is added to the map.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   635
     * If the field is already present and it has the same value as that specified, no action occurs.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   636
     * If the field is already present and it has a different value to that specified, then
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   637
     * an exception is thrown.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   638
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   639
     * @param field  the field to add, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   640
     * @param value  the value to add, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   641
     * @throws java.time.DateTimeException if the field is already present with a different value
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   642
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   643
    void addFieldValue(Map<TemporalField, Long> fieldValues, ChronoField field, long value) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   644
        Long old = fieldValues.get(field);  // check first for better error message
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   645
        if (old != null && old.longValue() != value) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   646
            throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   647
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   648
        fieldValues.put(field, value);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   649
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   650
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   651
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   652
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   653
     * Compares this chronology to another chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   654
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   655
     * The comparison order first by the chronology ID string, then by any
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   656
     * additional information specific to the subclass.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   657
     * It is "consistent with equals", as defined by {@link Comparable}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   658
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   659
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   660
     * This implementation compares the chronology ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   661
     * Subclasses must compare any additional state that they store.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   662
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   663
     * @param other  the other chronology to compare to, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   664
     * @return the comparator value, negative if less, positive if greater
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   665
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   666
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   667
    public int compareTo(Chronology other) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   668
        return getId().compareTo(other.getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   669
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   670
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   671
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   672
     * Checks if this chronology is equal to another chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   673
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   674
     * The comparison is based on the entire state of the object.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   675
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   676
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   677
     * This implementation checks the type and calls
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   678
     * {@link #compareTo(java.time.chrono.Chronology)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   679
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   680
     * @param obj  the object to check, null returns false
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   681
     * @return true if this is equal to the other chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   682
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   683
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   684
    public boolean equals(Object obj) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   685
        if (this == obj) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   686
           return true;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   687
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   688
        if (obj instanceof AbstractChronology) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   689
            return compareTo((AbstractChronology) obj) == 0;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   690
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   691
        return false;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   692
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   693
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   694
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   695
     * A hash code for this chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   696
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   697
     * The hash code should be based on the entire state of the object.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   698
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   699
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   700
     * This implementation is based on the chronology ID and class.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   701
     * Subclasses should add any additional state that they store.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   702
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   703
     * @return a suitable hash code
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   704
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   705
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   706
    public int hashCode() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   707
        return getClass().hashCode() ^ getId().hashCode();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   708
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   709
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   710
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   711
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   712
     * Outputs this chronology as a {@code String}, using the chronology ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   713
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   714
     * @return a string representation of this chronology, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   715
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   716
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   717
    public String toString() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   718
        return getId();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   719
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   720
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   721
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   722
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   723
     * Writes the Chronology using a
52078
4a63197816ce 8211952: Broken links in java.time API
jjg
parents: 47216
diff changeset
   724
     * <a href="{@docRoot}/serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   725
     * <pre>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   726
     *  out.writeByte(1);  // identifies this as a Chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   727
     *  out.writeUTF(getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   728
     * </pre>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   729
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   730
     * @return the instance of {@code Ser}, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   731
     */
57956
e0b8b019d2f5 8229997: Apply java.io.Serial annotations in java.base
darcy
parents: 52078
diff changeset
   732
    @java.io.Serial
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   733
    Object writeReplace() {
58362
628c12967b02 8231314: java.time serialization warning cleanup
rriggs
parents: 57956
diff changeset
   734
        return new Ser(Ser.CHRONO_TYPE, (Serializable)this);
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   735
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   736
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   737
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   738
     * Defend against malicious streams.
22081
86eb26ff8f2b 8030002: Enhance deserialization using readObject
rriggs
parents: 20795
diff changeset
   739
     *
22566
4ebe53dd7814 8032502: java.time add @param tags to readObject
rriggs
parents: 22081
diff changeset
   740
     * @param s the stream to read
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   741
     * @throws java.io.InvalidObjectException always
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   742
     */
57956
e0b8b019d2f5 8229997: Apply java.io.Serial annotations in java.base
darcy
parents: 52078
diff changeset
   743
    @java.io.Serial
22081
86eb26ff8f2b 8030002: Enhance deserialization using readObject
rriggs
parents: 20795
diff changeset
   744
    private void readObject(ObjectInputStream s) throws ObjectStreamException {
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   745
        throw new InvalidObjectException("Deserialization via serialization delegate");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   746
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   747
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   748
    void writeExternal(DataOutput out) throws IOException {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   749
        out.writeUTF(getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   750
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   751
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   752
    static Chronology readExternal(DataInput in) throws IOException {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   753
        String id = in.readUTF();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   754
        return Chronology.of(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   755
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   756
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   757
}