ICU-6887 Fix day-of-month calculations in Islamic calendar - add back to limits test

X-SVN-Rev: 27665
This commit is contained in:
John Emmons 2010-02-25 00:03:49 +00:00
parent 2d25e02751
commit 078862d761
4 changed files with 43 additions and 24 deletions

View File

@ -1,6 +1,6 @@
/* /*
****************************************************************************** ******************************************************************************
* Copyright (C) 2003-2008, International Business Machines Corporation * Copyright (C) 2003-2010, International Business Machines Corporation
* and others. All Rights Reserved. * and others. All Rights Reserved.
****************************************************************************** ******************************************************************************
* *
@ -232,7 +232,7 @@ int32_t IslamicCalendar::trueMonthStart(int32_t month) const
if (start==0) { if (start==0) {
// Make a guess at when the month started, using the average length // Make a guess at when the month started, using the average length
UDate origin = HIJRA_MILLIS UDate origin = HIJRA_MILLIS
+ uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH - 1) * kOneDay; + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH) * kOneDay;
// moonAge will fail due to memory allocation error // moonAge will fail due to memory allocation error
double age = moonAge(origin, status); double age = moonAge(origin, status);
@ -405,14 +405,14 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
// Guess at the number of elapsed full months since the epoch // Guess at the number of elapsed full months since the epoch
int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH);
startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH - 1); startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH);
double age = moonAge(internalGetTime(), status); double age = moonAge(internalGetTime(), status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
return; return;
} }
if ( days - startDate >= 28 && age > 0) { if ( days - startDate >= 25 && age > 0) {
// If we're near the end of the month, assume next month and search backwards // If we're near the end of the month, assume next month and search backwards
months++; months++;
} }

View File

@ -142,25 +142,27 @@ CalendarLimitTest::TestCalendarExtremeLimit()
void void
CalendarLimitTest::TestLimits(void) { CalendarLimitTest::TestLimits(void) {
static const UDate DEFAULT_START = 944006400000.0; // 1999-12-01T00:00Z static const UDate DEFAULT_START = 944006400000.0; // 1999-12-01T00:00Z
static const int32_t DEFAULT_END = -120; // Default for non-quick is run 2 minutes
static const struct { static const struct {
const char *type; const char *type;
UBool hasLeapMonth; UBool hasLeapMonth;
UDate actualTestStart; UDate actualTestStart;
int32_t actualTestEnd;
} TestCases[] = { } TestCases[] = {
{"gregorian", FALSE, DEFAULT_START}, {"gregorian", FALSE, DEFAULT_START, DEFAULT_END},
{"japanese", FALSE, 596937600000.0}, // 1988-12-01T00:00Z, Showa 63 {"japanese", FALSE, 596937600000.0, DEFAULT_END}, // 1988-12-01T00:00Z, Showa 63
{"buddhist", FALSE, DEFAULT_START}, {"buddhist", FALSE, DEFAULT_START, DEFAULT_END},
{"roc", FALSE, DEFAULT_START}, {"roc", FALSE, DEFAULT_START, DEFAULT_END},
{"persian", FALSE, DEFAULT_START}, {"persian", FALSE, DEFAULT_START, DEFAULT_END},
{"islamic-civil", FALSE, DEFAULT_START}, {"islamic-civil", FALSE, DEFAULT_START, DEFAULT_END},
//{"islamic", FALSE, DEFAULT_START}, // TODO: there is a bug in monthlength calculation {"islamic", FALSE, DEFAULT_START, 800000}, // Approx. 2250 years from now, after which some rounding errors occur in Islamic calendar
{"hebrew", TRUE, DEFAULT_START}, {"hebrew", TRUE, DEFAULT_START, DEFAULT_END},
{"chinese", TRUE, DEFAULT_START}, {"chinese", TRUE, DEFAULT_START, DEFAULT_END},
{"indian", FALSE, DEFAULT_START}, {"indian", FALSE, DEFAULT_START, DEFAULT_END},
{"coptic", FALSE, DEFAULT_START}, {"coptic", FALSE, DEFAULT_START, DEFAULT_END},
{"ethiopic", FALSE, DEFAULT_START}, {"ethiopic", FALSE, DEFAULT_START, DEFAULT_END},
{"ethiopic-amete-alem", FALSE, DEFAULT_START}, {"ethiopic-amete-alem", FALSE, DEFAULT_START, DEFAULT_END},
{NULL, FALSE, 0.0} {NULL, FALSE, 0.0}
}; };
@ -183,7 +185,7 @@ CalendarLimitTest::TestLimits(void) {
} }
// Do the test // Do the test
doTheoreticalLimitsTest(*cal, TestCases[i].hasLeapMonth); doTheoreticalLimitsTest(*cal, TestCases[i].hasLeapMonth);
doLimitsTest(*cal, TestCases[i].actualTestStart); doLimitsTest(*cal, TestCases[i].actualTestStart,TestCases[i].actualTestEnd);
delete cal; delete cal;
} }
} }
@ -260,8 +262,8 @@ CalendarLimitTest::doTheoreticalLimitsTest(Calendar& cal, UBool leapMonth) {
} }
void void
CalendarLimitTest::doLimitsTest(Calendar& cal, UDate startDate) { CalendarLimitTest::doLimitsTest(Calendar& cal, UDate startDate, int32_t endTime) {
int32_t testTime = quick ? -3 : -120; int32_t testTime = quick ? ( endTime / 40 ) : endTime;
doLimitsTest(cal, NULL /*default fields*/, startDate, testTime); doLimitsTest(cal, NULL /*default fields*/, startDate, testTime);
} }

