jdk/src/share/classes/java/time/format/Parsed.java
changeset 17474 8c100beabcc0
parent 16852 60207b2b4b42
child 19030 32f129cb6351
equal deleted inserted replaced
17473:35cd9b3a98ff 17474:8c100beabcc0
    78 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
    78 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
    79 
    79 
    80 import java.time.DateTimeException;
    80 import java.time.DateTimeException;
    81 import java.time.LocalDate;
    81 import java.time.LocalDate;
    82 import java.time.LocalTime;
    82 import java.time.LocalTime;
       
    83 import java.time.Period;
    83 import java.time.ZoneId;
    84 import java.time.ZoneId;
    84 import java.time.chrono.ChronoLocalDate;
    85 import java.time.chrono.ChronoLocalDate;
    85 import java.time.chrono.Chronology;
    86 import java.time.chrono.Chronology;
    86 import java.time.temporal.ChronoField;
    87 import java.time.temporal.ChronoField;
    87 import java.time.temporal.TemporalAccessor;
    88 import java.time.temporal.TemporalAccessor;
   103  * support the necessary backtracking.
   104  * support the necessary backtracking.
   104  * <p>
   105  * <p>
   105  * Once parsing is completed, this class can be used as the resultant {@code TemporalAccessor}.
   106  * Once parsing is completed, this class can be used as the resultant {@code TemporalAccessor}.
   106  * In most cases, it is only exposed once the fields have been resolved.
   107  * In most cases, it is only exposed once the fields have been resolved.
   107  *
   108  *
   108  * <h3>Specification for implementors</h3>
   109  * @implSpec
   109  * This class is a mutable context intended for use from a single thread.
   110  * This class is a mutable context intended for use from a single thread.
   110  * Usage of the class is thread-safe within standard parsing as a new instance of this class
   111  * Usage of the class is thread-safe within standard parsing as a new instance of this class
   111  * is automatically created for each parse and parsing is single-threaded
   112  * is automatically created for each parse and parsing is single-threaded
   112  *
   113  *
   113  * @since 1.8
   114  * @since 1.8
   126     /**
   127     /**
   127      * The parsed chronology.
   128      * The parsed chronology.
   128      */
   129      */
   129     Chronology chrono;
   130     Chronology chrono;
   130     /**
   131     /**
       
   132      * Whether a leap-second is parsed.
       
   133      */
       
   134     boolean leapSecond;
       
   135     /**
   131      * The effective chronology.
   136      * The effective chronology.
   132      */
   137      */
   133     Chronology effectiveChrono;
   138     Chronology effectiveChrono;
   134     /**
   139     /**
   135      * The resolver style to use.
   140      * The resolver style to use.
   141     private ChronoLocalDate<?> date;
   146     private ChronoLocalDate<?> date;
   142     /**
   147     /**
   143      * The resolved time.
   148      * The resolved time.
   144      */
   149      */
   145     private LocalTime time;
   150     private LocalTime time;
       
   151     /**
       
   152      * The excess period from time-only parsing.
       
   153      */
       
   154     Period excessDays = Period.ZERO;
   146 
   155 
   147     /**
   156     /**
   148      * Creates an instance.
   157      * Creates an instance.
   149      */
   158      */
   150     Parsed() {
   159     Parsed() {
   157         // only copy fields used in parsing stage
   166         // only copy fields used in parsing stage
   158         Parsed cloned = new Parsed();
   167         Parsed cloned = new Parsed();
   159         cloned.fieldValues.putAll(this.fieldValues);
   168         cloned.fieldValues.putAll(this.fieldValues);
   160         cloned.zone = this.zone;
   169         cloned.zone = this.zone;
   161         cloned.chrono = this.chrono;
   170         cloned.chrono = this.chrono;
       
   171         cloned.leapSecond = this.leapSecond;
   162         return cloned;
   172         return cloned;
   163     }
   173     }
   164 
   174 
   165     //-----------------------------------------------------------------------
   175     //-----------------------------------------------------------------------
   166     @Override
   176     @Override
   230         this.resolverStyle = resolverStyle;
   240         this.resolverStyle = resolverStyle;
   231         chrono = effectiveChrono;
   241         chrono = effectiveChrono;
   232         resolveFields();
   242         resolveFields();
   233         resolveTimeLenient();
   243         resolveTimeLenient();
   234         crossCheck();
   244         crossCheck();
       
   245         resolvePeriod();
   235         return this;
   246         return this;
   236     }
   247     }
   237 
   248 
   238     //-----------------------------------------------------------------------
   249     //-----------------------------------------------------------------------
   239     private void resolveFields() {
   250     private void resolveFields() {
   306 
   317 
   307     //-----------------------------------------------------------------------
   318     //-----------------------------------------------------------------------
   308     private void resolveTimeFields() {
   319     private void resolveTimeFields() {
   309         // simplify fields
   320         // simplify fields
   310         if (fieldValues.containsKey(CLOCK_HOUR_OF_DAY)) {
   321         if (fieldValues.containsKey(CLOCK_HOUR_OF_DAY)) {
       
   322             // lenient allows anything, smart allows 0-24, strict allows 1-24
   311             long ch = fieldValues.remove(CLOCK_HOUR_OF_DAY);
   323             long ch = fieldValues.remove(CLOCK_HOUR_OF_DAY);
       
   324             if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
       
   325                 CLOCK_HOUR_OF_DAY.checkValidValue(ch);
       
   326             }
   312             updateCheckConflict(CLOCK_HOUR_OF_DAY, HOUR_OF_DAY, ch == 24 ? 0 : ch);
   327             updateCheckConflict(CLOCK_HOUR_OF_DAY, HOUR_OF_DAY, ch == 24 ? 0 : ch);
   313         }
   328         }
   314         if (fieldValues.containsKey(CLOCK_HOUR_OF_AMPM)) {
   329         if (fieldValues.containsKey(CLOCK_HOUR_OF_AMPM)) {
       
   330             // lenient allows anything, smart allows 0-12, strict allows 1-12
   315             long ch = fieldValues.remove(CLOCK_HOUR_OF_AMPM);
   331             long ch = fieldValues.remove(CLOCK_HOUR_OF_AMPM);
       
   332             if (resolverStyle == ResolverStyle.STRICT || (resolverStyle == ResolverStyle.SMART && ch != 0)) {
       
   333                 CLOCK_HOUR_OF_AMPM.checkValidValue(ch);
       
   334             }
   316             updateCheckConflict(CLOCK_HOUR_OF_AMPM, HOUR_OF_AMPM, ch == 12 ? 0 : ch);
   335             updateCheckConflict(CLOCK_HOUR_OF_AMPM, HOUR_OF_AMPM, ch == 12 ? 0 : ch);
   317         }
   336         }
   318         if (fieldValues.containsKey(AMPM_OF_DAY) && fieldValues.containsKey(HOUR_OF_AMPM)) {
   337         if (fieldValues.containsKey(AMPM_OF_DAY) && fieldValues.containsKey(HOUR_OF_AMPM)) {
   319             long ap = fieldValues.remove(AMPM_OF_DAY);
   338             long ap = fieldValues.remove(AMPM_OF_DAY);
   320             long hap = fieldValues.remove(HOUR_OF_AMPM);
   339             long hap = fieldValues.remove(HOUR_OF_AMPM);
   321             updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap);
   340             if (resolverStyle == ResolverStyle.LENIENT) {
       
   341                 updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, Math.addExact(Math.multiplyExact(ap, 12), hap));
       
   342             } else {  // STRICT or SMART
       
   343                 AMPM_OF_DAY.checkValidValue(ap);
       
   344                 HOUR_OF_AMPM.checkValidValue(ap);
       
   345                 updateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap);
       
   346             }
       
   347         }
       
   348         if (fieldValues.containsKey(NANO_OF_DAY)) {
       
   349             long nod = fieldValues.remove(NANO_OF_DAY);
       
   350             if (resolverStyle != ResolverStyle.LENIENT) {
       
   351                 NANO_OF_DAY.checkValidValue(nod);
       
   352             }
       
   353             updateCheckConflict(NANO_OF_DAY, HOUR_OF_DAY, nod / 3600_000_000_000L);
       
   354             updateCheckConflict(NANO_OF_DAY, MINUTE_OF_HOUR, (nod / 60_000_000_000L) % 60);
       
   355             updateCheckConflict(NANO_OF_DAY, SECOND_OF_MINUTE, (nod / 1_000_000_000L) % 60);
       
   356             updateCheckConflict(NANO_OF_DAY, NANO_OF_SECOND, nod % 1_000_000_000L);
   322         }
   357         }
   323         if (fieldValues.containsKey(MICRO_OF_DAY)) {
   358         if (fieldValues.containsKey(MICRO_OF_DAY)) {
   324             long cod = fieldValues.remove(MICRO_OF_DAY);
   359             long cod = fieldValues.remove(MICRO_OF_DAY);
       
   360             if (resolverStyle != ResolverStyle.LENIENT) {
       
   361                 MICRO_OF_DAY.checkValidValue(cod);
       
   362             }
   325             updateCheckConflict(MICRO_OF_DAY, SECOND_OF_DAY, cod / 1_000_000L);
   363             updateCheckConflict(MICRO_OF_DAY, SECOND_OF_DAY, cod / 1_000_000L);
   326             updateCheckConflict(MICRO_OF_DAY, MICRO_OF_SECOND, cod % 1_000_000L);
   364             updateCheckConflict(MICRO_OF_DAY, MICRO_OF_SECOND, cod % 1_000_000L);
   327         }
   365         }
   328         if (fieldValues.containsKey(MILLI_OF_DAY)) {
   366         if (fieldValues.containsKey(MILLI_OF_DAY)) {
   329             long lod = fieldValues.remove(MILLI_OF_DAY);
   367             long lod = fieldValues.remove(MILLI_OF_DAY);
       
   368             if (resolverStyle != ResolverStyle.LENIENT) {
       
   369                 MILLI_OF_DAY.checkValidValue(lod);
       
   370             }
   330             updateCheckConflict(MILLI_OF_DAY, SECOND_OF_DAY, lod / 1_000);
   371             updateCheckConflict(MILLI_OF_DAY, SECOND_OF_DAY, lod / 1_000);
   331             updateCheckConflict(MILLI_OF_DAY, MILLI_OF_SECOND, lod % 1_000);
   372             updateCheckConflict(MILLI_OF_DAY, MILLI_OF_SECOND, lod % 1_000);
   332         }
   373         }
   333         if (fieldValues.containsKey(SECOND_OF_DAY)) {
   374         if (fieldValues.containsKey(SECOND_OF_DAY)) {
   334             long sod = fieldValues.remove(SECOND_OF_DAY);
   375             long sod = fieldValues.remove(SECOND_OF_DAY);
       
   376             if (resolverStyle != ResolverStyle.LENIENT) {
       
   377                 SECOND_OF_DAY.checkValidValue(sod);
       
   378             }
   335             updateCheckConflict(SECOND_OF_DAY, HOUR_OF_DAY, sod / 3600);
   379             updateCheckConflict(SECOND_OF_DAY, HOUR_OF_DAY, sod / 3600);
   336             updateCheckConflict(SECOND_OF_DAY, MINUTE_OF_HOUR, (sod / 60) % 60);
   380             updateCheckConflict(SECOND_OF_DAY, MINUTE_OF_HOUR, (sod / 60) % 60);
   337             updateCheckConflict(SECOND_OF_DAY, SECOND_OF_MINUTE, sod % 60);
   381             updateCheckConflict(SECOND_OF_DAY, SECOND_OF_MINUTE, sod % 60);
   338         }
   382         }
   339         if (fieldValues.containsKey(MINUTE_OF_DAY)) {
   383         if (fieldValues.containsKey(MINUTE_OF_DAY)) {
   340             long mod = fieldValues.remove(MINUTE_OF_DAY);
   384             long mod = fieldValues.remove(MINUTE_OF_DAY);
       
   385             if (resolverStyle != ResolverStyle.LENIENT) {
       
   386                 MINUTE_OF_DAY.checkValidValue(mod);
       
   387             }
   341             updateCheckConflict(MINUTE_OF_DAY, HOUR_OF_DAY, mod / 60);
   388             updateCheckConflict(MINUTE_OF_DAY, HOUR_OF_DAY, mod / 60);
   342             updateCheckConflict(MINUTE_OF_DAY, MINUTE_OF_HOUR, mod % 60);
   389             updateCheckConflict(MINUTE_OF_DAY, MINUTE_OF_HOUR, mod % 60);
   343         }
   390         }
   344 
   391 
   345         // combine partial second fields strictly, leaving lenient expansion to later
   392         // combine partial second fields strictly, leaving lenient expansion to later
   346         if (fieldValues.containsKey(NANO_OF_SECOND)) {
   393         if (fieldValues.containsKey(NANO_OF_SECOND)) {
   347             long nos = fieldValues.get(NANO_OF_SECOND);
   394             long nos = fieldValues.get(NANO_OF_SECOND);
       
   395             if (resolverStyle != ResolverStyle.LENIENT) {
       
   396                 NANO_OF_SECOND.checkValidValue(nos);
       
   397             }
   348             if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   398             if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   349                 long cos = fieldValues.remove(MICRO_OF_SECOND);
   399                 long cos = fieldValues.remove(MICRO_OF_SECOND);
       
   400                 if (resolverStyle != ResolverStyle.LENIENT) {
       
   401                     MICRO_OF_SECOND.checkValidValue(cos);
       
   402                 }
   350                 nos = cos * 1000 + (nos % 1000);
   403                 nos = cos * 1000 + (nos % 1000);
   351                 updateCheckConflict(MICRO_OF_SECOND, NANO_OF_SECOND, nos);
   404                 updateCheckConflict(MICRO_OF_SECOND, NANO_OF_SECOND, nos);
   352             }
   405             }
   353             if (fieldValues.containsKey(MILLI_OF_SECOND)) {
   406             if (fieldValues.containsKey(MILLI_OF_SECOND)) {
   354                 long los = fieldValues.remove(MILLI_OF_SECOND);
   407                 long los = fieldValues.remove(MILLI_OF_SECOND);
       
   408                 if (resolverStyle != ResolverStyle.LENIENT) {
       
   409                     MILLI_OF_SECOND.checkValidValue(los);
       
   410                 }
   355                 updateCheckConflict(MILLI_OF_SECOND, NANO_OF_SECOND, los * 1_000_000L + (nos % 1_000_000L));
   411                 updateCheckConflict(MILLI_OF_SECOND, NANO_OF_SECOND, los * 1_000_000L + (nos % 1_000_000L));
   356             }
   412             }
   357         }
   413         }
   358 
   414 
   359         // convert to time if possible
   415         // convert to time if all four fields available (optimization)
   360         if (fieldValues.containsKey(NANO_OF_DAY)) {
       
   361             long nod = fieldValues.remove(NANO_OF_DAY);
       
   362             updateCheckConflict(LocalTime.ofNanoOfDay(nod));
       
   363         }
       
   364         if (fieldValues.containsKey(HOUR_OF_DAY) && fieldValues.containsKey(MINUTE_OF_HOUR) &&
   416         if (fieldValues.containsKey(HOUR_OF_DAY) && fieldValues.containsKey(MINUTE_OF_HOUR) &&
   365                 fieldValues.containsKey(SECOND_OF_MINUTE) && fieldValues.containsKey(NANO_OF_SECOND)) {
   417                 fieldValues.containsKey(SECOND_OF_MINUTE) && fieldValues.containsKey(NANO_OF_SECOND)) {
   366             int hodVal = HOUR_OF_DAY.checkValidIntValue(fieldValues.remove(HOUR_OF_DAY));
   418             long hod = fieldValues.remove(HOUR_OF_DAY);
   367             int mohVal = MINUTE_OF_HOUR.checkValidIntValue(fieldValues.remove(MINUTE_OF_HOUR));
   419             long moh = fieldValues.remove(MINUTE_OF_HOUR);
   368             int somVal = SECOND_OF_MINUTE.checkValidIntValue(fieldValues.remove(SECOND_OF_MINUTE));
   420             long som = fieldValues.remove(SECOND_OF_MINUTE);
   369             int nosVal = NANO_OF_SECOND.checkValidIntValue(fieldValues.remove(NANO_OF_SECOND));
   421             long nos = fieldValues.remove(NANO_OF_SECOND);
   370             updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal));
   422             resolveTime(hod, moh, som, nos);
   371         }
   423         }
   372     }
   424     }
   373 
   425 
   374     private void resolveTimeLenient() {
   426     private void resolveTimeLenient() {
   375         // leniently create a time from incomplete information
   427         // leniently create a time from incomplete information
   376         // done after everything else as it creates information from nothing
   428         // done after everything else as it creates information from nothing
   377         // which would break updateCheckConflict(field)
   429         // which would break updateCheckConflict(field)
   378 
   430 
   379         if (time == null) {
   431         if (time == null) {
   380             // can only get here if NANO_OF_SECOND not present
   432             // NANO_OF_SECOND merged with MILLI/MICRO above
   381             if (fieldValues.containsKey(MILLI_OF_SECOND)) {
   433             if (fieldValues.containsKey(MILLI_OF_SECOND)) {
   382                 long los = fieldValues.remove(MILLI_OF_SECOND);
   434                 long los = fieldValues.remove(MILLI_OF_SECOND);
   383                 if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   435                 if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   384                     // merge milli-of-second and micro-of-second for better error message
   436                     // merge milli-of-second and micro-of-second for better error message
   385                     long cos = los * 1_000 + (fieldValues.get(MICRO_OF_SECOND) % 1_000);
   437                     long cos = los * 1_000 + (fieldValues.get(MICRO_OF_SECOND) % 1_000);
   393             } else if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   445             } else if (fieldValues.containsKey(MICRO_OF_SECOND)) {
   394                 // convert micro-of-second to nano-of-second
   446                 // convert micro-of-second to nano-of-second
   395                 long cos = fieldValues.remove(MICRO_OF_SECOND);
   447                 long cos = fieldValues.remove(MICRO_OF_SECOND);
   396                 fieldValues.put(NANO_OF_SECOND, cos * 1_000L);
   448                 fieldValues.put(NANO_OF_SECOND, cos * 1_000L);
   397             }
   449             }
   398         }
   450 
   399 
   451             // merge hour/minute/second/nano leniently
   400         // merge hour/minute/second/nano leniently
   452             Long hod = fieldValues.get(HOUR_OF_DAY);
   401         Long hod = fieldValues.get(HOUR_OF_DAY);
   453             if (hod != null) {
   402         if (hod != null) {
   454                 Long moh = fieldValues.get(MINUTE_OF_HOUR);
   403             int hodVal = HOUR_OF_DAY.checkValidIntValue(hod);
   455                 Long som = fieldValues.get(SECOND_OF_MINUTE);
   404             Long moh = fieldValues.get(MINUTE_OF_HOUR);
   456                 Long nos = fieldValues.get(NANO_OF_SECOND);
   405             Long som = fieldValues.get(SECOND_OF_MINUTE);
   457 
   406             Long nos = fieldValues.get(NANO_OF_SECOND);
   458                 // check for invalid combinations that cannot be defaulted
   407 
       
   408             // check for invalid combinations that cannot be defaulted
       
   409             if (time == null) {
       
   410                 if ((moh == null && (som != null || nos != null)) ||
   459                 if ((moh == null && (som != null || nos != null)) ||
   411                         (moh != null && som == null && nos != null)) {
   460                         (moh != null && som == null && nos != null)) {
   412                     return;
   461                     return;
   413                 }
   462                 }
   414             }
   463 
   415 
   464                 // default as necessary and build time
   416             // default as necessary and build time
   465                 long mohVal = (moh != null ? moh : 0);
   417             int mohVal = (moh != null ? MINUTE_OF_HOUR.checkValidIntValue(moh) : (time != null ? time.getMinute() : 0));
   466                 long somVal = (som != null ? som : 0);
   418             int somVal = (som != null ? SECOND_OF_MINUTE.checkValidIntValue(som) : (time != null ? time.getSecond() : 0));
   467                 long nosVal = (nos != null ? nos : 0);
   419             int nosVal = (nos != null ? NANO_OF_SECOND.checkValidIntValue(nos) : (time != null ? time.getNano() : 0));
   468                 resolveTime(hod, mohVal, somVal, nosVal);
   420             updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal));
   469                 fieldValues.remove(HOUR_OF_DAY);
   421             fieldValues.remove(HOUR_OF_DAY);
   470                 fieldValues.remove(MINUTE_OF_HOUR);
   422             fieldValues.remove(MINUTE_OF_HOUR);
   471                 fieldValues.remove(SECOND_OF_MINUTE);
   423             fieldValues.remove(SECOND_OF_MINUTE);
   472                 fieldValues.remove(NANO_OF_SECOND);
   424             fieldValues.remove(NANO_OF_SECOND);
   473             }
   425         }
   474         }
   426     }
   475 
   427 
   476         // validate remaining
   428     private void updateCheckConflict(LocalTime lt) {
   477         if (resolverStyle != ResolverStyle.LENIENT && fieldValues.size() > 0) {
       
   478             for (Entry<TemporalField, Long> entry : fieldValues.entrySet()) {
       
   479                 TemporalField field = entry.getKey();
       
   480                 if (field instanceof ChronoField && field.isTimeBased()) {
       
   481                     ((ChronoField) field).checkValidValue(entry.getValue());
       
   482                 }
       
   483             }
       
   484         }
       
   485     }
       
   486 
       
   487     private void resolveTime(long hod, long moh, long som, long nos) {
       
   488         if (resolverStyle == ResolverStyle.LENIENT) {
       
   489             long totalNanos = Math.multiplyExact(hod, 3600_000_000_000L);
       
   490             totalNanos = Math.addExact(totalNanos, Math.multiplyExact(moh, 60_000_000_000L));
       
   491             totalNanos = Math.addExact(totalNanos, Math.multiplyExact(som, 1_000_000_000L));
       
   492             totalNanos = Math.addExact(totalNanos, nos);
       
   493             int excessDays = (int) Math.floorDiv(totalNanos, 86400_000_000_000L);  // safe int cast
       
   494             long nod = Math.floorMod(totalNanos, 86400_000_000_000L);
       
   495             updateCheckConflict(LocalTime.ofNanoOfDay(nod), Period.ofDays(excessDays));
       
   496         } else {  // STRICT or SMART
       
   497             int mohVal = MINUTE_OF_HOUR.checkValidIntValue(moh);
       
   498             int nosVal = NANO_OF_SECOND.checkValidIntValue(nos);
       
   499             // handle 24:00 end of day
       
   500             if (resolverStyle == ResolverStyle.SMART && hod == 24 && mohVal == 0 && som == 0 && nosVal == 0) {
       
   501                 updateCheckConflict(LocalTime.MIDNIGHT, Period.ofDays(1));
       
   502             } else {
       
   503                 int hodVal = HOUR_OF_DAY.checkValidIntValue(hod);
       
   504                 int somVal = SECOND_OF_MINUTE.checkValidIntValue(som);
       
   505                 updateCheckConflict(LocalTime.of(hodVal, mohVal, somVal, nosVal), Period.ZERO);
       
   506             }
       
   507         }
       
   508     }
       
   509 
       
   510     private void resolvePeriod() {
       
   511         // add whole days if we have both date and time
       
   512         if (date != null && time != null && excessDays.isZero() == false) {
       
   513             date = date.plus(excessDays);
       
   514             excessDays = Period.ZERO;
       
   515         }
       
   516     }
       
   517 
       
   518     private void updateCheckConflict(LocalTime timeToSet, Period periodToSet) {
   429         if (time != null) {
   519         if (time != null) {
   430             if (lt != null && time.equals(lt) == false) {
   520             if (time.equals(timeToSet) == false) {
   431                 throw new DateTimeException("Conflict found: Fields resolved to two different times: " + time + " " + lt);
   521                 throw new DateTimeException("Conflict found: Fields resolved to different times: " + time + " " + timeToSet);
       
   522             }
       
   523             if (excessDays.isZero() == false && periodToSet.isZero() == false && excessDays.equals(periodToSet) == false) {
       
   524                 throw new DateTimeException("Conflict found: Fields resolved to different excess periods: " + excessDays + " " + periodToSet);
       
   525             } else {
       
   526                 excessDays = periodToSet;
   432             }
   527             }
   433         } else {
   528         } else {
   434             time = lt;
   529             time = timeToSet;
       
   530             excessDays = periodToSet;
   435         }
   531         }
   436     }
   532     }
   437 
   533 
   438     //-----------------------------------------------------------------------
   534     //-----------------------------------------------------------------------
   439     private void crossCheck() {
   535     private void crossCheck() {