Skip to content

Commit 78be065

Browse files
committed
ICU-23265 Fixed parseMeasureUnitOption() so that it correctly handles measurement unit alises.
1 parent f359a60 commit 78be065

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

icu4c/source/i18n/number_skeletons.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,8 +1076,15 @@ void blueprint_helpers::parseMeasureUnitOption(const StringSegment& segment, Mac
10761076
if (MeasureUnit::validateAndGet(type.toStringPiece(), subType.toStringPiece(), unit)) {
10771077
macros.unit = unit;
10781078
return;
1079-
}
1079+
}
10801080

1081+
UErrorCode localStatus = U_ZERO_ERROR;
1082+
unit = MeasureUnit::forIdentifier(subType.data(), localStatus);
1083+
if (U_SUCCESS(localStatus) && uprv_strcmp(type.data(), unit.getType()) == 0) {
1084+
macros.unit = unit;
1085+
return;
1086+
}
1087+
10811088
status = U_NUMBER_SKELETON_SYNTAX_ERROR;
10821089
}
10831090

icu4c/source/test/intltest/numbertest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ class NumberSkeletonTest : public IntlTest {
306306
void perUnitToSkeleton();
307307
void measurementSystemOverride();
308308
void longSkeletonCrash();
309+
void unitAliases();
309310

310311
void runIndexedTest(int32_t index, UBool exec, const char*& name, char* par = nullptr) override;
311312

icu4c/source/test/intltest/numbertest_skeletons.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void NumberSkeletonTest::runIndexedTest(int32_t index, UBool exec, const char*&
3636
TESTCASE_AUTO(perUnitToSkeleton);
3737
TESTCASE_AUTO(measurementSystemOverride);
3838
TESTCASE_AUTO(longSkeletonCrash);
39+
TESTCASE_AUTO(unitAliases);
3940
TESTCASE_AUTO_END;
4041
}
4142

@@ -581,4 +582,31 @@ void NumberSkeletonTest::longSkeletonCrash() {
581582
UnlocalizedNumberFormatter nf = NumberFormatter::forSkeleton(skeleton, err);
582583
}
583584

585+
void NumberSkeletonTest::unitAliases() {
586+
IcuTestErrorCode status(*this, "unitAliases");
587+
588+
struct TestCase {
589+
const char16_t* skeleton;
590+
const char16_t* expectedResult;
591+
} testCases[] = {
592+
{ u"measure-unit/concentr-part-per-1e6", u"3.14 ppm" },
593+
{ u"measure-unit/concentr-part-per-million", u"3.14 ppm" },
594+
{ u"measure-unit/concentr-permillion", u"3.14 ppm" },
595+
{ u"measure-unit/concentr-milligram-ofglucose-per-deciliter", u"3.14 mg/dL" },
596+
{ u"measure-unit/concentr-milligram-per-deciliter", u"3.14 mg/dL" },
597+
{ u"measure-unit/mass-tonne", u"3.14 t" },
598+
{ u"measure-unit/mass-metric-ton", u"3.14 t" },
599+
};
600+
601+
for (const auto& testCase : testCases) {
602+
LocalizedNumberFormatter nf = NumberFormatter::forSkeleton(testCase.skeleton, status).locale(Locale::getUS());
603+
UnicodeString actualResult = nf.formatDouble(3.14, status).toString(status);
604+
605+
status.setScope(testCase.skeleton);
606+
if (!status.errIfFailureAndReset()) {
607+
assertEquals(testCase.skeleton, testCase.expectedResult, actualResult);
608+
}
609+
}
610+
}
611+
584612
#endif /* #if !UCONFIG_NO_FORMATTING */

icu4j/main/core/src/main/java/com/ibm/icu/number/NumberSkeletonImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,16 @@ private static void parseMeasureUnitOption(StringSegment segment, MacroProps mac
10991099
macros.unit = unit;
11001100
return;
11011101
}
1102+
try {
1103+
unit = MeasureUnit.forIdentifier(subType);
1104+
if (unit.getType().equals(type)) {
1105+
macros.unit = unit;
1106+
return;
1107+
}
1108+
} catch (IllegalArgumentException e) {
1109+
// handled below
1110+
}
1111+
11021112
throw new SkeletonSyntaxException("Unknown measure unit", segment);
11031113
}
11041114

icu4j/main/core/src/test/java/com/ibm/icu/dev/test/number/NumberSkeletonTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,4 +549,36 @@ public void measurementSystemOverride() {
549549
"Wrong result: " + languageTag + ":" + skeleton, expectedResult, actualResult);
550550
}
551551
}
552+
553+
@Test
554+
public void unitAliases() {
555+
class TestCase {
556+
String skeleton;
557+
String expectedResult;
558+
TestCase(String skeleton, String expectedResult) {
559+
this.skeleton = skeleton;
560+
this.expectedResult = expectedResult;
561+
}
562+
}
563+
TestCase[] testCases = new TestCase[] {
564+
new TestCase("measure-unit/concentr-part-per-1e6", "3.14 ppm"),
565+
new TestCase("measure-unit/concentr-part-per-million", "3.14 ppm"),
566+
new TestCase("measure-unit/concentr-permillion", "3.14 ppm"),
567+
new TestCase("measure-unit/concentr-milligram-ofglucose-per-deciliter", "3.14 mg/dL"),
568+
new TestCase("measure-unit/concentr-milligram-per-deciliter", "3.14 mg/dL"),
569+
new TestCase("measure-unit/mass-tonne", "3.14 t"),
570+
new TestCase("measure-unit/mass-metric-ton", "3.14 t"),
571+
};
572+
573+
for (TestCase testCase : testCases) {
574+
try {
575+
LocalizedNumberFormatter nf = NumberFormatter.forSkeleton(testCase.skeleton).locale(Locale.US);
576+
String actualResult = nf.format(3.14).toString();
577+
578+
assertEquals("Wrong result for " + testCase.skeleton + ":", testCase.expectedResult, actualResult);
579+
} catch (SkeletonSyntaxException e) {
580+
fail(testCase.skeleton);
581+
}
582+
}
583+
}
552584
}

0 commit comments

Comments
 (0)