View Javadoc
1   /*
2    * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  /*
27   * This file is available under and governed by the GNU General Public
28   * License version 2 only, as published by the Free Software Foundation.
29   * However, the following notice accompanied the original version of this
30   * file:
31   *
32   * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
33   *
34   * All rights reserved.
35   *
36   * Redistribution and use in source and binary forms, with or without
37   * modification, are permitted provided that the following conditions are met:
38   *
39   *  * Redistributions of source code must retain the above copyright notice,
40   *    this list of conditions and the following disclaimer.
41   *
42   *  * Redistributions in binary form must reproduce the above copyright notice,
43   *    this list of conditions and the following disclaimer in the documentation
44   *    and/or other materials provided with the distribution.
45   *
46   *  * Neither the name of JSR-310 nor the names of its contributors
47   *    may be used to endorse or promote products derived from this software
48   *    without specific prior written permission.
49   *
50   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
51   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
52   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
53   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
54   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
56   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
57   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
58   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
59   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61   */
62  package java.time.chrono;
63  
64  import java.time.Clock;
65  import java.time.DateTimeException;
66  import java.time.Instant;
67  import java.time.LocalDate;
68  import java.time.LocalTime;
69  import java.time.ZoneId;
70  import java.time.format.DateTimeFormatterBuilder;
71  import java.time.format.ResolverStyle;
72  import java.time.format.TextStyle;
73  import java.time.temporal.ChronoField;
74  import java.time.temporal.TemporalAccessor;
75  import java.time.temporal.TemporalField;
76  import java.time.temporal.TemporalQueries;
77  import java.time.temporal.TemporalQuery;
78  import java.time.temporal.UnsupportedTemporalTypeException;
79  import java.time.temporal.ValueRange;
80  import java.util.List;
81  import java.util.Locale;
82  import java.util.Map;
83  import java.util.Objects;
84  import java.util.Set;
85  
86  /**
87   * A calendar system, used to organize and identify dates.
88   * <p>
89   * The main date and time API is built on the ISO calendar system.
90   * The chronology operates behind the scenes to represent the general concept of a calendar system.
91   * For example, the Japanese, Minguo, Thai Buddhist and others.
92   * <p>
93   * Most other calendar systems also operate on the shared concepts of year, month and day,
94   * linked to the cycles of the Earth around the Sun, and the Moon around the Earth.
95   * These shared concepts are defined by {@link ChronoField} and are available
96   * for use by any {@code Chronology} implementation:
97   * <pre>
98   *   LocalDate isoDate = ...
99   *   ThaiBuddhistDate thaiDate = ...
100  *   int isoYear = isoDate.get(ChronoField.YEAR);
101  *   int thaiYear = thaiDate.get(ChronoField.YEAR);
102  * </pre>
103  * As shown, although the date objects are in different calendar systems, represented by different
104  * {@code Chronology} instances, both can be queried using the same constant on {@code ChronoField}.
105  * For a full discussion of the implications of this, see {@link ChronoLocalDate}.
106  * In general, the advice is to use the known ISO-based {@code LocalDate}, rather than
107  * {@code ChronoLocalDate}.
108  * <p>
109  * While a {@code Chronology} object typically uses {@code ChronoField} and is based on
110  * an era, year-of-era, month-of-year, day-of-month model of a date, this is not required.
111  * A {@code Chronology} instance may represent a totally different kind of calendar system,
112  * such as the Mayan.
113  * <p>
114  * In practical terms, the {@code Chronology} instance also acts as a factory.
115  * The {@link #of(String)} method allows an instance to be looked up by identifier,
116  * while the {@link #ofLocale(Locale)} method allows lookup by locale.
117  * <p>
118  * The {@code Chronology} instance provides a set of methods to create {@code ChronoLocalDate} instances.
119  * The date classes are used to manipulate specific dates.
120  * <ul>
121  * <li> {@link #dateNow() dateNow()}
122  * <li> {@link #dateNow(Clock) dateNow(clock)}
123  * <li> {@link #dateNow(ZoneId) dateNow(zone)}
124  * <li> {@link #date(int, int, int) date(yearProleptic, month, day)}
125  * <li> {@link #date(Era, int, int, int) date(era, yearOfEra, month, day)}
126  * <li> {@link #dateYearDay(int, int) dateYearDay(yearProleptic, dayOfYear)}
127  * <li> {@link #dateYearDay(Era, int, int) dateYearDay(era, yearOfEra, dayOfYear)}
128  * <li> {@link #date(TemporalAccessor) date(TemporalAccessor)}
129  * </ul>
130  *
131  * <h3 id="addcalendars">Adding New Calendars</h3>
132  * The set of available chronologies can be extended by applications.
133  * Adding a new calendar system requires the writing of an implementation of
134  * {@code Chronology}, {@code ChronoLocalDate} and {@code Era}.
135  * The majority of the logic specific to the calendar system will be in
136  * {@code ChronoLocalDate}. The {@code Chronology} subclass acts as a factory.
137  * <p>
138  * To permit the discovery of additional chronologies, the {@link java.util.ServiceLoader ServiceLoader}
139  * is used. A file must be added to the {@code META-INF/services} directory with the
140  * name 'java.time.chrono.Chronology' listing the implementation classes.
141  * See the ServiceLoader for more details on service loading.
142  * For lookup by id or calendarType, the system provided calendars are found
143  * first followed by application provided calendars.
144  * <p>
145  * Each chronology must define a chronology ID that is unique within the system.
146  * If the chronology represents a calendar system defined by the
147  * CLDR specification then the calendar type is the concatenation of the
148  * CLDR type and, if applicable, the CLDR variant,
149  *
150  * @implSpec
151  * This interface must be implemented with care to ensure other classes operate correctly.
152  * All implementations that can be instantiated must be final, immutable and thread-safe.
153  * Subclasses should be Serializable wherever possible.
154  *
155  * @since 1.8
156  */
157 public interface Chronology extends Comparable<Chronology> {
158 
159     /**
160      * Obtains an instance of {@code Chronology} from a temporal object.
161      * <p>
162      * This obtains a chronology based on the specified temporal.
163      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
164      * which this factory converts to an instance of {@code Chronology}.
165      * <p>
166      * The conversion will obtain the chronology using {@link TemporalQueries#chronology()}.
167      * If the specified temporal object does not have a chronology, {@link IsoChronology} is returned.
168      * <p>
169      * This method matches the signature of the functional interface {@link TemporalQuery}
170      * allowing it to be used in queries via method reference, {@code Chronology::from}.
171      *
172      * @param temporal  the temporal to convert, not null
173      * @return the chronology, not null
174      * @throws DateTimeException if unable to convert to an {@code Chronology}
175      */
176     static Chronology from(TemporalAccessor temporal) {
177         Objects.requireNonNull(temporal, "temporal");
178         Chronology obj = temporal.query(TemporalQueries.chronology());
179         return (obj != null ? obj : IsoChronology.INSTANCE);
180     }
181 
182     //-----------------------------------------------------------------------
183     /**
184      * Obtains an instance of {@code Chronology} from a locale.
185      * <p>
186      * This returns a {@code Chronology} based on the specified locale,
187      * typically returning {@code IsoChronology}. Other calendar systems
188      * are only returned if they are explicitly selected within the locale.
189      * <p>
190      * The {@link Locale} class provide access to a range of information useful
191      * for localizing an application. This includes the language and region,
192      * such as "en-GB" for English as used in Great Britain.
193      * <p>
194      * The {@code Locale} class also supports an extension mechanism that
195      * can be used to identify a calendar system. The mechanism is a form
196      * of key-value pairs, where the calendar system has the key "ca".
197      * For example, the locale "en-JP-u-ca-japanese" represents the English
198      * language as used in Japan with the Japanese calendar system.
199      * <p>
200      * This method finds the desired calendar system by in a manner equivalent
201      * to passing "ca" to {@link Locale#getUnicodeLocaleType(String)}.
202      * If the "ca" key is not present, then {@code IsoChronology} is returned.
203      * <p>
204      * Note that the behavior of this method differs from the older
205      * {@link java.util.Calendar#getInstance(Locale)} method.
206      * If that method receives a locale of "th_TH" it will return {@code BuddhistCalendar}.
207      * By contrast, this method will return {@code IsoChronology}.
208      * Passing the locale "th-TH-u-ca-buddhist" into either method will
209      * result in the Thai Buddhist calendar system and is therefore the
210      * recommended approach going forward for Thai calendar system localization.
211      * <p>
212      * A similar, but simpler, situation occurs for the Japanese calendar system.
213      * The locale "jp_JP_JP" has previously been used to access the calendar.
214      * However, unlike the Thai locale, "ja_JP_JP" is automatically converted by
215      * {@code Locale} to the modern and recommended form of "ja-JP-u-ca-japanese".
216      * Thus, there is no difference in behavior between this method and
217      * {@code Calendar#getInstance(Locale)}.
218      *
219      * @param locale  the locale to use to obtain the calendar system, not null
220      * @return the calendar system associated with the locale, not null
221      * @throws DateTimeException if the locale-specified calendar cannot be found
222      */
223     static Chronology ofLocale(Locale locale) {
224         return AbstractChronology.ofLocale(locale);
225     }
226 
227     //-----------------------------------------------------------------------
228     /**
229      * Obtains an instance of {@code Chronology} from a chronology ID or
230      * calendar system type.
231      * <p>
232      * This returns a chronology based on either the ID or the type.
233      * The {@link #getId() chronology ID} uniquely identifies the chronology.
234      * The {@link #getCalendarType() calendar system type} is defined by the
235      * CLDR specification.
236      * <p>
237      * The chronology may be a system chronology or a chronology
238      * provided by the application via ServiceLoader configuration.
239      * <p>
240      * Since some calendars can be customized, the ID or type typically refers
241      * to the default customization. For example, the Gregorian calendar can have multiple
242      * cutover dates from the Julian, but the lookup only provides the default cutover date.
243      *
244      * @param id  the chronology ID or calendar system type, not null
245      * @return the chronology with the identifier requested, not null
246      * @throws DateTimeException if the chronology cannot be found
247      */
248     static Chronology of(String id) {
249         return AbstractChronology.of(id);
250     }
251 
252     /**
253      * Returns the available chronologies.
254      * <p>
255      * Each returned {@code Chronology} is available for use in the system.
256      * The set of chronologies includes the system chronologies and
257      * any chronologies provided by the application via ServiceLoader
258      * configuration.
259      *
260      * @return the independent, modifiable set of the available chronology IDs, not null
261      */
262     static Set<Chronology> getAvailableChronologies() {
263         return AbstractChronology.getAvailableChronologies();
264     }
265 
266     //-----------------------------------------------------------------------
267     /**
268      * Gets the ID of the chronology.
269      * <p>
270      * The ID uniquely identifies the {@code Chronology}.
271      * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
272      *
273      * @return the chronology ID, not null
274      * @see #getCalendarType()
275      */
276     String getId();
277 
278     /**
279      * Gets the calendar type of the calendar system.
280      * <p>
281      * The calendar type is an identifier defined by the CLDR and
282      * <em>Unicode Locale Data Markup Language (LDML)</em> specifications
283      * to uniquely identification a calendar.
284      * The {@code getCalendarType} is the concatenation of the CLDR calendar type
285      * and the variant, if applicable, is appended separated by "-".
286      * The calendar type is used to lookup the {@code Chronology} using {@link #of(String)}.
287      *
288      * @return the calendar system type, null if the calendar is not defined by CLDR/LDML
289      * @see #getId()
290      */
291     String getCalendarType();
292 
293     //-----------------------------------------------------------------------
294     /**
295      * Obtains a local date in this chronology from the era, year-of-era,
296      * month-of-year and day-of-month fields.
297      *
298      * @implSpec
299      * The default implementation combines the era and year-of-era into a proleptic
300      * year before calling {@link #date(int, int, int)}.
301      *
302      * @param era  the era of the correct type for the chronology, not null
303      * @param yearOfEra  the chronology year-of-era
304      * @param month  the chronology month-of-year
305      * @param dayOfMonth  the chronology day-of-month
306      * @return the local date in this chronology, not null
307      * @throws DateTimeException if unable to create the date
308      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
309      */
310     default ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
311         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
312     }
313 
314     /**
315      * Obtains a local date in this chronology from the proleptic-year,
316      * month-of-year and day-of-month fields.
317      *
318      * @param prolepticYear  the chronology proleptic-year
319      * @param month  the chronology month-of-year
320      * @param dayOfMonth  the chronology day-of-month
321      * @return the local date in this chronology, not null
322      * @throws DateTimeException if unable to create the date
323      */
324     ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth);
325 
326     /**
327      * Obtains a local date in this chronology from the era, year-of-era and
328      * day-of-year fields.
329      *
330      * @implSpec
331      * The default implementation combines the era and year-of-era into a proleptic
332      * year before calling {@link #dateYearDay(int, int)}.
333      *
334      * @param era  the era of the correct type for the chronology, not null
335      * @param yearOfEra  the chronology year-of-era
336      * @param dayOfYear  the chronology day-of-year
337      * @return the local date in this chronology, not null
338      * @throws DateTimeException if unable to create the date
339      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
340      */
341     default ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
342         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
343     }
344 
345     /**
346      * Obtains a local date in this chronology from the proleptic-year and
347      * day-of-year fields.
348      *
349      * @param prolepticYear  the chronology proleptic-year
350      * @param dayOfYear  the chronology day-of-year
351      * @return the local date in this chronology, not null
352      * @throws DateTimeException if unable to create the date
353      */
354     ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear);
355 
356     /**
357      * Obtains a local date in this chronology from the epoch-day.
358      * <p>
359      * The definition of {@link ChronoField#EPOCH_DAY EPOCH_DAY} is the same
360      * for all calendar systems, thus it can be used for conversion.
361      *
362      * @param epochDay  the epoch day
363      * @return the local date in this chronology, not null
364      * @throws DateTimeException if unable to create the date
365      */
366     ChronoLocalDate dateEpochDay(long epochDay);
367 
368     //-----------------------------------------------------------------------
369     /**
370      * Obtains the current local date in this chronology from the system clock in the default time-zone.
371      * <p>
372      * This will query the {@link Clock#systemDefaultZone() system clock} in the default
373      * time-zone to obtain the current date.
374      * <p>
375      * Using this method will prevent the ability to use an alternate clock for testing
376      * because the clock is hard-coded.
377      *
378      * @implSpec
379      * The default implementation invokes {@link #dateNow(Clock)}.
380      *
381      * @return the current local date using the system clock and default time-zone, not null
382      * @throws DateTimeException if unable to create the date
383      */
384     default ChronoLocalDate dateNow() {
385         return dateNow(Clock.systemDefaultZone());
386     }
387 
388     /**
389      * Obtains the current local date in this chronology from the system clock in the specified time-zone.
390      * <p>
391      * This will query the {@link Clock#system(ZoneId) system clock} to obtain the current date.
392      * Specifying the time-zone avoids dependence on the default time-zone.
393      * <p>
394      * Using this method will prevent the ability to use an alternate clock for testing
395      * because the clock is hard-coded.
396      *
397      * @implSpec
398      * The default implementation invokes {@link #dateNow(Clock)}.
399      *
400      * @param zone  the zone ID to use, not null
401      * @return the current local date using the system clock, not null
402      * @throws DateTimeException if unable to create the date
403      */
404     default ChronoLocalDate dateNow(ZoneId zone) {
405         return dateNow(Clock.system(zone));
406     }
407 
408     /**
409      * Obtains the current local date in this chronology from the specified clock.
410      * <p>
411      * This will query the specified clock to obtain the current date - today.
412      * Using this method allows the use of an alternate clock for testing.
413      * The alternate clock may be introduced using {@link Clock dependency injection}.
414      *
415      * @implSpec
416      * The default implementation invokes {@link #date(TemporalAccessor)} )}.
417      *
418      * @param clock  the clock to use, not null
419      * @return the current local date, not null
420      * @throws DateTimeException if unable to create the date
421      */
422     default ChronoLocalDate dateNow(Clock clock) {
423         Objects.requireNonNull(clock, "clock");
424         return date(LocalDate.now(clock));
425     }
426 
427     //-----------------------------------------------------------------------
428     /**
429      * Obtains a local date in this chronology from another temporal object.
430      * <p>
431      * This obtains a date in this chronology based on the specified temporal.
432      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
433      * which this factory converts to an instance of {@code ChronoLocalDate}.
434      * <p>
435      * The conversion typically uses the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
436      * field, which is standardized across calendar systems.
437      * <p>
438      * This method matches the signature of the functional interface {@link TemporalQuery}
439      * allowing it to be used as a query via method reference, {@code aChronology::date}.
440      *
441      * @param temporal  the temporal object to convert, not null
442      * @return the local date in this chronology, not null
443      * @throws DateTimeException if unable to create the date
444      * @see ChronoLocalDate#from(TemporalAccessor)
445      */
446     ChronoLocalDate date(TemporalAccessor temporal);
447 
448     /**
449      * Obtains a local date-time in this chronology from another temporal object.
450      * <p>
451      * This obtains a date-time in this chronology based on the specified temporal.
452      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
453      * which this factory converts to an instance of {@code ChronoLocalDateTime}.
454      * <p>
455      * The conversion extracts and combines the {@code ChronoLocalDate} and the
456      * {@code LocalTime} from the temporal object.
457      * Implementations are permitted to perform optimizations such as accessing
458      * those fields that are equivalent to the relevant objects.
459      * The result uses this chronology.
460      * <p>
461      * This method matches the signature of the functional interface {@link TemporalQuery}
462      * allowing it to be used as a query via method reference, {@code aChronology::localDateTime}.
463      *
464      * @param temporal  the temporal object to convert, not null
465      * @return the local date-time in this chronology, not null
466      * @throws DateTimeException if unable to create the date-time
467      * @see ChronoLocalDateTime#from(TemporalAccessor)
468      */
469     default ChronoLocalDateTime<? extends ChronoLocalDate> localDateTime(TemporalAccessor temporal) {
470         try {
471             return date(temporal).atTime(LocalTime.from(temporal));
472         } catch (DateTimeException ex) {
473             throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass(), ex);
474         }
475     }
476 
477     /**
478      * Obtains a {@code ChronoZonedDateTime} in this chronology from another temporal object.
479      * <p>
480      * This obtains a zoned date-time in this chronology based on the specified temporal.
481      * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
482      * which this factory converts to an instance of {@code ChronoZonedDateTime}.
483      * <p>
484      * The conversion will first obtain a {@code ZoneId} from the temporal object,
485      * falling back to a {@code ZoneOffset} if necessary. It will then try to obtain
486      * an {@code Instant}, falling back to a {@code ChronoLocalDateTime} if necessary.
487      * The result will be either the combination of {@code ZoneId} or {@code ZoneOffset}
488      * with {@code Instant} or {@code ChronoLocalDateTime}.
489      * Implementations are permitted to perform optimizations such as accessing
490      * those fields that are equivalent to the relevant objects.
491      * The result uses this chronology.
492      * <p>
493      * This method matches the signature of the functional interface {@link TemporalQuery}
494      * allowing it to be used as a query via method reference, {@code aChronology::zonedDateTime}.
495      *
496      * @param temporal  the temporal object to convert, not null
497      * @return the zoned date-time in this chronology, not null
498      * @throws DateTimeException if unable to create the date-time
499      * @see ChronoZonedDateTime#from(TemporalAccessor)
500      */
501     default ChronoZonedDateTime<? extends ChronoLocalDate> zonedDateTime(TemporalAccessor temporal) {
502         try {
503             ZoneId zone = ZoneId.from(temporal);
504             try {
505                 Instant instant = Instant.from(temporal);
506                 return zonedDateTime(instant, zone);
507 
508             } catch (DateTimeException ex1) {
509                 ChronoLocalDateTimeImpl<?> cldt = ChronoLocalDateTimeImpl.ensureValid(this, localDateTime(temporal));
510                 return ChronoZonedDateTimeImpl.ofBest(cldt, zone, null);
511             }
512         } catch (DateTimeException ex) {
513             throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " + temporal.getClass(), ex);
514         }
515     }
516 
517     /**
518      * Obtains a {@code ChronoZonedDateTime} in this chronology from an {@code Instant}.
519      * <p>
520      * This obtains a zoned date-time with the same instant as that specified.
521      *
522      * @param instant  the instant to create the date-time from, not null
523      * @param zone  the time-zone, not null
524      * @return the zoned date-time, not null
525      * @throws DateTimeException if the result exceeds the supported range
526      */
527     default ChronoZonedDateTime<? extends ChronoLocalDate> zonedDateTime(Instant instant, ZoneId zone) {
528         return ChronoZonedDateTimeImpl.ofInstant(this, instant, zone);
529     }
530 
531     //-----------------------------------------------------------------------
532     /**
533      * Checks if the specified year is a leap year.
534      * <p>
535      * A leap-year is a year of a longer length than normal.
536      * The exact meaning is determined by the chronology according to the following constraints.
537      * <ul>
538      * <li>a leap-year must imply a year-length longer than a non leap-year.
539      * <li>a chronology that does not support the concept of a year must return false.
540      * </ul>
541      *
542      * @param prolepticYear  the proleptic-year to check, not validated for range
543      * @return true if the year is a leap year
544      */
545     boolean isLeapYear(long prolepticYear);
546 
547     /**
548      * Calculates the proleptic-year given the era and year-of-era.
549      * <p>
550      * This combines the era and year-of-era into the single proleptic-year field.
551      * <p>
552      * If the chronology makes active use of eras, such as {@code JapaneseChronology}
553      * then the year-of-era will be validated against the era.
554      * For other chronologies, validation is optional.
555      *
556      * @param era  the era of the correct type for the chronology, not null
557      * @param yearOfEra  the chronology year-of-era
558      * @return the proleptic-year
559      * @throws DateTimeException if unable to convert to a proleptic-year,
560      *  such as if the year is invalid for the era
561      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
562      */
563     int prolepticYear(Era era, int yearOfEra);
564 
565     /**
566      * Creates the chronology era object from the numeric value.
567      * <p>
568      * The era is, conceptually, the largest division of the time-line.
569      * Most calendar systems have a single epoch dividing the time-line into two eras.
570      * However, some have multiple eras, such as one for the reign of each leader.
571      * The exact meaning is determined by the chronology according to the following constraints.
572      * <p>
573      * The era in use at 1970-01-01 must have the value 1.
574      * Later eras must have sequentially higher values.
575      * Earlier eras must have sequentially lower values.
576      * Each chronology must refer to an enum or similar singleton to provide the era values.
577      * <p>
578      * This method returns the singleton era of the correct type for the specified era value.
579      *
580      * @param eraValue  the era value
581      * @return the calendar system era, not null
582      * @throws DateTimeException if unable to create the era
583      */
584     Era eraOf(int eraValue);
585 
586     /**
587      * Gets the list of eras for the chronology.
588      * <p>
589      * Most calendar systems have an era, within which the year has meaning.
590      * If the calendar system does not support the concept of eras, an empty
591      * list must be returned.
592      *
593      * @return the list of eras for the chronology, may be immutable, not null
594      */
595     List<Era> eras();
596 
597     //-----------------------------------------------------------------------
598     /**
599      * Gets the range of valid values for the specified field.
600      * <p>
601      * All fields can be expressed as a {@code long} integer.
602      * This method returns an object that describes the valid range for that value.
603      * <p>
604      * Note that the result only describes the minimum and maximum valid values
605      * and it is important not to read too much into them. For example, there
606      * could be values within the range that are invalid for the field.
607      * <p>
608      * This method will return a result whether or not the chronology supports the field.
609      *
610      * @param field  the field to get the range for, not null
611      * @return the range of valid values for the field, not null
612      * @throws DateTimeException if the range for the field cannot be obtained
613      */
614     ValueRange range(ChronoField field);
615 
616     //-----------------------------------------------------------------------
617     /**
618      * Gets the textual representation of this chronology.
619      * <p>
620      * This returns the textual name used to identify the chronology,
621      * suitable for presentation to the user.
622      * The parameters control the style of the returned text and the locale.
623      *
624      * @implSpec
625      * The default implementation behaves as the the formatter was used to
626      * format the chronology textual name.
627      *
628      * @param style  the style of the text required, not null
629      * @param locale  the locale to use, not null
630      * @return the text value of the chronology, not null
631      */
632     default String getDisplayName(TextStyle style, Locale locale) {
633         TemporalAccessor temporal = new TemporalAccessor() {
634             @Override
635             public boolean isSupported(TemporalField field) {
636                 return false;
637             }
638             @Override
639             public long getLong(TemporalField field) {
640                 throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
641             }
642             @SuppressWarnings("unchecked")
643             @Override
644             public <R> R query(TemporalQuery<R> query) {
645                 if (query == TemporalQueries.chronology()) {
646                     return (R) Chronology.this;
647                 }
648                 return TemporalAccessor.super.query(query);
649             }
650         };
651         return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(temporal);
652     }
653 
654     //-----------------------------------------------------------------------
655     /**
656      * Resolves parsed {@code ChronoField} values into a date during parsing.
657      * <p>
658      * Most {@code TemporalField} implementations are resolved using the
659      * resolve method on the field. By contrast, the {@code ChronoField} class
660      * defines fields that only have meaning relative to the chronology.
661      * As such, {@code ChronoField} date fields are resolved here in the
662      * context of a specific chronology.
663      * <p>
664      * The default implementation, which explains typical resolve behaviour,
665      * is provided in {@link AbstractChronology}.
666      *
667      * @param fieldValues  the map of fields to values, which can be updated, not null
668      * @param resolverStyle  the requested type of resolve, not null
669      * @return the resolved date, null if insufficient information to create a date
670      * @throws DateTimeException if the date cannot be resolved, typically
671      *  because of a conflict in the input data
672      */
673     ChronoLocalDate resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle);
674 
675     //-----------------------------------------------------------------------
676     /**
677      * Obtains a period for this chronology based on years, months and days.
678      * <p>
679      * This returns a period tied to this chronology using the specified
680      * years, months and days.  All supplied chronologies use periods
681      * based on years, months and days, however the {@code ChronoPeriod} API
682      * allows the period to be represented using other units.
683      *
684      * @implSpec
685      * The default implementation returns an implementation class suitable
686      * for most calendar systems. It is based solely on the three units.
687      * Normalization, addition and subtraction derive the number of months
688      * in a year from the {@link #range(ChronoField)}. If the number of
689      * months within a year is fixed, then the calculation approach for
690      * addition, subtraction and normalization is slightly different.
691      * <p>
692      * If implementing an unusual calendar system that is not based on
693      * years, months and days, or where you want direct control, then
694      * the {@code ChronoPeriod} interface must be directly implemented.
695      * <p>
696      * The returned period is immutable and thread-safe.
697      *
698      * @param years  the number of years, may be negative
699      * @param months  the number of years, may be negative
700      * @param days  the number of years, may be negative
701      * @return the period in terms of this chronology, not null
702      */
703     default ChronoPeriod period(int years, int months, int days) {
704         return new ChronoPeriodImpl(this, years, months, days);
705     }
706 
707     //-----------------------------------------------------------------------
708     /**
709      * Compares this chronology to another chronology.
710      * <p>
711      * The comparison order first by the chronology ID string, then by any
712      * additional information specific to the subclass.
713      * It is "consistent with equals", as defined by {@link Comparable}.
714      *
715      * @param other  the other chronology to compare to, not null
716      * @return the comparator value, negative if less, positive if greater
717      */
718     @Override
719     int compareTo(Chronology other);
720 
721     /**
722      * Checks if this chronology is equal to another chronology.
723      * <p>
724      * The comparison is based on the entire state of the object.
725      *
726      * @param obj  the object to check, null returns false
727      * @return true if this is equal to the other chronology
728      */
729     @Override
730     boolean equals(Object obj);
731 
732     /**
733      * A hash code for this chronology.
734      * <p>
735      * The hash code should be based on the entire state of the object.
736      *
737      * @return a suitable hash code
738      */
739     @Override
740     int hashCode();
741 
742     //-----------------------------------------------------------------------
743     /**
744      * Outputs this chronology as a {@code String}.
745      * <p>
746      * The format should include the entire state of the object.
747      *
748      * @return a string representation of this chronology, not null
749      */
750     @Override
751     String toString();
752 
753 }