jdk/src/share/classes/java/time/chrono/AbstractChronology.java
author rriggs
Wed, 22 Jan 2014 17:40:58 -0500
changeset 22566 4ebe53dd7814
parent 22081 86eb26ff8f2b
permissions -rw-r--r--
8032502: java.time add @param tags to readObject Summary: Add @param tags Reviewed-by: lancea, darcy
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     1
/*
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
     2
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
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
     * ChronoLocalDate order constant.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   131
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   132
    static final Comparator<ChronoLocalDate> DATE_ORDER =
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   133
        (Comparator<ChronoLocalDate> & Serializable) (date1, date2) -> {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   134
            return Long.compare(date1.toEpochDay(), date2.toEpochDay());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   135
        };
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   136
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   137
     * ChronoLocalDateTime order constant.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   138
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   139
    static final Comparator<ChronoLocalDateTime<? extends ChronoLocalDate>> DATE_TIME_ORDER =
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   140
        (Comparator<ChronoLocalDateTime<? extends ChronoLocalDate>> & Serializable) (dateTime1, dateTime2) -> {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   141
            int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   142
            if (cmp == 0) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   143
                cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   144
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   145
            return cmp;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   146
        };
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   147
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   148
     * ChronoZonedDateTime order constant.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   149
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   150
    static final Comparator<ChronoZonedDateTime<?>> INSTANT_ORDER =
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   151
            (Comparator<ChronoZonedDateTime<?>> & Serializable) (dateTime1, dateTime2) -> {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   152
                int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   153
                if (cmp == 0) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   154
                    cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   155
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   156
                return cmp;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   157
            };
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   158
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   159
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   160
     * Map of available calendars by ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   161
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   162
    private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_ID = new ConcurrentHashMap<>();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   163
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   164
     * Map of available calendars by calendar type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   165
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   166
    private static final ConcurrentHashMap<String, Chronology> CHRONOS_BY_TYPE = new ConcurrentHashMap<>();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   167
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   168
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   169
     * 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
   170
     * Chronologies must not be registered until they are completely constructed.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   171
     * Specifically, not in the constructor of Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   172
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   173
     * @param chrono the chronology to register; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   174
     * @return the already registered Chronology if any, may be null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   175
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   176
    static Chronology registerChrono(Chronology chrono) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   177
        return registerChrono(chrono, chrono.getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   178
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   179
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   180
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   181
     * Register a Chronology by ID and type for lookup by {@link #of(String)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   182
     * Chronos must not be registered until they are completely constructed.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   183
     * Specifically, not in the constructor of Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   184
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   185
     * @param chrono the chronology to register; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   186
     * @param id the ID to register the chronology; not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   187
     * @return the already registered Chronology if any, may be null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   188
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   189
    static Chronology registerChrono(Chronology chrono, String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   190
        Chronology prev = CHRONOS_BY_ID.putIfAbsent(id, chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   191
        if (prev == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   192
            String type = chrono.getCalendarType();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   193
            if (type != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   194
                CHRONOS_BY_TYPE.putIfAbsent(type, chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   195
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   196
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   197
        return prev;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   198
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   199
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   200
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   201
     * Initialization of the maps from id and type to Chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   202
     * The ServiceLoader is used to find and register any implementations
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   203
     * of {@link java.time.chrono.AbstractChronology} found in the bootclass loader.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   204
     * The built-in chronologies are registered explicitly.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   205
     * Calendars configured via the Thread's context classloader are local
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   206
     * to that thread and are ignored.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   207
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   208
     * The initialization is done only once using the registration
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   209
     * of the IsoChronology as the test and the final step.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   210
     * Multiple threads may perform the initialization concurrently.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   211
     * Only the first registration of each Chronology is retained by the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   212
     * ConcurrentHashMap.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   213
     * @return true if the cache was initialized
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   214
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   215
    private static boolean initCache() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   216
        if (CHRONOS_BY_ID.get("ISO") == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   217
            // Initialization is incomplete
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   218
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   219
            // Register built-in Chronologies
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   220
            registerChrono(HijrahChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   221
            registerChrono(JapaneseChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   222
            registerChrono(MinguoChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   223
            registerChrono(ThaiBuddhistChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   224
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   225
            // Register Chronologies from the ServiceLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   226
            @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   227
            ServiceLoader<AbstractChronology> loader =  ServiceLoader.load(AbstractChronology.class, null);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   228
            for (AbstractChronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   229
                String id = chrono.getId();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   230
                if (id.equals("ISO") || registerChrono(chrono) != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   231
                    // Log the attempt to replace an existing Chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   232
                    PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   233
                    logger.warning("Ignoring duplicate Chronology, from ServiceLoader configuration "  + id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   234
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   235
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   236
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   237
            // finally, register IsoChronology to mark initialization is complete
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   238
            registerChrono(IsoChronology.INSTANCE);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   239
            return true;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   240
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   241
        return false;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   242
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   243
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   244
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   245
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   246
     * Obtains an instance of {@code Chronology} from a locale.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   247
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   248
     * See {@link Chronology#ofLocale(Locale)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   249
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   250
     * @param locale  the locale to use to obtain the calendar system, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   251
     * @return the calendar system associated with the locale, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   252
     * @throws java.time.DateTimeException if the locale-specified calendar cannot be found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   253
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   254
    static Chronology ofLocale(Locale locale) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   255
        Objects.requireNonNull(locale, "locale");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   256
        String type = locale.getUnicodeLocaleType("ca");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   257
        if (type == null || "iso".equals(type) || "iso8601".equals(type)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   258
            return IsoChronology.INSTANCE;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   259
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   260
        // Not pre-defined; lookup by the type
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   261
        do {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   262
            Chronology chrono = CHRONOS_BY_TYPE.get(type);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   263
            if (chrono != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   264
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   265
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   266
            // If not found, do the initialization (once) and repeat the lookup
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   267
        } while (initCache());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   268
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   269
        // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   270
        // Application provided Chronologies must not be cached
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   271
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   272
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   273
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   274
            if (type.equals(chrono.getCalendarType())) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   275
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   276
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   277
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   278
        throw new DateTimeException("Unknown calendar system: " + type);
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
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   282
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   283
     * Obtains an instance of {@code Chronology} from a chronology ID or
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   284
     * calendar system type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   285
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   286
     * See {@link Chronology#of(String)}.
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, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   290
     * @throws java.time.DateTimeException if the chronology cannot be found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   291
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   292
    static Chronology of(String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   293
        Objects.requireNonNull(id, "id");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   294
        do {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   295
            Chronology chrono = of0(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   296
            if (chrono != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   297
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   298
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   299
            // If not found, do the initialization (once) and repeat the lookup
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   300
        } while (initCache());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   301
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   302
        // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   303
        // Application provided Chronologies must not be cached
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   304
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   305
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   306
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   307
            if (id.equals(chrono.getId()) || id.equals(chrono.getCalendarType())) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   308
                return chrono;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   309
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   310
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   311
        throw new DateTimeException("Unknown chronology: " + id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   312
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   313
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   314
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   315
     * Obtains an instance of {@code Chronology} from a chronology ID or
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   316
     * calendar system type.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   317
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   318
     * @param id  the chronology ID or calendar system type, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   319
     * @return the chronology with the identifier requested, or {@code null} if not found
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   320
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   321
    private static Chronology of0(String id) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   322
        Chronology chrono = CHRONOS_BY_ID.get(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   323
        if (chrono == null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   324
            chrono = CHRONOS_BY_TYPE.get(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   325
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   326
        return chrono;
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
     * Returns the available chronologies.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   331
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   332
     * Each returned {@code Chronology} is available for use in the system.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   333
     * The set of chronologies includes the system chronologies and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   334
     * any chronologies provided by the application via ServiceLoader
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   335
     * configuration.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   336
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   337
     * @return the independent, modifiable set of the available chronology IDs, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   338
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   339
    static Set<Chronology> getAvailableChronologies() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   340
        initCache();       // force initialization
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   341
        HashSet<Chronology> chronos = new HashSet<>(CHRONOS_BY_ID.values());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   342
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   343
        /// Add in Chronologies from the ServiceLoader configuration
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   344
        @SuppressWarnings("rawtypes")
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   345
        ServiceLoader<Chronology> loader = ServiceLoader.load(Chronology.class);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   346
        for (Chronology chrono : loader) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   347
            chronos.add(chrono);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   348
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   349
        return chronos;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   350
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   351
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   352
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   353
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   354
     * Creates an instance.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   355
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   356
    protected AbstractChronology() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   357
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   358
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   359
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   360
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   361
     * Resolves parsed {@code ChronoField} values into a date during parsing.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   362
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   363
     * Most {@code TemporalField} implementations are resolved using the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   364
     * resolve method on the field. By contrast, the {@code ChronoField} class
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   365
     * defines fields that only have meaning relative to the chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   366
     * As such, {@code ChronoField} date fields are resolved here in the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   367
     * context of a specific chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   368
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   369
     * {@code ChronoField} instances are resolved by this method, which may
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   370
     * be overridden in subclasses.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   371
     * <ul>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   372
     * <li>{@code EPOCH_DAY} - If present, this is converted to a date and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   373
     *  all other date fields are then cross-checked against the date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   374
     * <li>{@code PROLEPTIC_MONTH} - If present, then it is split into the
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   375
     *  {@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
   376
     *  then the field is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   377
     * <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
   378
     *  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
   379
     *  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
   380
     *  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
   381
     *  present, and the mode is smart or lenient, then the last available era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   382
     *  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
   383
     *  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
   384
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   385
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   386
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   387
     *  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
   388
     *  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
   389
     *  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
   390
     *  then adding the difference in months, then the difference in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   391
     *  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
   392
     *  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
   393
     *  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
   394
     * <li>{@code YEAR} and {@code DAY_OF_YEAR} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   395
     *  If both are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   396
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   397
     *  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
   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 difference in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   400
     *  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
   401
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   402
     *  {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   403
     *  If all four are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   404
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   405
     *  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
   406
     *  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
   407
     *  the difference in months, then the difference in weeks, then in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   408
     *  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
   409
     *  their outer ranges. The date is then combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   410
     *  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
   411
     *  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
   412
     *  the date is additionally validated to check that the day and week adjustment
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   413
     *  did not change the month.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   414
     * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   415
     *  {@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
   416
     *  form a date. The approach is the same as described above for
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   417
     *  years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   418
     *  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
   419
     *  the years, months and weeks have been handled.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   420
     * <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
   421
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   422
     *  In all three modes, the {@code YEAR} is validated.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   423
     *  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
   424
     *  creating a date on the first day of the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   425
     *  the difference in weeks, then in days.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   426
     *  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
   427
     *  their outer ranges. The date is then combined in a manner equivalent to
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   428
     *  creating a date on the first day of the requested year, then adding
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   429
     *  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
   430
     *  the date is additionally validated to check that the day and week adjustment
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   431
     *  did not change the year.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   432
     * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} -
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   433
     *  If all three are present, then they are combined to form a date.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   434
     *  The approach is the same as described above for years and weeks in
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   435
     *  {@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
   436
     *  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
   437
     * </ul>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   438
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   439
     * The default implementation is suitable for most calendar systems.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   440
     * 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
   441
     * then the last era in {@link #eras()} is used.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   442
     * The implementation assumes a 7 day week, that the first day-of-month
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   443
     * 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
   444
     * first of the month and year always exists.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   445
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   446
     * @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
   447
     * @param resolverStyle  the requested type of resolve, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   448
     * @return the resolved date, null if insufficient information to create a date
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   449
     * @throws java.time.DateTimeException if the date cannot be resolved, typically
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   450
     *  because of a conflict in the input data
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   451
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   452
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   453
    public ChronoLocalDate resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   454
        // check epoch-day before inventing era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   455
        if (fieldValues.containsKey(EPOCH_DAY)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   456
            return dateEpochDay(fieldValues.remove(EPOCH_DAY));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   457
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   458
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   459
        // fix proleptic month before inventing era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   460
        resolveProlepticMonth(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   461
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   462
        // invent era if necessary to resolve year-of-era
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   463
        ChronoLocalDate resolved = resolveYearOfEra(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   464
        if (resolved != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   465
            return resolved;
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
        // build date
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   469
        if (fieldValues.containsKey(YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   470
            if (fieldValues.containsKey(MONTH_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   471
                if (fieldValues.containsKey(DAY_OF_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   472
                    return resolveYMD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   473
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   474
                if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   475
                    if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   476
                        return resolveYMAA(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   477
                    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   478
                    if (fieldValues.containsKey(DAY_OF_WEEK)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   479
                        return resolveYMAD(fieldValues, resolverStyle);
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
            if (fieldValues.containsKey(DAY_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   484
                return resolveYD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   485
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   486
            if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   487
                if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   488
                    return resolveYAA(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   489
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   490
                if (fieldValues.containsKey(DAY_OF_WEEK)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   491
                    return resolveYAD(fieldValues, resolverStyle);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   492
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   493
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   494
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   495
        return null;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   496
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   497
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   498
    void resolveProlepticMonth(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   499
        Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   500
        if (pMonth != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   501
            if (resolverStyle != ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   502
                PROLEPTIC_MONTH.checkValidValue(pMonth);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   503
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   504
            // first day-of-month is likely to be safest for setting proleptic-month
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   505
            // cannot add to year zero, as not all chronologies have a year zero
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   506
            ChronoLocalDate chronoDate = dateNow()
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   507
                    .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   508
            addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   509
            addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   510
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   511
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   512
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   513
    ChronoLocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   514
        Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   515
        if (yoeLong != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   516
            Long eraLong = fieldValues.remove(ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   517
            int yoe;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   518
            if (resolverStyle != ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   519
                yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   520
            } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   521
                yoe = Math.toIntExact(yoeLong);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   522
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   523
            if (eraLong != null) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   524
                Era eraObj = eraOf(range(ERA).checkValidIntValue(eraLong, ERA));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   525
                addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   526
            } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   527
                if (fieldValues.containsKey(YEAR)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   528
                    int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   529
                    ChronoLocalDate chronoDate = dateYearDay(year, 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   530
                    addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   531
                } else if (resolverStyle == ResolverStyle.STRICT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   532
                    // do not invent era if strict
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   533
                    // reinstate the field removed earlier, no cross-check issues
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   534
                    fieldValues.put(YEAR_OF_ERA, yoeLong);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   535
                } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   536
                    List<Era> eras = eras();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   537
                    if (eras.isEmpty()) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   538
                        addFieldValue(fieldValues, YEAR, yoe);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   539
                    } else {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   540
                        Era eraObj = eras.get(eras.size() - 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   541
                        addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   542
                    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   543
                }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   544
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   545
        } else if (fieldValues.containsKey(ERA)) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   546
            range(ERA).checkValidValue(fieldValues.get(ERA), ERA);  // always validated
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   547
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   548
        return null;
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 resolveYMD(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 days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   556
            return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   557
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   558
        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
   559
        ValueRange domRange = range(DAY_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   560
        int dom = domRange.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   561
        if (resolverStyle == ResolverStyle.SMART) {  // previous valid
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   562
            try {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   563
                return date(y, moy, dom);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   564
            } catch (DateTimeException ex) {
20795
8ec9e5b79828 8025722: TemporalAdjusters and TemporalQueries
rriggs
parents: 20794
diff changeset
   565
                return date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth());
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   566
            }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   567
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   568
        return date(y, moy, dom);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   569
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   570
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   571
    ChronoLocalDate resolveYD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   572
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   573
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   574
            long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   575
            return dateYearDay(y, 1).plus(days, DAYS);
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 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
   578
        return dateYearDay(y, doy);  // smart is same as strict
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   579
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   580
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   581
    ChronoLocalDate resolveYMAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   582
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   583
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   584
            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   585
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   586
            long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   587
            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
   588
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   589
        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
   590
        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
   591
        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
   592
        ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   593
        if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   594
            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
   595
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   596
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   597
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   598
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   599
    ChronoLocalDate resolveYMAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   600
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   601
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   602
            long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   603
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   604
            long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   605
            return resolveAligned(date(y, 1, 1), months, weeks, dow);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   606
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   607
        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
   608
        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
   609
        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
   610
        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
   611
        if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   612
            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
   613
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   614
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   615
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   616
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   617
    ChronoLocalDate resolveYAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   618
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   619
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   620
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   621
            long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   622
            return dateYearDay(y, 1).plus(weeks, WEEKS).plus(days, DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   623
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   624
        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
   625
        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
   626
        ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   627
        if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   628
            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
   629
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   630
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   631
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   632
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   633
    ChronoLocalDate resolveYAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   634
        int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   635
        if (resolverStyle == ResolverStyle.LENIENT) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   636
            long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   637
            long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   638
            return resolveAligned(dateYearDay(y, 1), 0, weeks, dow);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   639
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   640
        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
   641
        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
   642
        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
   643
        if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   644
            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
   645
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   646
        return date;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   647
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   648
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   649
    ChronoLocalDate resolveAligned(ChronoLocalDate base, long months, long weeks, long dow) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   650
        ChronoLocalDate date = base.plus(months, MONTHS).plus(weeks, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   651
        if (dow > 7) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   652
            date = date.plus((dow - 1) / 7, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   653
            dow = ((dow - 1) % 7) + 1;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   654
        } else if (dow < 1) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   655
            date = date.plus(Math.subtractExact(dow,  7) / 7, WEEKS);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   656
            dow = ((dow + 6) % 7) + 1;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   657
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   658
        return date.with(nextOrSame(DayOfWeek.of((int) dow)));
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   659
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   660
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   661
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   662
     * Adds a field-value pair to the map, checking for conflicts.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   663
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   664
     * 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
   665
     * 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
   666
     * 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
   667
     * an exception is thrown.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   668
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   669
     * @param field  the field to add, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   670
     * @param value  the value to add, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   671
     * @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
   672
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   673
    void addFieldValue(Map<TemporalField, Long> fieldValues, ChronoField field, long value) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   674
        Long old = fieldValues.get(field);  // check first for better error message
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   675
        if (old != null && old.longValue() != value) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   676
            throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   677
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   678
        fieldValues.put(field, value);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   679
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   680
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   681
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   682
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   683
     * Compares this chronology to another chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   684
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   685
     * The comparison order first by the chronology ID string, then by any
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   686
     * additional information specific to the subclass.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   687
     * It is "consistent with equals", as defined by {@link Comparable}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   688
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   689
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   690
     * This implementation compares the chronology ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   691
     * Subclasses must compare any additional state that they store.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   692
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   693
     * @param other  the other chronology to compare to, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   694
     * @return the comparator value, negative if less, positive if greater
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   695
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   696
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   697
    public int compareTo(Chronology other) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   698
        return getId().compareTo(other.getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   699
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   700
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   701
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   702
     * Checks if this chronology is equal to another chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   703
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   704
     * The comparison is based on the entire state of the object.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   705
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   706
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   707
     * This implementation checks the type and calls
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   708
     * {@link #compareTo(java.time.chrono.Chronology)}.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   709
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   710
     * @param obj  the object to check, null returns false
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   711
     * @return true if this is equal to the other chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   712
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   713
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   714
    public boolean equals(Object obj) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   715
        if (this == obj) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   716
           return true;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   717
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   718
        if (obj instanceof AbstractChronology) {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   719
            return compareTo((AbstractChronology) obj) == 0;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   720
        }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   721
        return false;
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   722
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   723
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   724
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   725
     * A hash code for this chronology.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   726
     * <p>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   727
     * The hash code should be based on the entire state of the object.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   728
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   729
     * @implSpec
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   730
     * This implementation is based on the chronology ID and class.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   731
     * Subclasses should add any additional state that they store.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   732
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   733
     * @return a suitable hash code
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   734
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   735
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   736
    public int hashCode() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   737
        return getClass().hashCode() ^ getId().hashCode();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   738
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   739
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   740
    //-----------------------------------------------------------------------
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   741
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   742
     * Outputs this chronology as a {@code String}, using the chronology ID.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   743
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   744
     * @return a string representation of this chronology, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   745
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   746
    @Override
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   747
    public String toString() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   748
        return getId();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   749
    }
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
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   753
     * Writes the Chronology using a
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   754
     * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>.
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   755
     * <pre>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   756
     *  out.writeByte(1);  // identifies this as a Chronology
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   757
     *  out.writeUTF(getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   758
     * </pre>
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   759
     *
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   760
     * @return the instance of {@code Ser}, not null
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   761
     */
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   762
    Object writeReplace() {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   763
        return new Ser(Ser.CHRONO_TYPE, this);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   764
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   765
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   766
    /**
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   767
     * Defend against malicious streams.
22081
86eb26ff8f2b 8030002: Enhance deserialization using readObject
rriggs
parents: 20795
diff changeset
   768
     *
22566
4ebe53dd7814 8032502: java.time add @param tags to readObject
rriggs
parents: 22081
diff changeset
   769
     * @param s the stream to read
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   770
     * @throws java.io.InvalidObjectException always
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   771
     */
22081
86eb26ff8f2b 8030002: Enhance deserialization using readObject
rriggs
parents: 20795
diff changeset
   772
    private void readObject(ObjectInputStream s) throws ObjectStreamException {
20794
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   773
        throw new InvalidObjectException("Deserialization via serialization delegate");
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   774
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   775
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   776
    void writeExternal(DataOutput out) throws IOException {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   777
        out.writeUTF(getId());
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   778
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   779
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   780
    static Chronology readExternal(DataInput in) throws IOException {
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   781
        String id = in.readUTF();
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   782
        return Chronology.of(id);
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   783
    }
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   784
ec823009c5f7 8025719: Change Chronology to an interface
scolebourne
parents:
diff changeset
   785
}