ICU-21099 udat_toCalendarDateField should handle all UDateFormatFields and out of range
This commit is contained in:
parent
a951ab59c7
commit
d39899350d
@ -82,13 +82,18 @@ static UCalendarDateFields gDateFieldMapping[] = {
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_FIELD = 32 (also UCAL_DST_OFFSET)
|
||||
UCAL_ZONE_OFFSET, // UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33 (also UCAL_DST_OFFSET)
|
||||
UCAL_EXTENDED_YEAR, // UDAT_RELATED_YEAR_FIELD = 34 (not an exact match)
|
||||
UCAL_FIELD_COUNT, // UDAT_FIELD_COUNT = 35
|
||||
UCAL_FIELD_COUNT, // UDAT_AM_PM_MIDNIGHT_NOON_FIELD=35 (no match)
|
||||
UCAL_FIELD_COUNT, // UDAT_FLEXIBLE_DAY_PERIOD_FIELD=36 (no match)
|
||||
UCAL_FIELD_COUNT, // UDAT_TIME_SEPARATOR_FIELD = 37 (no match)
|
||||
// UDAT_FIELD_COUNT = 38 as of ICU 67
|
||||
// UCAL_IS_LEAP_MONTH is not the target of a mapping
|
||||
};
|
||||
|
||||
U_CAPI UCalendarDateFields U_EXPORT2
|
||||
udat_toCalendarDateField(UDateFormatField field) {
|
||||
return gDateFieldMapping[field];
|
||||
static_assert(UDAT_FIELD_COUNT == UPRV_LENGTHOF(gDateFieldMapping),
|
||||
"UDateFormatField and gDateFieldMapping should have the same number of entries and be kept in sync.");
|
||||
return (field >= UDAT_ERA_FIELD && field < UPRV_LENGTHOF(gDateFieldMapping))? gDateFieldMapping[field]: UCAL_FIELD_COUNT;
|
||||
}
|
||||
|
||||
/* For now- one opener. */
|
||||
|
@ -832,10 +832,24 @@ typedef enum UDateFormatField {
|
||||
|
||||
/**
|
||||
* Maps from a UDateFormatField to the corresponding UCalendarDateFields.
|
||||
* Note: since the mapping is many-to-one, there is no inverse mapping.
|
||||
*
|
||||
* Note 1: Since the mapping is many-to-one, there is no inverse mapping.
|
||||
*
|
||||
* Note 2: There is no UErrorCode parameter, so in case of error (UDateFormatField is
|
||||
* unknown or has no corresponding UCalendarDateFields value), the function returns the
|
||||
* current value of UCAL_FIELD_COUNT. However, that value may change from release to
|
||||
* release and is consequently deprecated. For a future-proof runtime way of checking
|
||||
* for errors:
|
||||
* a) First save the value returned by the function when it is passed an invalid value
|
||||
* such as "(UDateFormatField)-1".
|
||||
* b) Then, to test for errors when passing some other UDateFormatField value, check
|
||||
* whether the function returns that saved value.
|
||||
*
|
||||
* @param field the UDateFormatField.
|
||||
* @return the UCalendarDateField. This will be UCAL_FIELD_COUNT in case
|
||||
* of error (e.g., the input field is UDAT_FIELD_COUNT).
|
||||
* @return the UCalendarDateField. In case of error (UDateFormatField is unknown or has
|
||||
* no corresponding UCalendarDateFields value) this will be the current value of
|
||||
* UCAL_FIELD_COUNT, but that value may change from release to release.
|
||||
* See Note 2 above.
|
||||
* @stable ICU 4.4
|
||||
*/
|
||||
U_CAPI UCalendarDateFields U_EXPORT2
|
||||
|
@ -43,6 +43,7 @@ static void TestCalendarDateParse(void);
|
||||
static void TestParseErrorReturnValue(void);
|
||||
static void TestFormatForFields(void);
|
||||
static void TestForceGannenNumbering(void);
|
||||
static void TestMapDateToCalFields(void);
|
||||
|
||||
void addDateForTest(TestNode** root);
|
||||
|
||||
@ -63,6 +64,7 @@ void addDateForTest(TestNode** root)
|
||||
TESTCASE(TestParseErrorReturnValue);
|
||||
TESTCASE(TestFormatForFields);
|
||||
TESTCASE(TestForceGannenNumbering);
|
||||
TESTCASE(TestMapDateToCalFields);
|
||||
}
|
||||
/* Testing the DateFormat API */
|
||||
static void TestDateFormat()
|
||||
@ -1905,4 +1907,35 @@ static void TestForceGannenNumbering(void) {
|
||||
udatpg_close(dtpgen);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
UChar patternChar; // for future use
|
||||
UDateFormatField dateField;
|
||||
UCalendarDateFields calField;
|
||||
} PatternCharToFieldsItem;
|
||||
|
||||
static const PatternCharToFieldsItem patCharToFieldsItems[] = {
|
||||
{ u'G', UDAT_ERA_FIELD, UCAL_ERA },
|
||||
{ u'y', UDAT_YEAR_FIELD, UCAL_YEAR },
|
||||
{ u'Y', UDAT_YEAR_WOY_FIELD, UCAL_YEAR_WOY },
|
||||
{ u'Q', UDAT_QUARTER_FIELD, UCAL_MONTH },
|
||||
{ u'H', UDAT_HOUR_OF_DAY0_FIELD, UCAL_HOUR_OF_DAY },
|
||||
{ u'r', UDAT_RELATED_YEAR_FIELD, UCAL_EXTENDED_YEAR },
|
||||
{ u'B', UDAT_FLEXIBLE_DAY_PERIOD_FIELD, UCAL_FIELD_COUNT },
|
||||
{ u'$', UDAT_FIELD_COUNT, UCAL_FIELD_COUNT },
|
||||
{ 0xFFFF, (UDateFormatField)-1, UCAL_FIELD_COUNT }, // patternChar ignored here
|
||||
{ (UChar)0, (UDateFormatField)0, (UCalendarDateFields)0 } // terminator
|
||||
};
|
||||
|
||||
static void TestMapDateToCalFields(void){
|
||||
const PatternCharToFieldsItem* itemPtr;
|
||||
for ( itemPtr=patCharToFieldsItems; itemPtr->patternChar!=(UChar)0; itemPtr++) {
|
||||
UCalendarDateFields calField = udat_toCalendarDateField(itemPtr->dateField);
|
||||
if (calField != itemPtr->calField) {
|
||||
log_err("for pattern char 0x%04X, dateField %d, expect calField %d and got %d\n",
|
||||
itemPtr->patternChar, itemPtr->dateField, itemPtr->calField, calField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
Loading…
Reference in New Issue
Block a user