+ case UDAT_AM_PM_MIDNIGHT_NOON_FIELD:
+ {
+ const UnicodeString *toAppend = NULL;
+ int32_t hour = cal.get(UCAL_HOUR_OF_DAY, status);
+
+ // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
+ // For ICU 57 output of "midnight" is temporarily suppressed.
+
+ // For "midnight" and "noon":
+ // Time, as displayed, must be exactly noon or midnight.
+ // This means minutes and seconds, if present, must be zero.
+ if ((/*hour == 0 ||*/ hour == 12) &&
+ (!fHasMinute || cal.get(UCAL_MINUTE, status) == 0) &&
+ (!fHasSecond || cal.get(UCAL_SECOND, status) == 0)) {
+ // Stealing am/pm value to use as our array index.
+ // It works out: am/midnight are both 0, pm/noon are both 1,
+ // 12 am is 12 midnight, and 12 pm is 12 noon.
+ int32_t value = cal.get(UCAL_AM_PM, status);
+
+ if (count <= 3) {
+ toAppend = &fSymbols->fAbbreviatedDayPeriods[value];
+ } else if (count == 4 || count > 5) {
+ toAppend = &fSymbols->fWideDayPeriods[value];
+ } else { // count == 5
+ toAppend = &fSymbols->fNarrowDayPeriods[value];
+ }
+ }
+
+ // toAppend is NULL if time isn't exactly midnight or noon (as displayed).
+ // toAppend is bogus if time is midnight or noon, but no localized string exists.
+ // In either case, fall back to am/pm.
+ if (toAppend == NULL || toAppend->isBogus()) {
+ // Reformat with identical arguments except ch, now changed to 'a'.
+ subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
+ handler, cal, mutableNFs, status);
+ } else {
+ appendTo += *toAppend;
+ }
+
+ break;
+ }
+
+ case UDAT_FLEXIBLE_DAY_PERIOD_FIELD:
+ {
+ // TODO: Maybe fetch the DayperiodRules during initialization (instead of at the first
+ // loading of an instance) if a relevant pattern character (b or B) is used.
+ const DayPeriodRules *ruleSet = DayPeriodRules::getInstance(this->getSmpFmtLocale(), status);
+ if (U_FAILURE(status)) {
+ // Data doesn't conform to spec, therefore loading failed.
+ break;
+ }
+ if (ruleSet == NULL) {
+ // Data doesn't exist for the locale we're looking for.
+ // Falling back to am/pm.
+ subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
+ handler, cal, mutableNFs, status);
+ break;
+ }
+
+ // Get current display time.
+ int32_t hour = cal.get(UCAL_HOUR_OF_DAY, status);
+ int32_t minute = 0;
+ if (fHasMinute) {
+ minute = cal.get(UCAL_MINUTE, status);
+ }
+ int32_t second = 0;
+ if (fHasSecond) {
+ second = cal.get(UCAL_SECOND, status);
+ }
+
+ // Determine day period.
+ DayPeriodRules::DayPeriod periodType;
+ if (hour == 0 && minute == 0 && second == 0 && ruleSet->hasMidnight()) {
+ periodType = DayPeriodRules::DAYPERIOD_MIDNIGHT;
+ } else if (hour == 12 && minute == 0 && second == 0 && ruleSet->hasNoon()) {
+ periodType = DayPeriodRules::DAYPERIOD_NOON;
+ } else {
+ periodType = ruleSet->getDayPeriodForHour(hour);
+ }
+
+ // Rule set exists, therefore periodType can't be UNKNOWN.
+ // Get localized string.
+ U_ASSERT(periodType != DayPeriodRules::DAYPERIOD_UNKNOWN);
+ UnicodeString *toAppend = NULL;
+ int32_t index;
+
+ // Note: "midnight" can be ambiguous as to whether it refers to beginning of day or end of day.
+ // For ICU 57 output of "midnight" is temporarily suppressed.
+
+ if (periodType != DayPeriodRules::DAYPERIOD_AM &&
+ periodType != DayPeriodRules::DAYPERIOD_PM &&
+ periodType != DayPeriodRules::DAYPERIOD_MIDNIGHT) {
+ index = (int32_t)periodType;
+ if (count <= 3) {
+ toAppend = &fSymbols->fAbbreviatedDayPeriods[index]; // i.e. short
+ } else if (count == 4 || count > 5) {
+ toAppend = &fSymbols->fWideDayPeriods[index];
+ } else { // count == 5
+ toAppend = &fSymbols->fNarrowDayPeriods[index];
+ }
+ }
+
+ // Fallback schedule:
+ // Midnight/Noon -> General Periods -> AM/PM.
+
+ // Midnight/Noon -> General Periods.
+ if ((toAppend == NULL || toAppend->isBogus()) &&
+ (periodType == DayPeriodRules::DAYPERIOD_MIDNIGHT ||
+ periodType == DayPeriodRules::DAYPERIOD_NOON)) {
+ periodType = ruleSet->getDayPeriodForHour(hour);
+ index = (int32_t)periodType;
+
+ if (count <= 3) {
+ toAppend = &fSymbols->fAbbreviatedDayPeriods[index]; // i.e. short
+ } else if (count == 4 || count > 5) {
+ toAppend = &fSymbols->fWideDayPeriods[index];
+ } else { // count == 5
+ toAppend = &fSymbols->fNarrowDayPeriods[index];
+ }
+ }
+
+ // General Periods -> AM/PM.
+ if (periodType == DayPeriodRules::DAYPERIOD_AM ||
+ periodType == DayPeriodRules::DAYPERIOD_PM ||
+ toAppend->isBogus()) {
+ subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum,
+ handler, cal, mutableNFs, status);
+ }
+ else {
+ appendTo += *toAppend;
+ }
+
+ break;
+ }