jdk/src/share/classes/java/time/chrono/Chronology.java
changeset 19030 32f129cb6351
parent 17474 8c100beabcc0
child 19841 15c8e97d6a14
equal deleted inserted replaced
19029:30c64a024c86 19030:32f129cb6351
    72 import static java.time.temporal.ChronoField.ERA;
    72 import static java.time.temporal.ChronoField.ERA;
    73 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
    73 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
    74 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
    74 import static java.time.temporal.ChronoField.PROLEPTIC_MONTH;
    75 import static java.time.temporal.ChronoField.YEAR;
    75 import static java.time.temporal.ChronoField.YEAR;
    76 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
    76 import static java.time.temporal.ChronoField.YEAR_OF_ERA;
       
    77 import static java.time.temporal.ChronoUnit.DAYS;
       
    78 import static java.time.temporal.ChronoUnit.MONTHS;
       
    79 import static java.time.temporal.ChronoUnit.WEEKS;
    77 import static java.time.temporal.TemporalAdjuster.nextOrSame;
    80 import static java.time.temporal.TemporalAdjuster.nextOrSame;
    78 
    81 
    79 import java.io.DataInput;
    82 import java.io.DataInput;
    80 import java.io.DataOutput;
    83 import java.io.DataOutput;
    81 import java.io.IOException;
    84 import java.io.IOException;
    86 import java.time.DateTimeException;
    89 import java.time.DateTimeException;
    87 import java.time.DayOfWeek;
    90 import java.time.DayOfWeek;
    88 import java.time.Instant;
    91 import java.time.Instant;
    89 import java.time.LocalDate;
    92 import java.time.LocalDate;
    90 import java.time.LocalTime;
    93 import java.time.LocalTime;
       
    94 import java.time.Month;
       
    95 import java.time.Year;
    91 import java.time.ZoneId;
    96 import java.time.ZoneId;
    92 import java.time.format.DateTimeFormatterBuilder;
    97 import java.time.format.DateTimeFormatterBuilder;
    93 import java.time.format.ResolverStyle;
    98 import java.time.format.ResolverStyle;
    94 import java.time.format.TextStyle;
    99 import java.time.format.TextStyle;
    95 import java.time.temporal.ChronoField;
   100 import java.time.temporal.ChronoField;
    96 import java.time.temporal.ChronoUnit;
       
    97 import java.time.temporal.Temporal;
   101 import java.time.temporal.Temporal;
    98 import java.time.temporal.TemporalAccessor;
   102 import java.time.temporal.TemporalAccessor;
       
   103 import java.time.temporal.TemporalAdjuster;
    99 import java.time.temporal.TemporalField;
   104 import java.time.temporal.TemporalField;
   100 import java.time.temporal.TemporalQuery;
   105 import java.time.temporal.TemporalQuery;
   101 import java.time.temporal.UnsupportedTemporalTypeException;
   106 import java.time.temporal.UnsupportedTemporalTypeException;
   102 import java.time.temporal.ValueRange;
   107 import java.time.temporal.ValueRange;
   103 import java.util.Comparator;
   108 import java.util.Comparator;
   186 public abstract class Chronology implements Comparable<Chronology> {
   191 public abstract class Chronology implements Comparable<Chronology> {
   187 
   192 
   188     /**
   193     /**
   189      * ChronoLocalDate order constant.
   194      * ChronoLocalDate order constant.
   190      */
   195      */
   191     static final Comparator<ChronoLocalDate<?>> DATE_ORDER =
   196     static final Comparator<ChronoLocalDate> DATE_ORDER =
   192         (Comparator<ChronoLocalDate<?>> & Serializable) (date1, date2) -> {
   197         (Comparator<ChronoLocalDate> & Serializable) (date1, date2) -> {
   193             return Long.compare(date1.toEpochDay(), date2.toEpochDay());
   198             return Long.compare(date1.toEpochDay(), date2.toEpochDay());
   194         };
   199         };
   195     /**
   200     /**
   196      * ChronoLocalDateTime order constant.
   201      * ChronoLocalDateTime order constant.
   197      */
   202      */
   480     protected Chronology() {
   485     protected Chronology() {
   481     }
   486     }
   482 
   487 
   483     //-----------------------------------------------------------------------
   488     //-----------------------------------------------------------------------
   484     /**
   489     /**
   485      * Casts the {@code Temporal} to {@code ChronoLocalDate} with the same chronology.
       
   486      *
       
   487      * @param temporal  a date-time to cast, not null
       
   488      * @return the date-time checked and cast to {@code ChronoLocalDate}, not null
       
   489      * @throws ClassCastException if the date-time cannot be cast to ChronoLocalDate
       
   490      *  or the chronology is not equal this Chronology
       
   491      */
       
   492     ChronoLocalDate<?> ensureChronoLocalDate(Temporal temporal) {
       
   493         @SuppressWarnings("unchecked")
       
   494         ChronoLocalDate<?> other = (ChronoLocalDate<?>) temporal;
       
   495         if (this.equals(other.getChronology()) == false) {
       
   496             throw new ClassCastException("Chronology mismatch, expected: " + getId() + ", actual: " + other.getChronology().getId());
       
   497         }
       
   498         return other;
       
   499     }
       
   500 
       
   501     /**
       
   502      * Casts the {@code Temporal} to {@code ChronoLocalDateTime} with the same chronology.
       
   503      *
       
   504      * @param temporal   a date-time to cast, not null
       
   505      * @return the date-time checked and cast to {@code ChronoLocalDateTime}, not null
       
   506      * @throws ClassCastException if the date-time cannot be cast to ChronoLocalDateTimeImpl
       
   507      *  or the chronology is not equal this Chronology
       
   508      */
       
   509     ChronoLocalDateTimeImpl<?> ensureChronoLocalDateTime(Temporal temporal) {
       
   510         @SuppressWarnings("unchecked")
       
   511         ChronoLocalDateTimeImpl<?> other = (ChronoLocalDateTimeImpl<?>) temporal;
       
   512         if (this.equals(other.toLocalDate().getChronology()) == false) {
       
   513             throw new ClassCastException("Chronology mismatch, required: " + getId()
       
   514                     + ", supplied: " + other.toLocalDate().getChronology().getId());
       
   515         }
       
   516         return other;
       
   517     }
       
   518 
       
   519     /**
       
   520      * Casts the {@code Temporal} to {@code ChronoZonedDateTimeImpl} with the same chronology.
       
   521      *
       
   522      * @param temporal  a date-time to cast, not null
       
   523      * @return the date-time checked and cast to {@code ChronoZonedDateTimeImpl}, not null
       
   524      * @throws ClassCastException if the date-time cannot be cast to ChronoZonedDateTimeImpl
       
   525      *  or the chronology is not equal this Chronology
       
   526      */
       
   527     ChronoZonedDateTimeImpl<?> ensureChronoZonedDateTime(Temporal temporal) {
       
   528         @SuppressWarnings("unchecked")
       
   529         ChronoZonedDateTimeImpl<?> other = (ChronoZonedDateTimeImpl<?>) temporal;
       
   530         if (this.equals(other.toLocalDate().getChronology()) == false) {
       
   531             throw new ClassCastException("Chronology mismatch, required: " + getId()
       
   532                     + ", supplied: " + other.toLocalDate().getChronology().getId());
       
   533         }
       
   534         return other;
       
   535     }
       
   536 
       
   537     //-----------------------------------------------------------------------
       
   538     /**
       
   539      * Gets the ID of the chronology.
   490      * Gets the ID of the chronology.
   540      * <p>
   491      * <p>
   541      * The ID uniquely identifies the {@code Chronology}.
   492      * The ID uniquely identifies the {@code Chronology}.
   542      * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
   493      * It can be used to lookup the {@code Chronology} using {@link #of(String)}.
   543      *
   494      *
   572      * @param dayOfMonth  the chronology day-of-month
   523      * @param dayOfMonth  the chronology day-of-month
   573      * @return the local date in this chronology, not null
   524      * @return the local date in this chronology, not null
   574      * @throws DateTimeException if unable to create the date
   525      * @throws DateTimeException if unable to create the date
   575      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
   526      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
   576      */
   527      */
   577     public ChronoLocalDate<?> date(Era era, int yearOfEra, int month, int dayOfMonth) {
   528     public ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) {
   578         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
   529         return date(prolepticYear(era, yearOfEra), month, dayOfMonth);
   579     }
   530     }
   580 
   531 
   581     /**
   532     /**
   582      * Obtains a local date in this chronology from the proleptic-year,
   533      * Obtains a local date in this chronology from the proleptic-year,
   586      * @param month  the chronology month-of-year
   537      * @param month  the chronology month-of-year
   587      * @param dayOfMonth  the chronology day-of-month
   538      * @param dayOfMonth  the chronology day-of-month
   588      * @return the local date in this chronology, not null
   539      * @return the local date in this chronology, not null
   589      * @throws DateTimeException if unable to create the date
   540      * @throws DateTimeException if unable to create the date
   590      */
   541      */
   591     public abstract ChronoLocalDate<?> date(int prolepticYear, int month, int dayOfMonth);
   542     public abstract ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth);
   592 
   543 
   593     /**
   544     /**
   594      * Obtains a local date in this chronology from the era, year-of-era and
   545      * Obtains a local date in this chronology from the era, year-of-era and
   595      * day-of-year fields.
   546      * day-of-year fields.
   596      *
   547      *
   599      * @param dayOfYear  the chronology day-of-year
   550      * @param dayOfYear  the chronology day-of-year
   600      * @return the local date in this chronology, not null
   551      * @return the local date in this chronology, not null
   601      * @throws DateTimeException if unable to create the date
   552      * @throws DateTimeException if unable to create the date
   602      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
   553      * @throws ClassCastException if the {@code era} is not of the correct type for the chronology
   603      */
   554      */
   604     public ChronoLocalDate<?> dateYearDay(Era era, int yearOfEra, int dayOfYear) {
   555     public ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) {
   605         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
   556         return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear);
   606     }
   557     }
   607 
   558 
   608     /**
   559     /**
   609      * Obtains a local date in this chronology from the proleptic-year and
   560      * Obtains a local date in this chronology from the proleptic-year and
   612      * @param prolepticYear  the chronology proleptic-year
   563      * @param prolepticYear  the chronology proleptic-year
   613      * @param dayOfYear  the chronology day-of-year
   564      * @param dayOfYear  the chronology day-of-year
   614      * @return the local date in this chronology, not null
   565      * @return the local date in this chronology, not null
   615      * @throws DateTimeException if unable to create the date
   566      * @throws DateTimeException if unable to create the date
   616      */
   567      */
   617     public abstract ChronoLocalDate<?> dateYearDay(int prolepticYear, int dayOfYear);
   568     public abstract ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear);
   618 
   569 
   619     /**
   570     /**
   620      * Obtains a local date in this chronology from the epoch-day.
   571      * Obtains a local date in this chronology from the epoch-day.
   621      * <p>
   572      * <p>
   622      * The definition of {@link ChronoField#EPOCH_DAY EPOCH_DAY} is the same
   573      * The definition of {@link ChronoField#EPOCH_DAY EPOCH_DAY} is the same
   624      *
   575      *
   625      * @param epochDay  the epoch day
   576      * @param epochDay  the epoch day
   626      * @return the local date in this chronology, not null
   577      * @return the local date in this chronology, not null
   627      * @throws DateTimeException if unable to create the date
   578      * @throws DateTimeException if unable to create the date
   628      */
   579      */
   629     public abstract ChronoLocalDate<?> dateEpochDay(long epochDay);
   580     public abstract ChronoLocalDate dateEpochDay(long epochDay);
   630 
   581 
   631     //-----------------------------------------------------------------------
   582     //-----------------------------------------------------------------------
   632     /**
   583     /**
   633      * Obtains the current local date in this chronology from the system clock in the default time-zone.
   584      * Obtains the current local date in this chronology from the system clock in the default time-zone.
   634      * <p>
   585      * <p>
   641      * This implementation uses {@link #dateNow(Clock)}.
   592      * This implementation uses {@link #dateNow(Clock)}.
   642      *
   593      *
   643      * @return the current local date using the system clock and default time-zone, not null
   594      * @return the current local date using the system clock and default time-zone, not null
   644      * @throws DateTimeException if unable to create the date
   595      * @throws DateTimeException if unable to create the date
   645      */
   596      */
   646     public ChronoLocalDate<?> dateNow() {
   597     public ChronoLocalDate dateNow() {
   647         return dateNow(Clock.systemDefaultZone());
   598         return dateNow(Clock.systemDefaultZone());
   648     }
   599     }
   649 
   600 
   650     /**
   601     /**
   651      * Obtains the current local date in this chronology from the system clock in the specified time-zone.
   602      * Obtains the current local date in this chronology from the system clock in the specified time-zone.
   658      *
   609      *
   659      * @param zone  the zone ID to use, not null
   610      * @param zone  the zone ID to use, not null
   660      * @return the current local date using the system clock, not null
   611      * @return the current local date using the system clock, not null
   661      * @throws DateTimeException if unable to create the date
   612      * @throws DateTimeException if unable to create the date
   662      */
   613      */
   663     public ChronoLocalDate<?> dateNow(ZoneId zone) {
   614     public ChronoLocalDate dateNow(ZoneId zone) {
   664         return dateNow(Clock.system(zone));
   615         return dateNow(Clock.system(zone));
   665     }
   616     }
   666 
   617 
   667     /**
   618     /**
   668      * Obtains the current local date in this chronology from the specified clock.
   619      * Obtains the current local date in this chronology from the specified clock.
   673      *
   624      *
   674      * @param clock  the clock to use, not null
   625      * @param clock  the clock to use, not null
   675      * @return the current local date, not null
   626      * @return the current local date, not null
   676      * @throws DateTimeException if unable to create the date
   627      * @throws DateTimeException if unable to create the date
   677      */
   628      */
   678     public ChronoLocalDate<?> dateNow(Clock clock) {
   629     public ChronoLocalDate dateNow(Clock clock) {
   679         Objects.requireNonNull(clock, "clock");
   630         Objects.requireNonNull(clock, "clock");
   680         return date(LocalDate.now(clock));
   631         return date(LocalDate.now(clock));
   681     }
   632     }
   682 
   633 
   683     //-----------------------------------------------------------------------
   634     //-----------------------------------------------------------------------
   697      * @param temporal  the temporal object to convert, not null
   648      * @param temporal  the temporal object to convert, not null
   698      * @return the local date in this chronology, not null
   649      * @return the local date in this chronology, not null
   699      * @throws DateTimeException if unable to create the date
   650      * @throws DateTimeException if unable to create the date
   700      * @see ChronoLocalDate#from(TemporalAccessor)
   651      * @see ChronoLocalDate#from(TemporalAccessor)
   701      */
   652      */
   702     public abstract ChronoLocalDate<?> date(TemporalAccessor temporal);
   653     public abstract ChronoLocalDate date(TemporalAccessor temporal);
   703 
   654 
   704     /**
   655     /**
   705      * Obtains a local date-time in this chronology from another temporal object.
   656      * Obtains a local date-time in this chronology from another temporal object.
   706      * <p>
   657      * <p>
   707      * This obtains a date-time in this chronology based on the specified temporal.
   658      * This obtains a date-time in this chronology based on the specified temporal.
   720      * @param temporal  the temporal object to convert, not null
   671      * @param temporal  the temporal object to convert, not null
   721      * @return the local date-time in this chronology, not null
   672      * @return the local date-time in this chronology, not null
   722      * @throws DateTimeException if unable to create the date-time
   673      * @throws DateTimeException if unable to create the date-time
   723      * @see ChronoLocalDateTime#from(TemporalAccessor)
   674      * @see ChronoLocalDateTime#from(TemporalAccessor)
   724      */
   675      */
   725     public ChronoLocalDateTime<?> localDateTime(TemporalAccessor temporal) {
   676     public ChronoLocalDateTime<? extends ChronoLocalDate> localDateTime(TemporalAccessor temporal) {
   726         try {
   677         try {
   727             return date(temporal).atTime(LocalTime.from(temporal));
   678             return date(temporal).atTime(LocalTime.from(temporal));
   728         } catch (DateTimeException ex) {
   679         } catch (DateTimeException ex) {
   729             throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass(), ex);
   680             throw new DateTimeException("Unable to obtain ChronoLocalDateTime from TemporalAccessor: " + temporal.getClass(), ex);
   730         }
   681         }
   752      * @param temporal  the temporal object to convert, not null
   703      * @param temporal  the temporal object to convert, not null
   753      * @return the zoned date-time in this chronology, not null
   704      * @return the zoned date-time in this chronology, not null
   754      * @throws DateTimeException if unable to create the date-time
   705      * @throws DateTimeException if unable to create the date-time
   755      * @see ChronoZonedDateTime#from(TemporalAccessor)
   706      * @see ChronoZonedDateTime#from(TemporalAccessor)
   756      */
   707      */
   757     public ChronoZonedDateTime<?> zonedDateTime(TemporalAccessor temporal) {
   708     public ChronoZonedDateTime<? extends ChronoLocalDate> zonedDateTime(TemporalAccessor temporal) {
   758         try {
   709         try {
   759             ZoneId zone = ZoneId.from(temporal);
   710             ZoneId zone = ZoneId.from(temporal);
   760             try {
   711             try {
   761                 Instant instant = Instant.from(temporal);
   712                 Instant instant = Instant.from(temporal);
   762                 return zonedDateTime(instant, zone);
   713                 return zonedDateTime(instant, zone);
   763 
   714 
   764             } catch (DateTimeException ex1) {
   715             } catch (DateTimeException ex1) {
   765                 @SuppressWarnings("rawtypes")
   716                 ChronoLocalDateTimeImpl<?> cldt = ChronoLocalDateTimeImpl.ensureValid(this, localDateTime(temporal));
   766                 ChronoLocalDateTimeImpl cldt = ensureChronoLocalDateTime(localDateTime(temporal));
       
   767                 return ChronoZonedDateTimeImpl.ofBest(cldt, zone, null);
   717                 return ChronoZonedDateTimeImpl.ofBest(cldt, zone, null);
   768             }
   718             }
   769         } catch (DateTimeException ex) {
   719         } catch (DateTimeException ex) {
   770             throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " + temporal.getClass(), ex);
   720             throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " + temporal.getClass(), ex);
   771         }
   721         }
   779      * @param instant  the instant to create the date-time from, not null
   729      * @param instant  the instant to create the date-time from, not null
   780      * @param zone  the time-zone, not null
   730      * @param zone  the time-zone, not null
   781      * @return the zoned date-time, not null
   731      * @return the zoned date-time, not null
   782      * @throws DateTimeException if the result exceeds the supported range
   732      * @throws DateTimeException if the result exceeds the supported range
   783      */
   733      */
   784     public ChronoZonedDateTime<?> zonedDateTime(Instant instant, ZoneId zone) {
   734     public ChronoZonedDateTime<? extends ChronoLocalDate> zonedDateTime(Instant instant, ZoneId zone) {
   785         return ChronoZonedDateTimeImpl.ofInstant(this, instant, zone);
   735         return ChronoZonedDateTimeImpl.ofInstant(this, instant, zone);
   786     }
   736     }
   787 
   737 
   788     //-----------------------------------------------------------------------
   738     //-----------------------------------------------------------------------
   789     /**
   739     /**
   927      * resolve method on the field. By contrast, the {@code ChronoField} class
   877      * resolve method on the field. By contrast, the {@code ChronoField} class
   928      * defines fields that only have meaning relative to the chronology.
   878      * defines fields that only have meaning relative to the chronology.
   929      * As such, {@code ChronoField} date fields are resolved here in the
   879      * As such, {@code ChronoField} date fields are resolved here in the
   930      * context of a specific chronology.
   880      * context of a specific chronology.
   931      * <p>
   881      * <p>
       
   882      * {@code ChronoField} instances are resolved by this method, which may
       
   883      * be overridden in subclasses.
       
   884      * <ul>
       
   885      * <li>{@code EPOCH_DAY} - If present, this is converted to a date and
       
   886      *  all other date fields are then cross-checked against the date.
       
   887      * <li>{@code PROLEPTIC_MONTH} - If present, then it is split into the
       
   888      *  {@code YEAR} and {@code MONTH_OF_YEAR}. If the mode is strict or smart
       
   889      *  then the field is validated.
       
   890      * <li>{@code YEAR_OF_ERA} and {@code ERA} - If both are present, then they
       
   891      *  are combined to form a {@code YEAR}. In lenient mode, the {@code YEAR_OF_ERA}
       
   892      *  range is not validated, in smart and strict mode it is. The {@code ERA} is
       
   893      *  validated for range in all three modes. If only the {@code YEAR_OF_ERA} is
       
   894      *  present, and the mode is smart or lenient, then the last available era
       
   895      *  is assumed. In strict mode, no era is assumed and the {@code YEAR_OF_ERA} is
       
   896      *  left untouched. If only the {@code ERA} is present, then it is left untouched.
       
   897      * <li>{@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} -
       
   898      *  If all three are present, then they are combined to form a date.
       
   899      *  In all three modes, the {@code YEAR} is validated.
       
   900      *  If the mode is smart or strict, then the month and day are validated.
       
   901      *  If the mode is lenient, then the date is combined in a manner equivalent to
       
   902      *  creating a date on the first day of the first month in the requested year,
       
   903      *  then adding the difference in months, then the difference in days.
       
   904      *  If the mode is smart, and the day-of-month is greater than the maximum for
       
   905      *  the year-month, then the day-of-month is adjusted to the last day-of-month.
       
   906      *  If the mode is strict, then the three fields must form a valid date.
       
   907      * <li>{@code YEAR} and {@code DAY_OF_YEAR} -
       
   908      *  If both are present, then they are combined to form a date.
       
   909      *  In all three modes, the {@code YEAR} is validated.
       
   910      *  If the mode is lenient, then the date is combined in a manner equivalent to
       
   911      *  creating a date on the first day of the requested year, then adding
       
   912      *  the difference in days.
       
   913      *  If the mode is smart or strict, then the two fields must form a valid date.
       
   914      * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
       
   915      *  {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} -
       
   916      *  If all four are present, then they are combined to form a date.
       
   917      *  In all three modes, the {@code YEAR} is validated.
       
   918      *  If the mode is lenient, then the date is combined in a manner equivalent to
       
   919      *  creating a date on the first day of the first month in the requested year, then adding
       
   920      *  the difference in months, then the difference in weeks, then in days.
       
   921      *  If the mode is smart or strict, then the all four fields are validated to
       
   922      *  their outer ranges. The date is then combined in a manner equivalent to
       
   923      *  creating a date on the first day of the requested year and month, then adding
       
   924      *  the amount in weeks and days to reach their values. If the mode is strict,
       
   925      *  the date is additionally validated to check that the day and week adjustment
       
   926      *  did not change the month.
       
   927      * <li>{@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and
       
   928      *  {@code DAY_OF_WEEK} - If all four are present, then they are combined to
       
   929      *  form a date. The approach is the same as described above for
       
   930      *  years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}.
       
   931      *  The day-of-week is adjusted as the next or same matching day-of-week once
       
   932      *  the years, months and weeks have been handled.
       
   933      * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code ALIGNED_DAY_OF_WEEK_IN_YEAR} -
       
   934      *  If all three are present, then they are combined to form a date.
       
   935      *  In all three modes, the {@code YEAR} is validated.
       
   936      *  If the mode is lenient, then the date is combined in a manner equivalent to
       
   937      *  creating a date on the first day of the requested year, then adding
       
   938      *  the difference in weeks, then in days.
       
   939      *  If the mode is smart or strict, then the all three fields are validated to
       
   940      *  their outer ranges. The date is then combined in a manner equivalent to
       
   941      *  creating a date on the first day of the requested year, then adding
       
   942      *  the amount in weeks and days to reach their values. If the mode is strict,
       
   943      *  the date is additionally validated to check that the day and week adjustment
       
   944      *  did not change the year.
       
   945      * <li>{@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} -
       
   946      *  If all three are present, then they are combined to form a date.
       
   947      *  The approach is the same as described above for years and weeks in
       
   948      *  {@code ALIGNED_DAY_OF_WEEK_IN_YEAR}. The day-of-week is adjusted as the
       
   949      *  next or same matching day-of-week once the years and weeks have been handled.
       
   950      * </ul>
       
   951      * <p>
   932      * The default implementation is suitable for most calendar systems.
   952      * The default implementation is suitable for most calendar systems.
   933      * If {@link ChronoField#YEAR_OF_ERA} is found without an {@link ChronoField#ERA}
   953      * If {@link ChronoField#YEAR_OF_ERA} is found without an {@link ChronoField#ERA}
   934      * then the last era in {@link #eras()} is used.
   954      * then the last era in {@link #eras()} is used.
   935      * The implementation assumes a 7 day week, that the first day-of-month
   955      * The implementation assumes a 7 day week, that the first day-of-month
   936      * has the value 1, and that first day-of-year has the value 1.
   956      * has the value 1, that first day-of-year has the value 1, and that the
       
   957      * first of the month and year always exists.
   937      *
   958      *
   938      * @param fieldValues  the map of fields to values, which can be updated, not null
   959      * @param fieldValues  the map of fields to values, which can be updated, not null
   939      * @param resolverStyle  the requested type of resolve, not null
   960      * @param resolverStyle  the requested type of resolve, not null
   940      * @return the resolved date, null if insufficient information to create a date
   961      * @return the resolved date, null if insufficient information to create a date
   941      * @throws DateTimeException if the date cannot be resolved, typically
   962      * @throws DateTimeException if the date cannot be resolved, typically
   942      *  because of a conflict in the input data
   963      *  because of a conflict in the input data
   943      */
   964      */
   944     public ChronoLocalDate<?> resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
   965     public ChronoLocalDate resolveDate(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
   945         // check epoch-day before inventing era
   966         // check epoch-day before inventing era
   946         if (fieldValues.containsKey(EPOCH_DAY)) {
   967         if (fieldValues.containsKey(EPOCH_DAY)) {
   947             return dateEpochDay(fieldValues.remove(EPOCH_DAY));
   968             return dateEpochDay(fieldValues.remove(EPOCH_DAY));
   948         }
   969         }
   949 
   970 
   950         // fix proleptic month before inventing era
   971         // fix proleptic month before inventing era
   951         Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
   972         resolveProlepticMonth(fieldValues, resolverStyle);
   952         if (pMonth != null) {
       
   953             // first day-of-month is likely to be safest for setting proleptic-month
       
   954             // cannot add to year zero, as not all chronologies have a year zero
       
   955             ChronoLocalDate<?> chronoDate = dateNow()
       
   956                     .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth);
       
   957             addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR));
       
   958             addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR));
       
   959         }
       
   960 
   973 
   961         // invent era if necessary to resolve year-of-era
   974         // invent era if necessary to resolve year-of-era
   962         Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
   975         ChronoLocalDate resolved = resolveYearOfEra(fieldValues, resolverStyle);
   963         if (yoeLong != null) {
   976         if (resolved != null) {
   964             Long eraLong = fieldValues.remove(ERA);
   977             return resolved;
   965             int yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);
       
   966             if (eraLong != null) {
       
   967                 Era eraObj = eraOf(Math.toIntExact(eraLong));
       
   968                 addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
       
   969             } else if (fieldValues.containsKey(YEAR)) {
       
   970                 int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR);
       
   971                 ChronoLocalDate<?> chronoDate = dateYearDay(year, 1);
       
   972                 addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe));
       
   973             } else {
       
   974                 List<Era> eras = eras();
       
   975                 if (eras.isEmpty()) {
       
   976                     addFieldValue(fieldValues, YEAR, yoe);
       
   977                 } else {
       
   978                     Era eraObj = eras.get(eras.size() - 1);
       
   979                     addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
       
   980                 }
       
   981             }
       
   982         }
   978         }
   983 
   979 
   984         // build date
   980         // build date
   985         if (fieldValues.containsKey(YEAR)) {
   981         if (fieldValues.containsKey(YEAR)) {
   986             if (fieldValues.containsKey(MONTH_OF_YEAR)) {
   982             if (fieldValues.containsKey(MONTH_OF_YEAR)) {
   987                 if (fieldValues.containsKey(DAY_OF_MONTH)) {
   983                 if (fieldValues.containsKey(DAY_OF_MONTH)) {
   988                     int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
   984                     return resolveYMD(fieldValues, resolverStyle);
   989                     int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
   990                     int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
       
   991                     return date(y, moy, dom);
       
   992                 }
   985                 }
   993                 if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) {
   986                 if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) {
   994                     if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) {
   987                     if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) {
   995                         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
   988                         return resolveYMAA(fieldValues, resolverStyle);
   996                         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
   997                         int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
       
   998                         int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH);
       
   999                         ChronoLocalDate<?> chronoDate = date(y, moy, 1);
       
  1000                         return chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
       
  1001                     }
   989                     }
  1002                     if (fieldValues.containsKey(DAY_OF_WEEK)) {
   990                     if (fieldValues.containsKey(DAY_OF_WEEK)) {
  1003                         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
   991                         return resolveYMAD(fieldValues, resolverStyle);
  1004                         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
  1005                         int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
       
  1006                         int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
       
  1007                         ChronoLocalDate<?> chronoDate = date(y, moy, 1);
       
  1008                         return chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
       
  1009                     }
   992                     }
  1010                 }
   993                 }
  1011             }
   994             }
  1012             if (fieldValues.containsKey(DAY_OF_YEAR)) {
   995             if (fieldValues.containsKey(DAY_OF_YEAR)) {
  1013                 int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
   996                 return resolveYD(fieldValues, resolverStyle);
  1014                 int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR);
       
  1015                 return dateYearDay(y, doy);
       
  1016             }
   997             }
  1017             if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) {
   998             if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) {
  1018                 if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) {
   999                 if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) {
  1019                     int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
  1000                     return resolveYAA(fieldValues, resolverStyle);
  1020                     int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
       
  1021                     int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR);
       
  1022                     ChronoLocalDate<?> chronoDate = dateYearDay(y, 1);
       
  1023                     return chronoDate.plus((aw - 1) * 7 + (ad - 1), ChronoUnit.DAYS);
       
  1024                 }
  1001                 }
  1025                 if (fieldValues.containsKey(DAY_OF_WEEK)) {
  1002                 if (fieldValues.containsKey(DAY_OF_WEEK)) {
  1026                     int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
  1003                     return resolveYAD(fieldValues, resolverStyle);
  1027                     int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
       
  1028                     int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
       
  1029                     ChronoLocalDate<?> chronoDate = dateYearDay(y, 1);
       
  1030                     return chronoDate.plus((aw - 1) * 7, ChronoUnit.DAYS).with(nextOrSame(DayOfWeek.of(dow)));
       
  1031                 }
  1004                 }
  1032             }
  1005             }
  1033         }
  1006         }
  1034         return null;
  1007         return null;
       
  1008     }
       
  1009 
       
  1010     void resolveProlepticMonth(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1011         Long pMonth = fieldValues.remove(PROLEPTIC_MONTH);
       
  1012         if (pMonth != null) {
       
  1013             if (resolverStyle != ResolverStyle.LENIENT) {
       
  1014                 PROLEPTIC_MONTH.checkValidValue(pMonth);
       
  1015             }
       
  1016             // first day-of-month is likely to be safest for setting proleptic-month
       
  1017             // cannot add to year zero, as not all chronologies have a year zero
       
  1018             ChronoLocalDate chronoDate = dateNow()
       
  1019                     .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth);
       
  1020             addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR));
       
  1021             addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR));
       
  1022         }
       
  1023     }
       
  1024 
       
  1025     ChronoLocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1026         Long yoeLong = fieldValues.remove(YEAR_OF_ERA);
       
  1027         if (yoeLong != null) {
       
  1028             Long eraLong = fieldValues.remove(ERA);
       
  1029             int yoe;
       
  1030             if (resolverStyle != ResolverStyle.LENIENT) {
       
  1031                 yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA);
       
  1032             } else {
       
  1033                 yoe = Math.toIntExact(yoeLong);
       
  1034             }
       
  1035             if (eraLong != null) {
       
  1036                 Era eraObj = eraOf(range(ERA).checkValidIntValue(eraLong, ERA));
       
  1037                 addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
       
  1038             } else {
       
  1039                 if (fieldValues.containsKey(YEAR)) {
       
  1040                     int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR);
       
  1041                     ChronoLocalDate chronoDate = dateYearDay(year, 1);
       
  1042                     addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe));
       
  1043                 } else if (resolverStyle == ResolverStyle.STRICT) {
       
  1044                     // do not invent era if strict
       
  1045                     // reinstate the field removed earlier, no cross-check issues
       
  1046                     fieldValues.put(YEAR_OF_ERA, yoeLong);
       
  1047                 } else {
       
  1048                     List<Era> eras = eras();
       
  1049                     if (eras.isEmpty()) {
       
  1050                         addFieldValue(fieldValues, YEAR, yoe);
       
  1051                     } else {
       
  1052                         Era eraObj = eras.get(eras.size() - 1);
       
  1053                         addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe));
       
  1054                     }
       
  1055                 }
       
  1056             }
       
  1057         } else if (fieldValues.containsKey(ERA)) {
       
  1058             range(ERA).checkValidValue(fieldValues.get(ERA), ERA);  // always validated
       
  1059         }
       
  1060         return null;
       
  1061     }
       
  1062 
       
  1063     ChronoLocalDate resolveYMD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1064         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1065         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1066             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
       
  1067             long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1);
       
  1068             return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS);
       
  1069         }
       
  1070         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
  1071         ValueRange domRange = range(DAY_OF_MONTH);
       
  1072         int dom = domRange.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH);
       
  1073         if (resolverStyle == ResolverStyle.SMART) {  // previous valid
       
  1074             try {
       
  1075                 return date(y, moy, dom);
       
  1076             } catch (DateTimeException ex) {
       
  1077                 return date(y, moy, 1).with(TemporalAdjuster.lastDayOfMonth());
       
  1078             }
       
  1079         }
       
  1080         return date(y, moy, dom);
       
  1081     }
       
  1082 
       
  1083     ChronoLocalDate resolveYD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1084         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1085         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1086             long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1);
       
  1087             return dateYearDay(y, 1).plus(days, DAYS);
       
  1088         }
       
  1089         int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR);
       
  1090         return dateYearDay(y, doy);  // smart is same as strict
       
  1091     }
       
  1092 
       
  1093     ChronoLocalDate resolveYMAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1094         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1095         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1096             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
       
  1097             long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
       
  1098             long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1);
       
  1099             return date(y, 1, 1).plus(months, MONTHS).plus(weeks, WEEKS).plus(days, DAYS);
       
  1100         }
       
  1101         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
  1102         int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
       
  1103         int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH);
       
  1104         ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
       
  1105         if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
       
  1106             throw new DateTimeException("Strict mode rejected resolved date as it is in a different month");
       
  1107         }
       
  1108         return date;
       
  1109     }
       
  1110 
       
  1111     ChronoLocalDate resolveYMAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1112         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1113         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1114             long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1);
       
  1115             long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1);
       
  1116             long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
       
  1117             return resolveAligned(date(y, 1, 1), months, weeks, dow);
       
  1118         }
       
  1119         int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR);
       
  1120         int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH);
       
  1121         int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
       
  1122         ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow)));
       
  1123         if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) {
       
  1124             throw new DateTimeException("Strict mode rejected resolved date as it is in a different month");
       
  1125         }
       
  1126         return date;
       
  1127     }
       
  1128 
       
  1129     ChronoLocalDate resolveYAA(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1130         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1131         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1132             long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
       
  1133             long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1);
       
  1134             return dateYearDay(y, 1).plus(weeks, WEEKS).plus(days, DAYS);
       
  1135         }
       
  1136         int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
       
  1137         int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR);
       
  1138         ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7 + (ad - 1), DAYS);
       
  1139         if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
       
  1140             throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
       
  1141         }
       
  1142         return date;
       
  1143     }
       
  1144 
       
  1145     ChronoLocalDate resolveYAD(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) {
       
  1146         int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR);
       
  1147         if (resolverStyle == ResolverStyle.LENIENT) {
       
  1148             long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1);
       
  1149             long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1);
       
  1150             return resolveAligned(dateYearDay(y, 1), 0, weeks, dow);
       
  1151         }
       
  1152         int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR);
       
  1153         int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK);
       
  1154         ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow)));
       
  1155         if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) {
       
  1156             throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
       
  1157         }
       
  1158         return date;
       
  1159     }
       
  1160 
       
  1161     ChronoLocalDate resolveAligned(ChronoLocalDate base, long months, long weeks, long dow) {
       
  1162         ChronoLocalDate date = base.plus(months, MONTHS).plus(weeks, WEEKS);
       
  1163         if (dow > 7) {
       
  1164             date = date.plus((dow - 1) / 7, WEEKS);
       
  1165             dow = ((dow - 1) % 7) + 1;
       
  1166         } else if (dow < 1) {
       
  1167             date = date.plus(Math.subtractExact(dow,  7) / 7, WEEKS);
       
  1168             dow = ((dow + 6) % 7) + 1;
       
  1169         }
       
  1170         return date.with(nextOrSame(DayOfWeek.of((int) dow)));
  1035     }
  1171     }
  1036 
  1172 
  1037     /**
  1173     /**
  1038      * Adds a field-value pair to the map, checking for conflicts.
  1174      * Adds a field-value pair to the map, checking for conflicts.
  1039      * <p>
  1175      * <p>