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.
******************************************************************************
*
@ -232,7 +232,7 @@ int32_t IslamicCalendar::trueMonthStart(int32_t month) const
if (start==0) {
// Make a guess at when the month started, using the average length
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
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
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);
if (U_FAILURE(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
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
months++;
}

View File

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

View File

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2008, International Business Machines Corporation and
* Copyright (c) 1997-2010, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
@ -78,7 +78,7 @@ private:
/**
* 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);
};

View File

@ -2078,6 +2078,8 @@ void CalendarTest::Test3785()
{
UErrorCode status = U_ZERO_ERROR;
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(),
uzone.length(), NULL, 0, &status));
@ -2092,15 +2094,30 @@ void CalendarTest::Test3785()
status = U_ZERO_ERROR;
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));
UnicodeString act1(ubuffer);
if ( act1 != exp1 ) {
errln("Unexpected result from date 1 format\n");
}
ud0 += 1000.0; // add one second
status = U_ZERO_ERROR;
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));
UnicodeString act2(ubuffer);
if ( act2 != exp2 ) {
errln("Unexpected result from date 2 format\n");
}
return;
}