ICU-10640 Fix various bugs around duration formatting e.g 3:45:23
X-SVN-Rev: 35186
This commit is contained in:
parent
d09b746a61
commit
7fb4b7bcf6
@ -385,31 +385,36 @@ static int32_t toHMS(
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t count = 0;
|
||||
for (int32_t i = 0; i < measureCount; ++i) {
|
||||
if (measures[i].getUnit() == *hourUnit) {
|
||||
if ((result & 1) == 0) {
|
||||
++count;
|
||||
} else {
|
||||
// hour must come first
|
||||
if (result >= 1) {
|
||||
return 0;
|
||||
}
|
||||
hms[0] = measures[i].getNumber();
|
||||
if (hms[0].getDouble() < 0.0) {
|
||||
return 0;
|
||||
}
|
||||
result |= 1;
|
||||
} else if (measures[i].getUnit() == *minuteUnit) {
|
||||
if ((result & 2) == 0) {
|
||||
++count;
|
||||
} else {
|
||||
// minute must come after hour
|
||||
if (result >= 2) {
|
||||
return 0;
|
||||
}
|
||||
hms[1] = measures[i].getNumber();
|
||||
if (hms[1].getDouble() < 0.0) {
|
||||
return 0;
|
||||
}
|
||||
result |= 2;
|
||||
} else if (measures[i].getUnit() == *secondUnit) {
|
||||
if ((result & 4) == 0) {
|
||||
++count;
|
||||
} else {
|
||||
// second must come after hour and minute
|
||||
if (result >= 4) {
|
||||
return 0;
|
||||
}
|
||||
hms[2] = measures[i].getNumber();
|
||||
if (hms[2].getDouble() < 0.0) {
|
||||
return 0;
|
||||
}
|
||||
result |= 4;
|
||||
} else {
|
||||
return 0;
|
||||
@ -734,9 +739,9 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
return appendTo;
|
||||
}
|
||||
UDate millis =
|
||||
(UDate) (((hms[0].getDouble(status) * 60.0
|
||||
+ hms[1].getDouble(status)) * 60.0
|
||||
+ hms[2].getDouble(status)) * 1000.0);
|
||||
(UDate) (((uprv_trunc(hms[0].getDouble(status)) * 60.0
|
||||
+ uprv_trunc(hms[1].getDouble(status))) * 60.0
|
||||
+ uprv_trunc(hms[2].getDouble(status))) * 1000.0);
|
||||
switch (bitMap) {
|
||||
case 5: // hs
|
||||
case 7: // hms
|
||||
@ -774,9 +779,24 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
static void appendRange(
|
||||
const UnicodeString &src,
|
||||
int32_t start,
|
||||
int32_t end,
|
||||
UnicodeString &dest) {
|
||||
dest.append(src, start, end - start);
|
||||
}
|
||||
|
||||
static void appendRange(
|
||||
const UnicodeString &src,
|
||||
int32_t end,
|
||||
UnicodeString &dest) {
|
||||
dest.append(src, end, src.length() - end);
|
||||
}
|
||||
|
||||
UnicodeString &MeasureFormat::formatNumeric(
|
||||
UDate date,
|
||||
const DateFormat &dateFmt,
|
||||
UDate date, // Time since epoch 1:30:00 would be 5400000
|
||||
const DateFormat &dateFmt, // h:mm, m:ss, or h:mm:ss
|
||||
UDateFormatField smallestField,
|
||||
const Formattable &smallestAmount,
|
||||
UnicodeString &appendTo,
|
||||
@ -784,20 +804,53 @@ UnicodeString &MeasureFormat::formatNumeric(
|
||||
if (U_FAILURE(status)) {
|
||||
return appendTo;
|
||||
}
|
||||
// Format the smallest amount with this object's NumberFormat
|
||||
UnicodeString smallestAmountFormatted;
|
||||
|
||||
// We keep track of the integer part of smallest amount so that
|
||||
// we can replace it later so that we get '0:00:09.3' instead of
|
||||
// '0:00:9.3'
|
||||
FieldPosition intFieldPosition(UNUM_INTEGER_FIELD);
|
||||
(*numberFormat)->format(
|
||||
smallestAmount, smallestAmountFormatted, status);
|
||||
smallestAmount, smallestAmountFormatted, intFieldPosition, status);
|
||||
if (
|
||||
intFieldPosition.getBeginIndex() == 0 &&
|
||||
intFieldPosition.getEndIndex() == 0) {
|
||||
status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return appendTo;
|
||||
}
|
||||
|
||||
// Format time. draft becomes something like '5:30:45'
|
||||
FieldPosition smallestFieldPosition(smallestField);
|
||||
UnicodeString draft;
|
||||
dateFmt.format(date, draft, smallestFieldPosition, status);
|
||||
|
||||
// If we find field for smallest amount replace it with the formatted
|
||||
// smallest amount from above taking care to replace the integer part
|
||||
// with what is in original time. For example, If smallest amount
|
||||
// is 9.35s and the formatted time is 0:00:09 then 9.35 becomes 09.35
|
||||
// and replacing yields 0:00:09.35
|
||||
if (smallestFieldPosition.getBeginIndex() != 0 ||
|
||||
smallestFieldPosition.getEndIndex() != 0) {
|
||||
appendTo.append(draft, 0, smallestFieldPosition.getBeginIndex());
|
||||
appendTo.append(smallestAmountFormatted);
|
||||
appendTo.append(
|
||||
smallestFieldPosition.getEndIndex() != 0) {
|
||||
appendRange(draft, 0, smallestFieldPosition.getBeginIndex(), appendTo);
|
||||
appendRange(
|
||||
smallestAmountFormatted,
|
||||
0,
|
||||
intFieldPosition.getBeginIndex(),
|
||||
appendTo);
|
||||
appendRange(
|
||||
draft,
|
||||
smallestFieldPosition.getBeginIndex(),
|
||||
smallestFieldPosition.getEndIndex(),
|
||||
appendTo);
|
||||
appendRange(
|
||||
smallestAmountFormatted,
|
||||
intFieldPosition.getEndIndex(),
|
||||
appendTo);
|
||||
appendRange(
|
||||
draft,
|
||||
smallestFieldPosition.getEndIndex(),
|
||||
draft.length());
|
||||
appendTo);
|
||||
} else {
|
||||
appendTo.append(draft);
|
||||
}
|
||||
|
@ -314,10 +314,19 @@ void MeasureFormatTest::TestFormatPeriodEn() {
|
||||
Measure(5.0, MeasureUnit::createHour(status), status),
|
||||
Measure(17.0, MeasureUnit::createMinute(status), status)
|
||||
};
|
||||
Measure t_neg5h_17m[] = {
|
||||
Measure(-5.0, MeasureUnit::createHour(status), status),
|
||||
Measure(17.0, MeasureUnit::createMinute(status), status)
|
||||
};
|
||||
Measure t_19m_28s[] = {
|
||||
Measure(19.0, MeasureUnit::createMinute(status), status),
|
||||
Measure(28.0, MeasureUnit::createSecond(status), status)
|
||||
};
|
||||
Measure t_0h_0m_9s[] = {
|
||||
Measure(0.0, MeasureUnit::createHour(status), status),
|
||||
Measure(0.0, MeasureUnit::createMinute(status), status),
|
||||
Measure(9.0, MeasureUnit::createSecond(status), status)
|
||||
};
|
||||
Measure t_0h_0m_17s[] = {
|
||||
Measure(0.0, MeasureUnit::createHour(status), status),
|
||||
Measure(0.0, MeasureUnit::createMinute(status), status),
|
||||
@ -327,6 +336,16 @@ void MeasureFormatTest::TestFormatPeriodEn() {
|
||||
Measure(6.0, MeasureUnit::createHour(status), status),
|
||||
Measure(56.92, MeasureUnit::createMinute(status), status)
|
||||
};
|
||||
Measure t_3h_4s_5m[] = {
|
||||
Measure(3.0, MeasureUnit::createHour(status), status),
|
||||
Measure(4.0, MeasureUnit::createSecond(status), status),
|
||||
Measure(5.0, MeasureUnit::createMinute(status), status)
|
||||
};
|
||||
Measure t_6_7h_56_92m[] = {
|
||||
Measure(6.7, MeasureUnit::createHour(status), status),
|
||||
Measure(56.92, MeasureUnit::createMinute(status), status)
|
||||
};
|
||||
|
||||
Measure t_3h_5h[] = {
|
||||
Measure(3.0, MeasureUnit::createHour(status), status),
|
||||
Measure(5.0, MeasureUnit::createHour(status), status)
|
||||
@ -367,10 +386,13 @@ void MeasureFormatTest::TestFormatPeriodEn() {
|
||||
{t_1h_23_5m, LENGTHOF(t_1h_23_5m), "1:23.5"},
|
||||
{t_1h_0m_23s, LENGTHOF(t_1h_0m_23s), "1:00:23"},
|
||||
{t_5h_17m, LENGTHOF(t_5h_17m), "5:17"},
|
||||
{t_neg5h_17m, LENGTHOF(t_neg5h_17m), "-5h 17m"},
|
||||
{t_19m_28s, LENGTHOF(t_19m_28s), "19:28"},
|
||||
{t_2y_5M_3w_4d, LENGTHOF(t_2y_5M_3w_4d), "2y 5m 3w 4d"},
|
||||
{t_0h_0m_17s, LENGTHOF(t_0h_0m_17s), "0:00:17"},
|
||||
{t_0h_0m_9s, LENGTHOF(t_0h_0m_9s), "0:00:09"},
|
||||
{t_6h_56_92m, LENGTHOF(t_6h_56_92m), "6:56.92"},
|
||||
{t_6_7h_56_92m, LENGTHOF(t_6_7h_56_92m), "6:56.92"},
|
||||
{t_3h_4s_5m, LENGTHOF(t_3h_4s_5m), "3h 4s 5m"},
|
||||
{t_3h_5h, LENGTHOF(t_3h_5h), "3h 5h"}};
|
||||
|
||||
ExpectedResult fullDataDe[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user