private ParseResult <LocalTime> DetermineHour(PatternFields usedFields, string text, out int hour) { hour = 0; if (usedFields.HasAny(PatternFields.Hours24)) { if (usedFields.HasAll(PatternFields.Hours12 | PatternFields.Hours24)) { if (Hours12 % 12 != Hours24 % 12) { return(ParseResult <LocalTime> .InconsistentValues(text, 'H', 'h')); } } if (usedFields.HasAny(PatternFields.AmPm)) { if (Hours24 / 12 != AmPm) { return(ParseResult <LocalTime> .InconsistentValues(text, 'H', 't')); } } hour = Hours24; return(null); } // Okay, it's definitely valid - but we've still got 8 possibilities for what's been specified. switch (usedFields & (PatternFields.Hours12 | PatternFields.AmPm)) { case PatternFields.Hours12 | PatternFields.AmPm: hour = (Hours12 % 12) + AmPm * 12; break; case PatternFields.Hours12: // Preserve AM/PM from template value hour = (Hours12 % 12) + (TemplateValue.Hour / 12) * 12; break; case PatternFields.AmPm: // Preserve 12-hour hour of day from template value, use specified AM/PM hour = (TemplateValue.Hour % 12) + AmPm * 12; break; case 0: hour = TemplateValue.Hour; break; } return(null); }
/// <summary> /// Calculates the value from the parsed pieces. /// </summary> internal override ParseResult <LocalTime> CalculateValue(PatternFields usedFields, string text) { if (usedFields.HasAny(PatternFields.EmbeddedTime)) { return(ParseResult <LocalTime> .ForValue(LocalTime.FromHourMinuteSecondNanosecond(Hours24, Minutes, Seconds, FractionalSeconds))); } if (AmPm == 2) { AmPm = TemplateValue.Hour / 12; } ParseResult <LocalTime> failure = DetermineHour(usedFields, text, out int hour); if (failure != null) { return(failure); } int minutes = usedFields.HasAny(PatternFields.Minutes) ? Minutes : TemplateValue.Minute; int seconds = usedFields.HasAny(PatternFields.Seconds) ? Seconds : TemplateValue.Second; int fraction = usedFields.HasAny(PatternFields.FractionalSeconds) ? FractionalSeconds : TemplateValue.NanosecondOfSecond; return(ParseResult <LocalTime> .ForValue(LocalTime.FromHourMinuteSecondNanosecond(hour, minutes, seconds, fraction))); }
internal override ParseResult <LocalDate> CalculateValue(PatternFields usedFields, string text) { if (usedFields.HasAny(PatternFields.EmbeddedDate)) { return(ParseResult <LocalDate> .ForValue(new LocalDate(Year, MonthOfYearNumeric, DayOfMonth, Calendar))); } // This will set Year if necessary ParseResult <LocalDate> failure = DetermineYear(usedFields, text); if (failure != null) { return(failure); } // This will set MonthOfYearNumeric if necessary failure = DetermineMonth(usedFields, text); if (failure != null) { return(failure); } int day = usedFields.HasAny(PatternFields.DayOfMonth) ? DayOfMonth : TemplateValue.Day; if (day > Calendar.GetDaysInMonth(Year, MonthOfYearNumeric)) { return(ParseResult <LocalDate> .DayOfMonthOutOfRange(text, day, MonthOfYearNumeric, Year)); } LocalDate value = new LocalDate(Year, MonthOfYearNumeric, day, Calendar); if (usedFields.HasAny(PatternFields.DayOfWeek) && DayOfWeek != value.DayOfWeek) { return(ParseResult <LocalDate> .InconsistentDayOfWeekTextValue(text)); } // FIXME: If we got an era, check that the resulting date really lies within that era. return(ParseResult <LocalDate> .ForValue(value)); }
internal override ParseResult <AnnualDate> CalculateValue(PatternFields usedFields, string text) { // This will set MonthOfYearNumeric if necessary var failure = DetermineMonth(usedFields, text); if (failure != null) { return(failure); } int day = usedFields.HasAny(PatternFields.DayOfMonth) ? DayOfMonth : TemplateValue.Day; // Validate for the year 2000, just like the AnnualDate constructor does. if (day > CalendarSystem.Iso.GetDaysInMonth(2000, MonthOfYearNumeric)) { return(ParseResult <AnnualDate> .DayOfMonthOutOfRangeNoYear(text, day, MonthOfYearNumeric)); } return(ParseResult <AnnualDate> .ForValue(new AnnualDate(MonthOfYearNumeric, day))); }
/// <summary> /// Work out the year, based on fields of: /// - Year /// - YearOfEra /// - YearTwoDigits (implies YearOfEra) /// - Era /// /// If the year is specified, that trumps everything else - any other fields /// are just used for checking. /// /// If nothing is specified, the year of the template value is used. /// /// If just the era is specified, the year of the template value is used, /// and the specified era is checked against it. (Hopefully no-one will /// expect to get useful information from a format string with era but no year...) /// /// Otherwise, we have the year of era (possibly only two digits) and possibly the /// era. If the era isn't specified, take it from the template value. /// Finally, if we only have two digits, then use either the century of the template /// value or the previous century if the year-of-era is greater than TwoDigitYearMax... /// and if the template value isn't in the first century already. /// /// Phew. /// </summary> private ParseResult <LocalDate> DetermineYear(PatternFields usedFields, string text) { if (usedFields.HasAny(PatternFields.Year)) { if (Year > Calendar.MaxYear || Year < Calendar.MinYear) { return(ParseResult <LocalDate> .FieldValueOutOfRangePostParse(text, Year, 'u')); } if (usedFields.HasAny(PatternFields.Era) && Era != Calendar.GetEra(Year)) { return(ParseResult <LocalDate> .InconsistentValues(text, 'g', 'u')); } if (usedFields.HasAny(PatternFields.YearOfEra)) { int yearOfEraFromYear = Calendar.GetYearOfEra(Year); if (usedFields.HasAny(PatternFields.YearTwoDigits)) { // We're only checking the last two digits yearOfEraFromYear = yearOfEraFromYear % 100; } if (yearOfEraFromYear != YearOfEra) { return(ParseResult <LocalDate> .InconsistentValues(text, 'y', 'u')); } } return(null); } // Use the year from the template value, possibly checking the era. if (!usedFields.HasAny(PatternFields.YearOfEra)) { Year = TemplateValue.Year; return(usedFields.HasAny(PatternFields.Era) && Era != Calendar.GetEra(Year) ? ParseResult <LocalDate> .InconsistentValues(text, 'g', 'u') : null); } if (!usedFields.HasAny(PatternFields.Era)) { Era = TemplateValue.Era; } if (usedFields.HasAny(PatternFields.YearTwoDigits)) { int century = TemplateValue.YearOfEra / 100; if (YearOfEra > TwoDigitYearMax && century > 1) { century--; } YearOfEra += century * 100; } if (YearOfEra < Calendar.GetMinYearOfEra(Era) || YearOfEra > Calendar.GetMaxYearOfEra(Era)) { return(ParseResult <LocalDate> .YearOfEraOutOfRange(text, YearOfEra, Era, Calendar)); } Year = Calendar.GetAbsoluteYear(YearOfEra, Era); return(null); }