mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-16 18:25:57 +00:00
ICU-81 roll bugs and calculation errors in cutover year
X-SVN-Rev: 359
This commit is contained in:
parent
b3fec85b29
commit
b851d05295
3 changed files with 330 additions and 36 deletions
|
@ -31,6 +31,8 @@
|
|||
* {JDK bug 4210209 4209272}
|
||||
* 11/15/99 weiv Added YEAR_WOY and DOW_LOCAL computation
|
||||
* to timeToFields method, updated kMinValues, kMaxValues & kLeastMaxValues
|
||||
* 12/09/99 aliu Fixed j81, calculation errors and roll bugs
|
||||
* in year of cutover.
|
||||
********************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -454,6 +456,13 @@ GregorianCalendar::timeToFields(UDate theTime, bool_t quick, UErrorCode& status)
|
|||
year = 1 - year;
|
||||
}
|
||||
|
||||
// Adjust the doy for the cutover year. Do this AFTER the above
|
||||
// computations using doy! [j81 - aliu]
|
||||
if (rawYear == fGregorianCutoverYear &&
|
||||
theTime >= fNormalizedGregorianCutover) {
|
||||
dayOfYear -= 10;
|
||||
}
|
||||
|
||||
// Calculate year of week of year
|
||||
|
||||
|
||||
|
@ -1089,6 +1098,11 @@ GregorianCalendar::computeJulianDay(bool_t isGregorian, int32_t year)
|
|||
}
|
||||
else if (bestStamp == doyStamp) {
|
||||
julianDay += internalGet(DAY_OF_YEAR);
|
||||
|
||||
// Adjust for cutover year [j81 - aliu]
|
||||
if (year == fGregorianCutoverYear && isGregorian) {
|
||||
julianDay -= 10;
|
||||
}
|
||||
}
|
||||
else if (bestStamp == woyStamp) {
|
||||
// Compute from day of week plus week of year
|
||||
|
@ -1118,6 +1132,11 @@ GregorianCalendar::computeJulianDay(bool_t isGregorian, int32_t year)
|
|||
date += 7 * (internalGet(WEEK_OF_YEAR) - 1);
|
||||
|
||||
julianDay += date;
|
||||
|
||||
// Adjust for cutover year [j81 - aliu]
|
||||
if (year == fGregorianCutoverYear && isGregorian) {
|
||||
julianDay -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1366,6 +1385,34 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
max = getMaximum(field);
|
||||
}
|
||||
|
||||
/* Some of the fields require special handling to work in the month
|
||||
* containing the Gregorian cutover point. Do shared computations
|
||||
* for these fields here. [j81 - aliu] */
|
||||
bool_t inCutoverMonth = FALSE;
|
||||
int32_t cMonthLen; // 'c' for cutover; in days
|
||||
int32_t cDayOfMonth; // no discontinuity: [0, cMonthLen)
|
||||
double cMonthStart; // in ms
|
||||
switch (field) {
|
||||
case DAY_OF_MONTH:
|
||||
case WEEK_OF_MONTH:
|
||||
{
|
||||
max = monthLength(internalGet(MONTH));
|
||||
double t = internalGetTime();
|
||||
// We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an
|
||||
// additional 10 if we are after the cutover. Thus the monthStart
|
||||
// value will be correct iff we actually are in the cutover month.
|
||||
cDayOfMonth = internalGet(DAY_OF_MONTH) - ((t >= fGregorianCutover) ? 10 : 0);
|
||||
cMonthStart = t - ((cDayOfMonth - 1) * kOneDay);
|
||||
|
||||
// A month containing the cutover is 10 days shorter.
|
||||
if ((cMonthStart < fGregorianCutover) &&
|
||||
(cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) {
|
||||
inCutoverMonth = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (field) {
|
||||
case ERA:
|
||||
case YEAR:
|
||||
|
@ -1424,7 +1471,7 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
case WEEK_OF_YEAR:
|
||||
{
|
||||
// Unlike WEEK_OF_MONTH, WEEK_OF_YEAR never shifts the day of the
|
||||
// week. Also, rolling the week of the year can have seemingly
|
||||
// week. However, rolling the week of the year can have seemingly
|
||||
// strange effects simply because the year of the week of year
|
||||
// may be different from the calendar year. For example, the
|
||||
// date Dec 28, 1997 is the first day of week 1 of 1998 (if
|
||||
|
@ -1499,15 +1546,24 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
// the phantom days that we added, we recognize this and pin to
|
||||
// the first or the last day of the month. Easy, eh?
|
||||
|
||||
// Another wrinkle: To fix jitterbug 81, we have to make all this
|
||||
// work in the oddball month containing the Gregorian cutover.
|
||||
// This month is 10 days shorter than usual, and also contains
|
||||
// a discontinuity in the days; e.g., the default cutover month
|
||||
// is Oct 1582, and goes from day of month 4 to day of month 15.
|
||||
|
||||
// Normalize the DAY_OF_WEEK so that 0 is the first day of the week
|
||||
// in this locale. We have dow in 0..6.
|
||||
int32_t dow = internalGet(DAY_OF_WEEK) - getFirstDayOfWeek();
|
||||
if (dow < 0)
|
||||
dow += 7;
|
||||
|
||||
// Find the day of month, compensating for cutover discontinuity.
|
||||
int32_t dom = inCutoverMonth ? cDayOfMonth : internalGet(DAY_OF_MONTH);
|
||||
|
||||
// Find the day of the week (normalized for locale) for the first
|
||||
// of the month.
|
||||
int32_t fdm = (dow - internalGet(DAY_OF_MONTH) + 1) % 7;
|
||||
int32_t fdm = (dow - dom + 1) % 7;
|
||||
if (fdm < 0)
|
||||
fdm += 7;
|
||||
|
||||
|
@ -1523,8 +1579,8 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
|
||||
// Get the day of the week (normalized for locale) for the last
|
||||
// day of the month.
|
||||
int32_t monthLen = monthLength(internalGet(MONTH));
|
||||
int32_t ldm = (monthLen - internalGet(DAY_OF_MONTH) + dow) % 7;
|
||||
int32_t monthLen = inCutoverMonth ? cMonthLen : monthLength(internalGet(MONTH));
|
||||
int32_t ldm = (monthLen - dom + dow) % 7;
|
||||
// We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here.
|
||||
|
||||
// Get the limit day for the blocked-off rectangular month; that
|
||||
|
@ -1535,17 +1591,16 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
|
||||
// Now roll between start and (limit - 1).
|
||||
gap = limit - start;
|
||||
int32_t day_of_month = (internalGet(DAY_OF_MONTH) + amount*7 -
|
||||
start) % gap;
|
||||
if (day_of_month < 0)
|
||||
day_of_month += gap;
|
||||
day_of_month += start;
|
||||
int32_t newDom = (dom + amount*7 - start) % gap;
|
||||
if (newDom < 0)
|
||||
newDom += gap;
|
||||
newDom += start;
|
||||
|
||||
// Finally, pin to the real start and end of the month.
|
||||
if (day_of_month < 1)
|
||||
day_of_month = 1;
|
||||
if (day_of_month > monthLen)
|
||||
day_of_month = monthLen;
|
||||
if (newDom < 1)
|
||||
newDom = 1;
|
||||
if (newDom > monthLen)
|
||||
newDom = monthLen;
|
||||
|
||||
// Set the DAY_OF_MONTH. We rely on the fact that this field
|
||||
// takes precedence over everything else (since all other fields
|
||||
|
@ -1553,11 +1608,34 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
// disambiguation algorithm changes) then we will have to unset
|
||||
// the appropriate fields here so that DAY_OF_MONTH is attended
|
||||
// to.
|
||||
set(DAY_OF_MONTH, day_of_month);
|
||||
|
||||
// If we are in the cutover month, manipulate ms directly. Don't do
|
||||
// this in general because it doesn't work across DST boundaries
|
||||
// (details, details). This takes care of the discontinuity.
|
||||
if (inCutoverMonth) {
|
||||
setTimeInMillis(cMonthStart + (newDom-1)*kOneDay, status);
|
||||
} else {
|
||||
set(DAY_OF_MONTH, newDom);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case DAY_OF_MONTH:
|
||||
max = monthLength(internalGet(MONTH));
|
||||
if (inCutoverMonth) {
|
||||
// The default computation works except when the current month
|
||||
// contains the Gregorian cutover. We handle this special case
|
||||
// here. [j81 - aliu]
|
||||
double monthLen = cMonthLen * kOneDay;
|
||||
double msIntoMonth = icu_fmod(internalGetTime() - cMonthStart +
|
||||
amount * kOneDay, monthLen);
|
||||
if (msIntoMonth < 0) {
|
||||
msIntoMonth += monthLen;
|
||||
}
|
||||
setTimeInMillis(cMonthStart + msIntoMonth, status);
|
||||
return;
|
||||
} else {
|
||||
max = monthLength(internalGet(MONTH));
|
||||
// ...else fall through to default computation
|
||||
}
|
||||
break;
|
||||
case DAY_OF_YEAR:
|
||||
{
|
||||
|
@ -1632,6 +1710,7 @@ GregorianCalendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
|
|||
value += min;
|
||||
|
||||
set(field, value);
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
|
|
@ -71,11 +71,34 @@ CalendarRegressionTest::runIndexedTest( int32_t index, bool_t exec, char* &name,
|
|||
CASE(33,Test4166109)
|
||||
CASE(34,Test4167060)
|
||||
CASE(35,Test4197699)
|
||||
CASE(36,TestJ81)
|
||||
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
const char* CalendarRegressionTest::FIELD_NAME [] = {
|
||||
"ERA",
|
||||
"YEAR",
|
||||
"MONTH",
|
||||
"WEEK_OF_YEAR",
|
||||
"WEEK_OF_MONTH",
|
||||
"DAY_OF_MONTH",
|
||||
"DAY_OF_YEAR",
|
||||
"DAY_OF_WEEK",
|
||||
"DAY_OF_WEEK_IN_MONTH",
|
||||
"AM_PM",
|
||||
"HOUR",
|
||||
"HOUR_OF_DAY",
|
||||
"MINUTE",
|
||||
"SECOND",
|
||||
"MILLISECOND",
|
||||
"ZONE_OFFSET",
|
||||
"DST_OFFSET",
|
||||
"YEAR_WOY",
|
||||
"DOW_LOCAL"
|
||||
};
|
||||
|
||||
bool_t
|
||||
CalendarRegressionTest::failure(UErrorCode status, const char* msg)
|
||||
{
|
||||
|
@ -1244,25 +1267,6 @@ CalendarRegressionTest::test4031502()
|
|||
*/
|
||||
void CalendarRegressionTest::test4147269()
|
||||
{
|
||||
const char* fieldName [] = {
|
||||
"ERA",
|
||||
"YEAR",
|
||||
"MONTH",
|
||||
"WEEK_OF_YEAR",
|
||||
"WEEK_OF_MONTH",
|
||||
"DAY_OF_MONTH",
|
||||
"DAY_OF_YEAR",
|
||||
"DAY_OF_WEEK",
|
||||
"DAY_OF_WEEK_IN_MONTH",
|
||||
"AM_PM",
|
||||
"HOUR",
|
||||
"HOUR_OF_DAY",
|
||||
"MINUTE",
|
||||
"SECOND",
|
||||
"MILLISECOND",
|
||||
"ZONE_OFFSET",
|
||||
"DST_OFFSET"
|
||||
};
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
GregorianCalendar *calendar = new GregorianCalendar(status);
|
||||
calendar->setLenient(FALSE);
|
||||
|
@ -1280,7 +1284,7 @@ CalendarRegressionTest::test4031502()
|
|||
// We expect an exception to be thrown. If we fall through
|
||||
// to the next line, then we have a bug.
|
||||
if(U_SUCCESS(status))
|
||||
errln(UnicodeString("Test failed with field ") + fieldName[field] +
|
||||
errln(UnicodeString("Test failed with field ") + FIELD_NAME[field] +
|
||||
", date before: " + date +
|
||||
", date after: " + calendar->getTime(status) +
|
||||
", value: " + value + " (max = " + max +")");
|
||||
|
@ -1639,6 +1643,215 @@ void CalendarRegressionTest::Test4197699() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolling and adding across the Gregorian cutover should work as expected.
|
||||
* Jitterbug 81.
|
||||
*/
|
||||
void CalendarRegressionTest::TestJ81() {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UnicodeString temp, temp2, temp3;
|
||||
int32_t ONE_HOUR = (int32_t)60*60*1000;
|
||||
int32_t ONE_DAY = (int32_t)24*ONE_HOUR;
|
||||
int32_t i;
|
||||
GregorianCalendar cal(TimeZone::createTimeZone("GMT"), status);
|
||||
SimpleDateFormat fmt("HH:mm 'w'w 'd'D E d MMM yyyy", Locale::US, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Error: Cannot create calendar or format");
|
||||
return;
|
||||
}
|
||||
fmt.setCalendar(cal);
|
||||
// Get the Gregorian cutover
|
||||
UDate cutover = cal.getGregorianChange();
|
||||
logln(UnicodeString("Cutover: {") +
|
||||
fmt.format(cutover, temp) + "}(" + cutover/ONE_DAY + ")");
|
||||
|
||||
// Check woy and doy handling. Reference data:
|
||||
/* w40 d274 Mon 1 Oct 1582
|
||||
w40 d275 Tue 2 Oct 1582
|
||||
w40 d276 Wed 3 Oct 1582
|
||||
w40 d277 Thu 4 Oct 1582
|
||||
w40 d278 Fri 15 Oct 1582
|
||||
w40 d279 Sat 16 Oct 1582
|
||||
w41 d280 Sun 17 Oct 1582
|
||||
w41 d281 Mon 18 Oct 1582
|
||||
w41 d282 Tue 19 Oct 1582
|
||||
w41 d283 Wed 20 Oct 1582
|
||||
w41 d284 Thu 21 Oct 1582
|
||||
w41 d285 Fri 22 Oct 1582
|
||||
w41 d286 Sat 23 Oct 1582
|
||||
w42 d287 Sun 24 Oct 1582
|
||||
w42 d288 Mon 25 Oct 1582
|
||||
w42 d289 Tue 26 Oct 1582
|
||||
w42 d290 Wed 27 Oct 1582
|
||||
w42 d291 Thu 28 Oct 1582
|
||||
w42 d292 Fri 29 Oct 1582
|
||||
w42 d293 Sat 30 Oct 1582
|
||||
w43 d294 Sun 31 Oct 1582
|
||||
w43 d295 Mon 1 Nov 1582 */
|
||||
int32_t DOY_DATA[] = {
|
||||
// dom, woy, doy
|
||||
1, 40, 274, Calendar::MONDAY,
|
||||
4, 40, 277, Calendar::THURSDAY,
|
||||
15, 40, 278, Calendar::FRIDAY,
|
||||
17, 41, 280, Calendar::SUNDAY,
|
||||
24, 42, 287, Calendar::SUNDAY,
|
||||
25, 42, 288, Calendar::MONDAY,
|
||||
26, 42, 289, Calendar::TUESDAY,
|
||||
27, 42, 290, Calendar::WEDNESDAY,
|
||||
28, 42, 291, Calendar::THURSDAY,
|
||||
29, 42, 292, Calendar::FRIDAY,
|
||||
30, 42, 293, Calendar::SATURDAY,
|
||||
31, 43, 294, Calendar::SUNDAY
|
||||
};
|
||||
int32_t DOY_DATA_length = sizeof(DOY_DATA) / sizeof(DOY_DATA[0]);
|
||||
for (i=0; i<DOY_DATA_length; i+=4) {
|
||||
// Test time->fields
|
||||
cal.set(1582, Calendar::OCTOBER, DOY_DATA[i]);
|
||||
int32_t woy = cal.get(Calendar::WEEK_OF_YEAR, status);
|
||||
int32_t doy = cal.get(Calendar::DAY_OF_YEAR, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Error: get() failed");
|
||||
break;
|
||||
}
|
||||
if (woy != DOY_DATA[i+1] || doy != DOY_DATA[i+2]) {
|
||||
errln((UnicodeString)"Fail: expect woy=" + DOY_DATA[i+1] +
|
||||
", doy=" + DOY_DATA[i+2] + " on " +
|
||||
fmt.format(cal.getTime(status), temp.remove()));
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// Test fields->time for WOY
|
||||
cal.clear();
|
||||
cal.set(Calendar::YEAR, 1582);
|
||||
cal.set(Calendar::WEEK_OF_YEAR, DOY_DATA[i+1]);
|
||||
cal.set(Calendar::DAY_OF_WEEK, DOY_DATA[i+3]);
|
||||
int32_t dom = cal.get(Calendar::DAY_OF_MONTH, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Error: get() failed");
|
||||
break;
|
||||
}
|
||||
if (dom != DOY_DATA[i]) {
|
||||
errln((UnicodeString)"Fail: set woy=" + DOY_DATA[i+1] +
|
||||
" dow=" + DOY_DATA[i+3] + " => " +
|
||||
fmt.format(cal.getTime(status), temp.remove()) +
|
||||
", expected 1582 Oct " + DOY_DATA[i]);
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// Test fields->time for DOY
|
||||
cal.clear();
|
||||
cal.set(Calendar::YEAR, 1582);
|
||||
cal.set(Calendar::DAY_OF_YEAR, DOY_DATA[i+2]);
|
||||
dom = cal.get(Calendar::DAY_OF_MONTH, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Error: get() failed");
|
||||
break;
|
||||
}
|
||||
if (dom != DOY_DATA[i]) {
|
||||
errln((UnicodeString)"Fail: set doy=" + DOY_DATA[i+2] +
|
||||
" => " +
|
||||
fmt.format(cal.getTime(status), temp.remove()) +
|
||||
", expected 1582 Oct " + DOY_DATA[i]);
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
|
||||
// Test cases
|
||||
enum Action { ADD=1, ROLL=2 };
|
||||
enum Sign { PLUS=1, MINUS=2 };
|
||||
struct {
|
||||
Calendar::EDateFields field;
|
||||
int8_t actionMask; // ADD or ROLL or both
|
||||
int8_t signMask; // PLUS or MINUS or both
|
||||
int32_t amount;
|
||||
int32_t before; // ms before cutover
|
||||
int32_t after; // ms after cutover
|
||||
} DATA[] = {
|
||||
{ Calendar::WEEK_OF_YEAR, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
|
||||
{ Calendar::WEEK_OF_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
|
||||
{ Calendar::DAY_OF_MONTH, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
|
||||
{ Calendar::DAY_OF_MONTH, ROLL, PLUS, -6, -ONE_DAY, +14*ONE_DAY },
|
||||
{ Calendar::DAY_OF_MONTH, ROLL, PLUS, -7, 0, +14*ONE_DAY },
|
||||
{ Calendar::DAY_OF_MONTH, ROLL, PLUS, -7, +ONE_DAY, +15*ONE_DAY },
|
||||
{ Calendar::DAY_OF_MONTH, ROLL, PLUS, +18, -ONE_DAY, -4*ONE_DAY },
|
||||
{ Calendar::DAY_OF_YEAR, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
|
||||
{ Calendar::DAY_OF_WEEK, ADD|ROLL, PLUS|MINUS, 2, -ONE_DAY, +1*ONE_DAY },
|
||||
{ Calendar::DAY_OF_WEEK_IN_MONTH, ADD|ROLL, PLUS|MINUS, 1, -ONE_DAY, +6*ONE_DAY },
|
||||
{ Calendar::AM_PM, ADD, PLUS|MINUS, 4, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
{ Calendar::HOUR, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
{ Calendar::HOUR_OF_DAY, ADD, PLUS|MINUS, 48, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
{ Calendar::MINUTE, ADD, PLUS|MINUS, 48*60, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
{ Calendar::SECOND, ADD, PLUS|MINUS, 48*60*60, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
{ Calendar::MILLISECOND, ADD, PLUS|MINUS, 48*ONE_HOUR, -12*ONE_HOUR, +36*ONE_HOUR },
|
||||
// NOTE: These are not supported yet. See jitterbug 180.
|
||||
// Uncomment these lines when add/roll supported on these fields.
|
||||
// { Calendar::YEAR_WOY, ADD|ROLL, 1, -ONE_DAY, +6*ONE_DAY },
|
||||
// { Calendar::DOW_LOCAL, ADD|ROLL, 2, -ONE_DAY, +1*ONE_DAY }
|
||||
};
|
||||
int32_t DATA_length = sizeof(DATA) / sizeof(DATA[0]);
|
||||
|
||||
// Now run the tests
|
||||
for (i=0; i<DATA_length; ++i) {
|
||||
for (Action action=ADD; action<=ROLL; action=(Action)(action+1)) {
|
||||
if (!(DATA[i].actionMask & action)) {
|
||||
continue;
|
||||
}
|
||||
for (Sign sign=PLUS; sign<=MINUS; sign=(Sign)(sign+1)) {
|
||||
if (!(DATA[i].signMask & sign)) {
|
||||
continue;
|
||||
}
|
||||
status = U_ZERO_ERROR;
|
||||
int32_t amount = DATA[i].amount * (sign==MINUS?-1:1);
|
||||
UDate date = cutover +
|
||||
(sign==PLUS>0 ? DATA[i].before : DATA[i].after);
|
||||
UDate expected = cutover +
|
||||
(sign==PLUS>0 ? DATA[i].after : DATA[i].before);
|
||||
cal.setTime(date, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"FAIL: setTime returned error code " + status);
|
||||
continue;
|
||||
}
|
||||
if (action == ADD) {
|
||||
cal.add(DATA[i].field, amount, status);
|
||||
} else {
|
||||
cal.roll(DATA[i].field, amount, status);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"FAIL: " +
|
||||
(action==ADD?"add ":"roll ") + FIELD_NAME[DATA[i].field] +
|
||||
" returned error code " + status);
|
||||
continue;
|
||||
}
|
||||
UDate result = cal.getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"FAIL: getTime returned error code " + status);
|
||||
continue;
|
||||
}
|
||||
if (result == expected) {
|
||||
logln((UnicodeString)"Ok: {" +
|
||||
fmt.format(date, temp.remove()) +
|
||||
"}(" + date/ONE_DAY +
|
||||
(action==ADD?") add ":") roll ") +
|
||||
amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
|
||||
fmt.format(result, temp2.remove()) +
|
||||
"}(" + result/ONE_DAY + ")");
|
||||
} else {
|
||||
errln((UnicodeString)"FAIL: {" +
|
||||
fmt.format(date, temp.remove()) +
|
||||
"}(" + date/ONE_DAY +
|
||||
(action==ADD?") add ":") roll ") +
|
||||
amount + " " + FIELD_NAME[DATA[i].field] + " -> {" +
|
||||
fmt.format(result, temp2.remove()) +
|
||||
"}(" + result/ONE_DAY + "), expect {" +
|
||||
fmt.format(expected, temp3.remove()) +
|
||||
"}(" + expected/ONE_DAY + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UDate
|
||||
CalendarRegressionTest::makeDate(int32_t y, int32_t m, int32_t d,
|
||||
int32_t hr, int32_t min, int32_t sec)
|
||||
|
|
|
@ -65,7 +65,8 @@ public:
|
|||
void Test4165343(void) ;
|
||||
void Test4166109(void) ;
|
||||
void Test4167060(void) ;
|
||||
void Test4197699();
|
||||
void Test4197699(void);
|
||||
void TestJ81(void);
|
||||
|
||||
void printdate(GregorianCalendar *cal, char *string);
|
||||
void dowTest(bool_t lenient) ;
|
||||
|
@ -76,6 +77,7 @@ public:
|
|||
|
||||
static const UDate EARLIEST_SUPPORTED_MILLIS;
|
||||
static const UDate LATEST_SUPPORTED_MILLIS;
|
||||
static const char* FIELD_NAME[];
|
||||
|
||||
protected:
|
||||
bool_t failure(UErrorCode status, const char* msg);
|
||||
|
|
Loading…
Add table
Reference in a new issue