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