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
|
UnicodeString
|
||||||
DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode&
|
DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode&
|
||||||
/*status*/) {
|
/*status*/) {
|
||||||
|
@ -291,4 +291,9 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg,
|
|||||||
return result.getBuffer();
|
return result.getBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U_CAPI UDateFormatHourCycle U_EXPORT2
|
||||||
|
udatpg_getDefaultHourCycle(const UDateTimePatternGenerator *dtpg, UErrorCode* pErrorCode) {
|
||||||
|
return ((const DateTimePatternGenerator *)dtpg)->getDefaultHourCycle(*pErrorCode);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -483,6 +483,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
const UnicodeString& getDecimal() const;
|
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.
|
* 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
|
U_CAPI void U_EXPORT2
|
||||||
udat_setBooleanAttribute(UDateFormat *fmt, UDateFormatBooleanAttribute attr, UBool newValue, UErrorCode* status);
|
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
|
#if U_SHOW_CPLUSPLUS_API
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define __UDATPG_H__
|
#define __UDATPG_H__
|
||||||
|
|
||||||
#include "unicode/utypes.h"
|
#include "unicode/utypes.h"
|
||||||
|
#include "unicode/udat.h"
|
||||||
#include "unicode/uenum.h"
|
#include "unicode/uenum.h"
|
||||||
#include "unicode/localpointer.h"
|
#include "unicode/localpointer.h"
|
||||||
|
|
||||||
@ -651,4 +652,18 @@ udatpg_getPatternForSkeleton(const UDateTimePatternGenerator *dtpg,
|
|||||||
const UChar *skeleton, int32_t skeletonLength,
|
const UChar *skeleton, int32_t skeletonLength,
|
||||||
int32_t *pLength);
|
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
|
#endif
|
||||||
|
@ -43,6 +43,7 @@ static void TestUsage(void);
|
|||||||
static void TestBuilder(void);
|
static void TestBuilder(void);
|
||||||
static void TestOptions(void);
|
static void TestOptions(void);
|
||||||
static void TestGetFieldDisplayNames(void);
|
static void TestGetFieldDisplayNames(void);
|
||||||
|
static void TestGetDefaultHourCycle(void);
|
||||||
|
|
||||||
void addDateTimePatternGeneratorTest(TestNode** root) {
|
void addDateTimePatternGeneratorTest(TestNode** root) {
|
||||||
TESTCASE(TestOpenClose);
|
TESTCASE(TestOpenClose);
|
||||||
@ -50,6 +51,7 @@ void addDateTimePatternGeneratorTest(TestNode** root) {
|
|||||||
TESTCASE(TestBuilder);
|
TESTCASE(TestBuilder);
|
||||||
TESTCASE(TestOptions);
|
TESTCASE(TestOptions);
|
||||||
TESTCASE(TestGetFieldDisplayNames);
|
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
|
#endif
|
||||||
|
@ -1410,18 +1410,19 @@ void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() {
|
|||||||
const char* localeName;
|
const char* localeName;
|
||||||
const char16_t* expectedDtpgPattern;
|
const char16_t* expectedDtpgPattern;
|
||||||
const char16_t* expectedTimePattern;
|
const char16_t* expectedTimePattern;
|
||||||
|
UDateFormatHourCycle expectedDefaultHourCycle;
|
||||||
} cases[] = {
|
} cases[] = {
|
||||||
// ars is interesting because it does not have a region, but it aliases
|
// ars is interesting because it does not have a region, but it aliases
|
||||||
// to ar_SA, which has a region.
|
// 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;
|
// en_NH is interesting because NH is a deprecated region code;
|
||||||
// formerly New Hebrides, now Vanuatu => VU => h.
|
// 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.
|
// 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"}, // 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
|
// 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) {
|
for (auto& cas : cases) {
|
||||||
@ -1440,11 +1441,17 @@ void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() {
|
|||||||
if (status.errIfFailureAndReset()) {
|
if (status.errIfFailureAndReset()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UDateFormatHourCycle defaultHourCycle = dtpg->getDefaultHourCycle(status);
|
||||||
|
if (status.errIfFailureAndReset()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assertEquals(UnicodeString("dtpgPattern ") + cas.localeName,
|
assertEquals(UnicodeString("dtpgPattern ") + cas.localeName,
|
||||||
cas.expectedDtpgPattern, dtpgPattern);
|
cas.expectedDtpgPattern, dtpgPattern);
|
||||||
assertEquals(UnicodeString("timePattern ") + cas.localeName,
|
assertEquals(UnicodeString("timePattern ") + cas.localeName,
|
||||||
cas.expectedTimePattern, timePattern);
|
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);
|
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
|
* Capitalization setting, hoisted to DateFormat ICU 53
|
||||||
* Note that SimpleDateFormat serialization may call getContext/setContext to read/write
|
* 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 int APPENDITEM_WIDTH_INT = APPENDITEM_WIDTH.ordinal();
|
||||||
private static final DisplayWidth[] CLDR_FIELD_WIDTH = DisplayWidth.values();
|
private static final DisplayWidth[] CLDR_FIELD_WIDTH = DisplayWidth.values();
|
||||||
|
|
||||||
|
|
||||||
// Option masks for getBestPattern, replaceFieldTypes (individual masks may be ORed together)
|
// 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 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,
|
* The private interface to set a display name for a particular date/time field,
|
||||||
* in one of several possible display widths.
|
* in one of several possible display widths.
|
||||||
|
@ -1733,14 +1733,14 @@ public class DateTimeGeneratorTest extends TestFmwk {
|
|||||||
String[][] cases = new String[][]{
|
String[][] cases = new String[][]{
|
||||||
// ars is interesting because it does not have a region, but it aliases
|
// ars is interesting because it does not have a region, but it aliases
|
||||||
// to ar_SA, which has a region.
|
// 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 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.
|
// 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"}, // 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
|
// 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) {
|
for (String[] cas : cases) {
|
||||||
@ -1755,6 +1755,8 @@ public class DateTimeGeneratorTest extends TestFmwk {
|
|||||||
cas[1], dtpgPattern);
|
cas[1], dtpgPattern);
|
||||||
assertEquals("timePattern " + cas[1],
|
assertEquals("timePattern " + cas[1],
|
||||||
cas[2], timePattern);
|
cas[2], timePattern);
|
||||||
|
assertEquals("default hour cycle " + cas[3],
|
||||||
|
cas[3], dtpg.getDefaultHourCycle().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user