Skip to content

Commit

Permalink
ICU-22105 Fixed the unit-conversion logic to work correctly with nega…
Browse files Browse the repository at this point in the history
…tive temperature values.
  • Loading branch information
richgillam committed Aug 16, 2022
1 parent 3ef03a4 commit 8492a82
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 2 deletions.
2 changes: 1 addition & 1 deletion icu4c/source/i18n/units_complexconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity,
// TODO: return an error for "foot-and-foot"?
MaybeStackVector<Measure> result;
int sign = 1;
if (quantity < 0) {
if (quantity < 0 && unitsConverters_.length() > 1) {
quantity *= -1;
sign = -1;
}
Expand Down
41 changes: 41 additions & 0 deletions icu4c/source/test/cintltst/unumberformattertst.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static void TestPerUnitInArabic(void);

static void Test21674_State(void);

static void TestNegativeDegrees(void);

void addUNumberFormatterTest(TestNode** root);

#define TESTCASE(x) addTest(root, &x, "tsformat/unumberformatter/" #x)
Expand All @@ -47,6 +49,7 @@ void addUNumberFormatterTest(TestNode** root) {
TESTCASE(TestToDecimalNumber);
TESTCASE(TestPerUnitInArabic);
TESTCASE(Test21674_State);
TESTCASE(TestNegativeDegrees);
}


Expand Down Expand Up @@ -420,5 +423,43 @@ static void Test21674_State() {
unumf_closeResult(result);
}

// Test for ICU-22105
static void TestNegativeDegrees(void) {
typedef struct {
const UChar* skeleton;
double value;
const UChar* expectedResult;
} TestCase;

TestCase testCases[] = {
{ u"measure-unit/temperature-celsius unit-width-short", 0, u"0°C" },
{ u"measure-unit/temperature-celsius unit-width-short usage/default", 0, u"32°F" },
{ u"measure-unit/temperature-celsius unit-width-short usage/weather", 0, u"32°F" },

{ u"measure-unit/temperature-celsius unit-width-short", -1, u"-1°C" },
{ u"measure-unit/temperature-celsius unit-width-short usage/default", -1, u"30°F" },
{ u"measure-unit/temperature-celsius unit-width-short usage/weather", -1, u"30°F" }
};

for (int32_t i = 0; i < UPRV_LENGTHOF(testCases); i++) {
UErrorCode err = U_ZERO_ERROR;
UNumberFormatter* nf = unumf_openForSkeletonAndLocale(testCases[i].skeleton, -1, "en_US", &err);
UFormattedNumber* fn = unumf_openResult(&err);

if (assertSuccess("Failed to create formatter or result", &err)) {
UChar result[200];
unumf_formatDouble(nf, testCases[i].value, fn, &err);
unumf_resultToString(fn, result, 200, &err);

if (assertSuccess("Formatting number failed", &err)) {
assertUEquals("Got wrong result", testCases[i].expectedResult, result);
}
}

unumf_closeResult(fn);
unumf_close(nf);
}
}


#endif /* #if !UCONFIG_NO_FORMATTING */
11 changes: 11 additions & 0 deletions icu4c/source/test/intltest/numbertest_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,17 @@ void NumberFormatterApiTest::unitUsage() {
Locale("en-US"), //
1, //
"0.019 psi");

assertFormatSingle(u"negative temperature conversion", //
u"measure-unit/temperature-celsius unit-width-short usage/default", //
u"measure-unit/temperature-celsius unit-width-short usage/default", //
NumberFormatter::with() //
.unit(MeasureUnit::forIdentifier("celsius", status)) //
.usage("default") //
.unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_SHORT), //
Locale("en-US"), //
-1, //
u"30°F");
}

void NumberFormatterApiTest::unitUsageErrorCodes() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public static class ComplexConverterResult {
*/
public ComplexConverterResult convert(BigDecimal quantity, Precision rounder) {
BigInteger sign = BigInteger.ONE;
if (quantity.compareTo(BigDecimal.ZERO) < 0) {
if (quantity.compareTo(BigDecimal.ZERO) < 0 && unitsConverters_.size() > 1) {
quantity = quantity.abs();
sign = sign.negate();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1839,6 +1839,18 @@ public void unitUsage() {
new ULocale("en-US"),
1,
"0.019 psi");

// ICU-22105
assertFormatSingle("negative temperature conversion",
"measure-unit/temperature-celsius unit-width-short usage/default",
"measure-unit/temperature-celsius unit-width-short usage/default",
NumberFormatter.with()
.unit(MeasureUnit.forIdentifier("celsius"))
.usage("default")
.unitWidth(UnitWidth.SHORT),
new ULocale("en-US"),
-1,
"30°F");
}

@Test
Expand Down

0 comments on commit 8492a82

Please sign in to comment.