parent
8fda72f6d8
commit
923ec1ad30
@ -687,6 +687,22 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro
|
||||
}
|
||||
}
|
||||
|
||||
UDateFormatHourCycle
|
||||
DateTimePatternGenerator::getDefaultHourCycle(UErrorCode& /*status*/) const {
|
||||
switch(fDefaultHourFormatChar) {
|
||||
case CAP_K:
|
||||
return UDAT_HOUR_CYCLE_11;
|
||||
case LOW_H:
|
||||
return UDAT_HOUR_CYCLE_12;
|
||||
case CAP_H:
|
||||
return UDAT_HOUR_CYCLE_23;
|
||||
case LOW_K:
|
||||
return UDAT_HOUR_CYCLE_24;
|
||||
default:
|
||||
UPRV_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
||||
UnicodeString
|
||||
DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode&
|
||||
/*status*/) {
|
||||
|
@ -291,4 +291,9 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg,
|
||||
return result.getBuffer();
|
||||
}
|
||||
|
||||
U_CAPI UDateFormatHourCycle U_EXPORT2
|
||||
udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode) {
|
||||
return ((const DateTimePatternGenerator *)dtpg)->getDefaultHourCycle(*pErrorCode);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -483,6 +483,17 @@ public:
|
||||
*/
|
||||
const UnicodeString& getDecimal() const;
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Get the default hour cycle.
|
||||
* @param status Output param set to success/failure code on exit,
|
||||
* which must not indicate a failure before the function call.
|
||||
* @return the default hour cycle.
|
||||
* @draft ICU 67
|
||||
*/
|
||||
UDateFormatHourCycle getDefaultHourCycle(UErrorCode& status) const;
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
/**
|
||||
* ICU "poor man's RTTI", returns a UClassID for the actual class.
|
||||
*
|
||||
|
@ -958,7 +958,37 @@ udat_getBooleanAttribute(const UDateFormat* fmt, UDateFormatBooleanAttribute att
|
||||
U_CAPI void U_EXPORT2
|
||||
udat_setBooleanAttribute(UDateFormat *fmt, UDateFormatBooleanAttribute attr, UBool newValue, UErrorCode* status);
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Hour Cycle.
|
||||
* @draft ICU 67
|
||||
*/
|
||||
typedef enum UDateFormatHourCycle {
|
||||
/**
|
||||
* Hour in am/pm (0~11)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
UDAT_HOUR_CYCLE_11,
|
||||
|
||||
/**
|
||||
* Hour in am/pm (1~12)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
UDAT_HOUR_CYCLE_12,
|
||||
|
||||
/**
|
||||
* Hour in day (0~23)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
UDAT_HOUR_CYCLE_23,
|
||||
|
||||
/**
|
||||
* Hour in day (1~24)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
UDAT_HOUR_CYCLE_24
|
||||
} UDateFormatHourCycle;
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
#if U_SHOW_CPLUSPLUS_API
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define __UDATPG_H__
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
#include "unicode/udat.h"
|
||||
#include "unicode/uenum.h"
|
||||
#include "unicode/localpointer.h"
|
||||
|
||||
@ -651,4 +652,18 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg,
|
||||
const UChar *skeleton, int32_t skeletonLength,
|
||||
int32_t *pLength);
|
||||
|
||||
#ifndef U_HIDE_DRAFT_API
|
||||
/**
|
||||
* Return the default hour cycle.
|
||||
*
|
||||
* @param dtpg a pointer to UDateTimePatternGenerator.
|
||||
* @param pErrorCode a pointer to the UErrorCode which must not indicate a
|
||||
* failure before the function call.
|
||||
* @return the default hour cycle.
|
||||
* @draft ICU 67
|
||||
*/
|
||||
U_DRAFT UDateFormatHourCycle U_EXPORT2
|
||||
udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode);
|
||||
#endif /* U_HIDE_DRAFT_API */
|
||||
|
||||
#endif
|
||||
|
@ -43,6 +43,7 @@ static void TestUsage(void);
|
||||
static void TestBuilder(void);
|
||||
static void TestOptions(void);
|
||||
static void TestGetFieldDisplayNames(void);
|
||||
static void TestGetDefaultHourCycle(void);
|
||||
|
||||
void addDateTimePatternGeneratorTest(TestNode** root) {
|
||||
TESTCASE(TestOpenClose);
|
||||
@ -50,6 +51,7 @@ void addDateTimePatternGeneratorTest(TestNode** root) {
|
||||
TESTCASE(TestBuilder);
|
||||
TESTCASE(TestOptions);
|
||||
TESTCASE(TestGetFieldDisplayNames);
|
||||
TESTCASE(TestGetDefaultHourCycle);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -510,4 +512,46 @@ static void TestGetFieldDisplayNames() {
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct HourCycleData {
|
||||
const char * locale;
|
||||
UDateFormatHourCycle expected;
|
||||
} HourCycleData;
|
||||
|
||||
static void TestGetDefaultHourCycle() {
|
||||
const HourCycleData testData[] = {
|
||||
/*loc expected */
|
||||
{ "ar_EG", UDAT_HOUR_CYCLE_12 },
|
||||
{ "de_DE", UDAT_HOUR_CYCLE_23 },
|
||||
{ "en_AU", UDAT_HOUR_CYCLE_12 },
|
||||
{ "en_CA", UDAT_HOUR_CYCLE_12 },
|
||||
{ "en_US", UDAT_HOUR_CYCLE_12 },
|
||||
{ "es_ES", UDAT_HOUR_CYCLE_23 },
|
||||
{ "fi", UDAT_HOUR_CYCLE_23 },
|
||||
{ "fr", UDAT_HOUR_CYCLE_23 },
|
||||
{ "ja_JP", UDAT_HOUR_CYCLE_23 },
|
||||
{ "zh_CN", UDAT_HOUR_CYCLE_12 },
|
||||
{ "zh_HK", UDAT_HOUR_CYCLE_12 },
|
||||
{ "zh_TW", UDAT_HOUR_CYCLE_12 },
|
||||
{ "ko_KR", UDAT_HOUR_CYCLE_12 },
|
||||
};
|
||||
int count = UPRV_LENGTHOF(testData);
|
||||
const HourCycleData * testDataPtr = testData;
|
||||
for (; count-- > 0; ++testDataPtr) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UDateTimePatternGenerator * dtpgen =
|
||||
udatpg_open(testDataPtr->locale, &status);
|
||||
if ( U_FAILURE(status) ) {
|
||||
log_data_err( "ERROR udatpg_open failed for locale %s : %s - (Are you missing data?)\n",
|
||||
testDataPtr->locale, myErrorName(status));
|
||||
} else {
|
||||
UDateFormatHourCycle actual = udatpg_getDefaultHourCycle(dtpgen, &status);
|
||||
if (U_FAILURE(status) || testDataPtr->expected != actual) {
|
||||
log_err("ERROR dtpgen locale %s udatpg_getDefaultHourCycle expecte to get %d but get %d\n",
|
||||
testDataPtr->locale, testDataPtr->expected, actual);
|
||||
}
|
||||
udatpg_close(dtpgen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1410,18 +1410,19 @@ void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() {
|
||||
const char* localeName;
|
||||
const char16_t* expectedDtpgPattern;
|
||||
const char16_t* expectedTimePattern;
|
||||
UDateFormatHourCycle expectedDefaultHourCycle;
|
||||
} cases[] = {
|
||||
// ars is interesting because it does not have a region, but it aliases
|
||||
// to ar_SA, which has a region.
|
||||
{"ars", u"h a", u"h:mm a"},
|
||||
{"ars", u"h a", u"h:mm a", UDAT_HOUR_CYCLE_12},
|
||||
// en_NH is interesting because NH is a deprecated region code;
|
||||
// formerly New Hebrides, now Vanuatu => VU => h.
|
||||
{"en_NH", u"h a", u"h:mm a"},
|
||||
{"en_NH", u"h a", u"h:mm a", UDAT_HOUR_CYCLE_12},
|
||||
// ch_ZH is a typo (should be zh_CN), but we should fail gracefully.
|
||||
// {"cn_ZH", u"HH", u"H:mm"}, // TODO(ICU-20653): Desired behavior
|
||||
{"cn_ZH", u"HH", u"h:mm a"}, // Actual behavior
|
||||
{"cn_ZH", u"HH", u"h:mm a", UDAT_HOUR_CYCLE_23 }, // Actual behavior
|
||||
// a non-BCP47 locale without a country code should not fail
|
||||
{"ja_TRADITIONAL", u"H時", u"H:mm"},
|
||||
{"ja_TRADITIONAL", u"H時", u"H:mm", UDAT_HOUR_CYCLE_23},
|
||||
};
|
||||
|
||||
for (auto& cas : cases) {
|
||||
@ -1440,11 +1441,17 @@ void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() {
|
||||
if (status.errIfFailureAndReset()) {
|
||||
return;
|
||||
}
|
||||
UDateFormatHourCycle defaultHourCycle = dtpg->getDefaultHourCycle(status);
|
||||
if (status.errIfFailureAndReset()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertEquals(UnicodeString("dtpgPattern ") + cas.localeName,
|
||||
cas.expectedDtpgPattern, dtpgPattern);
|
||||
assertEquals(UnicodeString("timePattern ") + cas.localeName,
|
||||
cas.expectedTimePattern, timePattern);
|
||||
assertEquals(UnicodeString("defaultHour ") + cas.localeName,
|
||||
cas.expectedDefaultHourCycle, defaultHourCycle);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -535,6 +535,36 @@ public abstract class DateFormat extends UFormat {
|
||||
*/
|
||||
private EnumSet<BooleanAttribute> booleanAttributes = EnumSet.allOf(BooleanAttribute.class);
|
||||
|
||||
/**
|
||||
* Hour Cycle
|
||||
* @draft ICU 67
|
||||
*/
|
||||
public enum HourCycle {
|
||||
/**
|
||||
* hour in am/pm (0~11)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
HOUR_CYCLE_11,
|
||||
|
||||
/**
|
||||
* hour in am/pm (1~12)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
HOUR_CYCLE_12,
|
||||
|
||||
/**
|
||||
* hour in day (0~23)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
HOUR_CYCLE_23,
|
||||
|
||||
/**
|
||||
* hour in day (1~24)
|
||||
* @draft ICU 67
|
||||
*/
|
||||
HOUR_CYCLE_24;
|
||||
};
|
||||
|
||||
/*
|
||||
* Capitalization setting, hoisted to DateFormat ICU 53
|
||||
* Note that SimpleDateFormat serialization may call getContext/setContext to read/write
|
||||
|
@ -1205,7 +1205,6 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
|
||||
private static final int APPENDITEM_WIDTH_INT = APPENDITEM_WIDTH.ordinal();
|
||||
private static final DisplayWidth[] CLDR_FIELD_WIDTH = DisplayWidth.values();
|
||||
|
||||
|
||||
// Option masks for getBestPattern, replaceFieldTypes (individual masks may be ORed together)
|
||||
|
||||
/**
|
||||
@ -1313,6 +1312,20 @@ public class DateTimePatternGenerator implements Freezable<DateTimePatternGenera
|
||||
return getFieldDisplayName(field, APPENDITEM_WIDTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default hour cycle.
|
||||
* @draft ICU 67
|
||||
*/
|
||||
public DateFormat.HourCycle getDefaultHourCycle() {
|
||||
switch(getDefaultHourFormatChar()) {
|
||||
case 'h': return DateFormat.HourCycle.HOUR_CYCLE_12;
|
||||
case 'H': return DateFormat.HourCycle.HOUR_CYCLE_23;
|
||||
case 'k': return DateFormat.HourCycle.HOUR_CYCLE_24;
|
||||
case 'K': return DateFormat.HourCycle.HOUR_CYCLE_11;
|
||||
default: throw new AssertionError("should be unreachable");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The private interface to set a display name for a particular date/time field,
|
||||
* in one of several possible display widths.
|
||||
|
@ -1733,14 +1733,14 @@ public class DateTimeGeneratorTest extends TestFmwk {
|
||||
String[][] cases = new String[][]{
|
||||
// ars is interesting because it does not have a region, but it aliases
|
||||
// to ar_SA, which has a region.
|
||||
{"ars", "h a", "h:mm a"},
|
||||
{"ars", "h a", "h:mm a", "HOUR_CYCLE_12"},
|
||||
// en_NH is interesting because NH is a depregated region code.
|
||||
{"en_NH", "h a", "h:mm a"},
|
||||
{"en_NH", "h a", "h:mm a", "HOUR_CYCLE_12"},
|
||||
// ch_ZH is a typo (should be zh_CN), but we should fail gracefully.
|
||||
// {"cn_ZH", "HH", "H:mm"}, // TODO(ICU-20653): Desired behavior
|
||||
{"cn_ZH", "HH", "h:mm a"}, // Actual behavior
|
||||
{"cn_ZH", "HH", "h:mm a", "HOUR_CYCLE_23"}, // Actual behavior
|
||||
// a non-BCP47 locale without a country code should not fail
|
||||
{"ja_TRADITIONAL", "H時", "H:mm"},
|
||||
{"ja_TRADITIONAL", "H時", "H:mm", "HOUR_CYCLE_23"},
|
||||
};
|
||||
|
||||
for (String[] cas : cases) {
|
||||
@ -1755,6 +1755,8 @@ public class DateTimeGeneratorTest extends TestFmwk {
|
||||
cas[1], dtpgPattern);
|
||||
assertEquals("timePattern " + cas[1],
|
||||
cas[2], timePattern);
|
||||
assertEquals("default hour cycle " + cas[3],
|
||||
cas[3], dtpg.getDefaultHourCycle().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user