View File

@ -1,6 +1,6 @@
/******************************************************************** /********************************************************************
* COPYRIGHT: * COPYRIGHT:
* Copyright (c) 1997-2008, International Business Machines Corporation and * Copyright (c) 1997-2010, International Business Machines Corporation and
* others. All Rights Reserved. * others. All Rights Reserved.
********************************************************************/ ********************************************************************/
@ -78,7 +78,7 @@ private:
/** /**
* doLimitsTest with default test duration and fields * doLimitsTest with default test duration and fields
*/ */
void doLimitsTest(Calendar& cal, UDate startDate); void doLimitsTest(Calendar& cal, UDate startDate, int32_t endTime);
UnicodeString& ymdToString(const Calendar& cal, UnicodeString& str); UnicodeString& ymdToString(const Calendar& cal, UnicodeString& str);
}; };

View File

@ -2078,6 +2078,8 @@ void CalendarTest::Test3785()
{ {
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
UnicodeString uzone = UNICODE_STRING_SIMPLE("Europe/Paris"); UnicodeString uzone = UNICODE_STRING_SIMPLE("Europe/Paris");
UnicodeString exp1 = UNICODE_STRING_SIMPLE("Mon 30 Jumada II 1433 AH, 01:47:03");
UnicodeString exp2 = UNICODE_STRING_SIMPLE("Mon 1 Rajab 1433 AH, 01:47:04");
LocalUDateFormatPointer df(udat_open(UDAT_NONE, UDAT_NONE, "en@calendar=islamic", uzone.getTerminatedBuffer(), LocalUDateFormatPointer df(udat_open(UDAT_NONE, UDAT_NONE, "en@calendar=islamic", uzone.getTerminatedBuffer(),
uzone.length(), NULL, 0, &status)); uzone.length(), NULL, 0, &status));
@ -2092,15 +2094,30 @@ void CalendarTest::Test3785()
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status); udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
if (U_FAILURE(status)) return; if (U_FAILURE(status)) {
errln("Error formatting date 1\n");
return;
}
//printf("formatted: '%s'\n", mkcstr(ubuffer)); //printf("formatted: '%s'\n", mkcstr(ubuffer));
UnicodeString act1(ubuffer);
if ( act1 != exp1 ) {
errln("Unexpected result from date 1 format\n");
}
ud0 += 1000.0; // add one second ud0 += 1000.0; // add one second
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status); udat_format(df.getAlias(), ud0, ubuffer, 1024, NULL, &status);
if (U_FAILURE(status)) return; if (U_FAILURE(status)) {
errln("Error formatting date 2\n");
return;
}
//printf("formatted: '%s'\n", mkcstr(ubuffer)); //printf("formatted: '%s'\n", mkcstr(ubuffer));
UnicodeString act2(ubuffer);
if ( act2 != exp2 ) {
errln("Unexpected result from date 2 format\n");
}
return; return;
} }