private void ResolveTime(long hod, long moh, long som, long nos) { if (ResolverStyle == ResolverStyle.LENIENT) { long totalNanos = Math.MultiplyExact(hod, 3600_000_000_000L); totalNanos = Math.AddExact(totalNanos, Math.MultiplyExact(moh, 60_000_000_000L)); totalNanos = Math.AddExact(totalNanos, Math.MultiplyExact(som, 1_000_000_000L)); totalNanos = Math.AddExact(totalNanos, nos); int excessDays = (int)Math.FloorDiv(totalNanos, 86400_000_000_000L); // safe int cast long nod = Math.FloorMod(totalNanos, 86400_000_000_000L); UpdateCheckConflict(LocalTime.OfNanoOfDay(nod), Period.OfDays(excessDays)); } // STRICT or SMART else { int mohVal = MINUTE_OF_HOUR.checkValidIntValue(moh); int nosVal = NANO_OF_SECOND.checkValidIntValue(nos); // handle 24:00 end of day if (ResolverStyle == ResolverStyle.SMART && hod == 24 && mohVal == 0 && som == 0 && nosVal == 0) { UpdateCheckConflict(LocalTime.MIDNIGHT, Period.OfDays(1)); } else { int hodVal = HOUR_OF_DAY.checkValidIntValue(hod); int somVal = SECOND_OF_MINUTE.checkValidIntValue(som); UpdateCheckConflict(LocalTime.Of(hodVal, mohVal, somVal, nosVal), Period.ZERO); } } }
//----------------------------------------------------------------------- private void ResolveTimeFields() { // simplify fields if (FieldValues.ContainsKey(CLOCK_HOUR_OF_DAY)) { // lenient allows anything, smart allows 0-24, strict allows 1-24 long ch = FieldValues.Remove(CLOCK_HOUR_OF_DAY); if (ResolverStyle == ResolverStyle.STRICT || (ResolverStyle == ResolverStyle.SMART && ch != 0)) { CLOCK_HOUR_OF_DAY.checkValidValue(ch); } UpdateCheckConflict(CLOCK_HOUR_OF_DAY, HOUR_OF_DAY, ch == 24 ? 0 : ch); } if (FieldValues.ContainsKey(CLOCK_HOUR_OF_AMPM)) { // lenient allows anything, smart allows 0-12, strict allows 1-12 long ch = FieldValues.Remove(CLOCK_HOUR_OF_AMPM); if (ResolverStyle == ResolverStyle.STRICT || (ResolverStyle == ResolverStyle.SMART && ch != 0)) { CLOCK_HOUR_OF_AMPM.checkValidValue(ch); } UpdateCheckConflict(CLOCK_HOUR_OF_AMPM, HOUR_OF_AMPM, ch == 12 ? 0 : ch); } if (FieldValues.ContainsKey(AMPM_OF_DAY) && FieldValues.ContainsKey(HOUR_OF_AMPM)) { long ap = FieldValues.Remove(AMPM_OF_DAY); long hap = FieldValues.Remove(HOUR_OF_AMPM); if (ResolverStyle == ResolverStyle.LENIENT) { UpdateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, Math.AddExact(Math.MultiplyExact(ap, 12), hap)); } // STRICT or SMART else { AMPM_OF_DAY.checkValidValue(ap); HOUR_OF_AMPM.checkValidValue(ap); UpdateCheckConflict(AMPM_OF_DAY, HOUR_OF_DAY, ap * 12 + hap); } } if (FieldValues.ContainsKey(NANO_OF_DAY)) { long nod = FieldValues.Remove(NANO_OF_DAY); if (ResolverStyle != ResolverStyle.LENIENT) { NANO_OF_DAY.checkValidValue(nod); } UpdateCheckConflict(NANO_OF_DAY, HOUR_OF_DAY, nod / 3600_000_000_000L); UpdateCheckConflict(NANO_OF_DAY, MINUTE_OF_HOUR, (nod / 60_000_000_000L) % 60); UpdateCheckConflict(NANO_OF_DAY, SECOND_OF_MINUTE, (nod / 1_000_000_000L) % 60); UpdateCheckConflict(NANO_OF_DAY, NANO_OF_SECOND, nod % 1_000_000_000L); } if (FieldValues.ContainsKey(MICRO_OF_DAY)) { long cod = FieldValues.Remove(MICRO_OF_DAY); if (ResolverStyle != ResolverStyle.LENIENT) { MICRO_OF_DAY.checkValidValue(cod); } UpdateCheckConflict(MICRO_OF_DAY, SECOND_OF_DAY, cod / 1_000_000L); UpdateCheckConflict(MICRO_OF_DAY, MICRO_OF_SECOND, cod % 1_000_000L); } if (FieldValues.ContainsKey(MILLI_OF_DAY)) { long lod = FieldValues.Remove(MILLI_OF_DAY); if (ResolverStyle != ResolverStyle.LENIENT) { MILLI_OF_DAY.checkValidValue(lod); } UpdateCheckConflict(MILLI_OF_DAY, SECOND_OF_DAY, lod / 1000); UpdateCheckConflict(MILLI_OF_DAY, MILLI_OF_SECOND, lod % 1000); } if (FieldValues.ContainsKey(SECOND_OF_DAY)) { long sod = FieldValues.Remove(SECOND_OF_DAY); if (ResolverStyle != ResolverStyle.LENIENT) { SECOND_OF_DAY.checkValidValue(sod); } UpdateCheckConflict(SECOND_OF_DAY, HOUR_OF_DAY, sod / 3600); UpdateCheckConflict(SECOND_OF_DAY, MINUTE_OF_HOUR, (sod / 60) % 60); UpdateCheckConflict(SECOND_OF_DAY, SECOND_OF_MINUTE, sod % 60); } if (FieldValues.ContainsKey(MINUTE_OF_DAY)) { long mod = FieldValues.Remove(MINUTE_OF_DAY); if (ResolverStyle != ResolverStyle.LENIENT) { MINUTE_OF_DAY.checkValidValue(mod); } UpdateCheckConflict(MINUTE_OF_DAY, HOUR_OF_DAY, mod / 60); UpdateCheckConflict(MINUTE_OF_DAY, MINUTE_OF_HOUR, mod % 60); } // combine partial second fields strictly, leaving lenient expansion to later if (FieldValues.ContainsKey(NANO_OF_SECOND)) { long nos = FieldValues[NANO_OF_SECOND]; if (ResolverStyle != ResolverStyle.LENIENT) { NANO_OF_SECOND.checkValidValue(nos); } if (FieldValues.ContainsKey(MICRO_OF_SECOND)) { long cos = FieldValues.Remove(MICRO_OF_SECOND); if (ResolverStyle != ResolverStyle.LENIENT) { MICRO_OF_SECOND.checkValidValue(cos); } nos = cos * 1000 + (nos % 1000); UpdateCheckConflict(MICRO_OF_SECOND, NANO_OF_SECOND, nos); } if (FieldValues.ContainsKey(MILLI_OF_SECOND)) { long los = FieldValues.Remove(MILLI_OF_SECOND); if (ResolverStyle != ResolverStyle.LENIENT) { MILLI_OF_SECOND.checkValidValue(los); } UpdateCheckConflict(MILLI_OF_SECOND, NANO_OF_SECOND, los * 1_000_000L + (nos % 1_000_000L)); } } // convert to time if all four fields available (optimization) if (FieldValues.ContainsKey(HOUR_OF_DAY) && FieldValues.ContainsKey(MINUTE_OF_HOUR) && FieldValues.ContainsKey(SECOND_OF_MINUTE) && FieldValues.ContainsKey(NANO_OF_SECOND)) { long hod = FieldValues.Remove(HOUR_OF_DAY); long moh = FieldValues.Remove(MINUTE_OF_HOUR); long som = FieldValues.Remove(SECOND_OF_MINUTE); long nos = FieldValues.Remove(NANO_OF_SECOND); ResolveTime(hod, moh, som, nos); } }