ICU-8449 ICU4J Islamic Umm Al-Qura calendar updates based on Yoshito's review.

X-SVN-Rev: 34445
This commit is contained in:
Yoshito Umaoka 2013-09-23 05:15:07 +00:00
parent 86ce4329cd
commit cb99f40912
2 changed files with 132 additions and 91 deletions

View file

@ -354,9 +354,9 @@ public class IslamicCalendar extends Calendar {
*
*/
public boolean isCivil() {
if(cType == CalculationType.ISLAMIC_CIVIL) {
if(cType == CalculationType.ISLAMIC_CIVIL) {
return true;
}
}
return false;
}
@ -399,77 +399,77 @@ public class IslamicCalendar extends Calendar {
*/
private static final int[] UMALQURA_MONTHLENGTH = {
//* 1318 -1322 */ "0101 0111 0100", "1001 0111 0110", "0100 1011 0111", "0010 0101 0111", "0101 0010 1011",
0x0574, 0x0975, 0x06A7, 0x0257, 0x052B,
//* 1323 -1327 */ "0110 1001 0101", "0110 1100 1010", "1010 1101 0101", "0101 0101 1011", "0010 0101 1101",
0x0695, 0x06CA, 0x0AD5, 0x055B, 0x025B,
//* 1328 -1332 */ "1001 0010 1101", "1100 1001 0101", "1101 0100 1010", "1110 1010 0101", "0110 1101 0010",
0x092D, 0x0C95, 0x0D4A, 0x0E5B, 0x025B,
//* 1333 -1337 */ "1010 1101 0101", "0101 0101 1010", "1010 1010 1011", "0100 0100 1011", "0110 1010 0101",
0x0AD5, 0x055A, 0x0AAB, 0x044B, 0x06A5,
//* 1338 -1342 */ "0111 0101 0010", "1011 1010 1001", "0011 0111 0100", "1010 1011 0110", "0101 0101 0110",
0x0752, 0x0BA9, 0x0374, 0x0AB6, 0x0556,
//* 1343 -1347 */ "1010 1010 1010", "1101 0101 0010", "1101 1010 1001", "0101 1101 0100", "1010 1110 1010",
0x0AAA, 0x0D52, 0x0DA9, 0x05D4, 0x0AEA,
//* 1348 -1352 */ "0100 1101 1101", "0010 0110 1110", "1001 0010 1110", "1010 1010 0110", "1101 0101 0100",
0x04DD, 0x026E, 0x092E, 0x0AA6, 0x0D54,
//* 1353 -1357 */ "0101 1010 1010", "0101 1011 0101", "0010 1011 0100", "1001 0011 0111", "0100 1001 1011",
0x05AA, 0x05B5, 0x02B4, 0x0937, 0x049B,
//* 1358 -1362 */ "1010 0100 1011", "1011 0010 0101", "1011 0101 0100", "1011 0110 1010", "0101 0110 1101",
0x0A4B, 0x0B25, 0x0B54, 0x0B6A, 0x056D,
//* 1363 -1367 */ "0100 1010 1101", "1010 0101 0101", "1101 0010 0101", "1110 1001 0010", "1110 1100 1001",
0x04AD, 0x0A55, 0x0D25, 0x0E92, 0x0EC9,
//* 1368 -1372 */ "0110 1101 0100", "1010 1110 1010", "0101 0110 1011", "0100 1010 1011", "0110 1000 0101",
0x06D4, 0x0ADA, 0x056B, 0x04AB, 0x0685,
//* 1373 -1377 */ "1011 0100 1001", "1011 1010 0100", "1011 1011 0010", "0101 1011 0101", "0010 1011 1010",
0x0B49, 0x0BA4, 0x0BB2, 0x05B5, 0x02BA,
//* 1378 -1382 */ "1001 0101 1011", "0100 1010 1011", "0101 0101 0101", "0110 1011 0010", "0110 1101 1001",
0x095B, 0x04AB, 0x0555, 0x06B2, 0x06D9,
//* 1383 -1387 */ "0010 1110 1100", "1001 0110 1110", "0100 1010 1110", "1010 0101 0110", "1101 0010 1010",
0x02EC, 0x096E, 0x04AE, 0x0A56, 0x0D2A,
//* 1388 -1392 */ "1101 0101 0101", "0101 1010 1010", "1010 1011 0101", "0100 1011 1011", "0000 0101 1011",
0x0D55, 0x05AA, 0x0AB5, 0x04BB, 0x005B,
//* 1393 -1397 */ "1001 0010 1011", "1010 1001 0101", "0011 0100 1010", "1011 1010 0101", "0101 1010 1010",
0x092B, 0x0A95, 0x034A, 0x0BA5, 0x05AA,
//* 1398 -1402 */ "1010 1011 0101", "0101 0101 0110", "1010 1001 0110", "1101 0100 1010", "1110 1010 0101",
0x0AB5, 0x0556, 0x0A96, 0x0B4A, 0x0EA5,
//* 1403 -1407 */ "0111 0101 0010", "0110 1110 1001", "0011 0110 1010", "1010 1010 1101", "0101 0101 0101",
0x0752, 0x06E9, 0x036A, 0x0AAD, 0x0555,
//* 1408 -1412 */ "1010 1010 0101", "1011 0101 0010", "1011 1010 1001", "0101 1011 0100", "1001 1011 1010",
0x0AA5, 0x0B52, 0x0BA9, 0x05B4, 0x09BA,
//* 1413 -1417 */ "0100 1101 1011", "0010 0101 1101", "0101 0010 1101", "1010 1010 0101", "1010 1101 0100",
0x04DB, 0x025D, 0x052D, 0x0AA5, 0x0AD4,
//* 1418 -1422 */ "1010 1110 1010", "0101 0110 1101", "0100 1011 1101", "0010 0011 1101", "1001 0001 1101",
0x0AEA, 0x056D, 0x04BD, 0x023D, 0x091D,
//* 1423 -1427 */ "1010 1001 0101", "1011 0100 1010", "1011 0101 1010", "0101 0110 1101", "0010 1011 0110",
0x0A95, 0x0B4A, 0x0B5A, 0x056D, 0x02B6,
//* 1428 -1432 */ "1001 0011 1011", "0100 1001 1011", "0110 0101 0101", "0110 1010 1001", "0111 0101 0100",
0x093B, 0x049B, 0x0655, 0x06A9, 0x0754,
//* 1433 -1437 */ "1011 0110 1010", "0101 0110 1100", "1010 1010 1101", "0101 0101 0101", "1011 0010 1001",
0x0B6A, 0x056C, 0x0AAD, 0x0555, 0x0B29,
//* 1438 -1442 */ "1011 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010", "0101 0101 1010",
0x0B92, 0x0BA9, 0x05D4, 0x0ADA, 0x055A,
//* 1443 -1447 */ "1010 1010 1011", "0101 1001 0101", "0111 0100 1001", "0111 0110 0100", "1011 1010 1010",
0x0AAB, 0x0595, 0x0749, 0x0764, 0x0BAA,
0x0574, 0x0975, 0x06A7, 0x0257, 0x052B,
//* 1323 -1327 */ "0110 1001 0101", "0110 1100 1010", "1010 1101 0101", "0101 0101 1011", "0010 0101 1101",
0x0695, 0x06CA, 0x0AD5, 0x055B, 0x025B,
//* 1328 -1332 */ "1001 0010 1101", "1100 1001 0101", "1101 0100 1010", "1110 1010 0101", "0110 1101 0010",
0x092D, 0x0C95, 0x0D4A, 0x0E5B, 0x025B,
//* 1333 -1337 */ "1010 1101 0101", "0101 0101 1010", "1010 1010 1011", "0100 0100 1011", "0110 1010 0101",
0x0AD5, 0x055A, 0x0AAB, 0x044B, 0x06A5,
//* 1338 -1342 */ "0111 0101 0010", "1011 1010 1001", "0011 0111 0100", "1010 1011 0110", "0101 0101 0110",
0x0752, 0x0BA9, 0x0374, 0x0AB6, 0x0556,
//* 1343 -1347 */ "1010 1010 1010", "1101 0101 0010", "1101 1010 1001", "0101 1101 0100", "1010 1110 1010",
0x0AAA, 0x0D52, 0x0DA9, 0x05D4, 0x0AEA,
//* 1348 -1352 */ "0100 1101 1101", "0010 0110 1110", "1001 0010 1110", "1010 1010 0110", "1101 0101 0100",
0x04DD, 0x026E, 0x092E, 0x0AA6, 0x0D54,
//* 1353 -1357 */ "0101 1010 1010", "0101 1011 0101", "0010 1011 0100", "1001 0011 0111", "0100 1001 1011",
0x05AA, 0x05B5, 0x02B4, 0x0937, 0x049B,
//* 1358 -1362 */ "1010 0100 1011", "1011 0010 0101", "1011 0101 0100", "1011 0110 1010", "0101 0110 1101",
0x0A4B, 0x0B25, 0x0B54, 0x0B6A, 0x056D,
//* 1363 -1367 */ "0100 1010 1101", "1010 0101 0101", "1101 0010 0101", "1110 1001 0010", "1110 1100 1001",
0x04AD, 0x0A55, 0x0D25, 0x0E92, 0x0EC9,
//* 1368 -1372 */ "0110 1101 0100", "1010 1110 1010", "0101 0110 1011", "0100 1010 1011", "0110 1000 0101",
0x06D4, 0x0ADA, 0x056B, 0x04AB, 0x0685,
//* 1373 -1377 */ "1011 0100 1001", "1011 1010 0100", "1011 1011 0010", "0101 1011 0101", "0010 1011 1010",
0x0B49, 0x0BA4, 0x0BB2, 0x05B5, 0x02BA,
//* 1378 -1382 */ "1001 0101 1011", "0100 1010 1011", "0101 0101 0101", "0110 1011 0010", "0110 1101 1001",
0x095B, 0x04AB, 0x0555, 0x06B2, 0x06D9,
//* 1383 -1387 */ "0010 1110 1100", "1001 0110 1110", "0100 1010 1110", "1010 0101 0110", "1101 0010 1010",
0x02EC, 0x096E, 0x04AE, 0x0A56, 0x0D2A,
//* 1388 -1392 */ "1101 0101 0101", "0101 1010 1010", "1010 1011 0101", "0100 1011 1011", "0000 0101 1011",
0x0D55, 0x05AA, 0x0AB5, 0x04BB, 0x005B,
//* 1393 -1397 */ "1001 0010 1011", "1010 1001 0101", "0011 0100 1010", "1011 1010 0101", "0101 1010 1010",
0x092B, 0x0A95, 0x034A, 0x0BA5, 0x05AA,
//* 1398 -1402 */ "1010 1011 0101", "0101 0101 0110", "1010 1001 0110", "1101 0100 1010", "1110 1010 0101",
0x0AB5, 0x0556, 0x0A96, 0x0B4A, 0x0EA5,
//* 1403 -1407 */ "0111 0101 0010", "0110 1110 1001", "0011 0110 1010", "1010 1010 1101", "0101 0101 0101",
0x0752, 0x06E9, 0x036A, 0x0AAD, 0x0555,
//* 1408 -1412 */ "1010 1010 0101", "1011 0101 0010", "1011 1010 1001", "0101 1011 0100", "1001 1011 1010",
0x0AA5, 0x0B52, 0x0BA9, 0x05B4, 0x09BA,
//* 1413 -1417 */ "0100 1101 1011", "0010 0101 1101", "0101 0010 1101", "1010 1010 0101", "1010 1101 0100",
0x04DB, 0x025D, 0x052D, 0x0AA5, 0x0AD4,
//* 1418 -1422 */ "1010 1110 1010", "0101 0110 1101", "0100 1011 1101", "0010 0011 1101", "1001 0001 1101",
0x0AEA, 0x056D, 0x04BD, 0x023D, 0x091D,
//* 1423 -1427 */ "1010 1001 0101", "1011 0100 1010", "1011 0101 1010", "0101 0110 1101", "0010 1011 0110",
0x0A95, 0x0B4A, 0x0B5A, 0x056D, 0x02B6,
//* 1428 -1432 */ "1001 0011 1011", "0100 1001 1011", "0110 0101 0101", "0110 1010 1001", "0111 0101 0100",
0x093B, 0x049B, 0x0655, 0x06A9, 0x0754,
//* 1433 -1437 */ "1011 0110 1010", "0101 0110 1100", "1010 1010 1101", "0101 0101 0101", "1011 0010 1001",
0x0B6A, 0x056C, 0x0AAD, 0x0555, 0x0B29,
//* 1438 -1442 */ "1011 1001 0010", "1011 1010 1001", "0101 1101 0100", "1010 1101 1010", "0101 0101 1010",
0x0B92, 0x0BA9, 0x05D4, 0x0ADA, 0x055A,
//* 1443 -1447 */ "1010 1010 1011", "0101 1001 0101", "0111 0100 1001", "0111 0110 0100", "1011 1010 1010",
0x0AAB, 0x0595, 0x0749, 0x0764, 0x0BAA,
//* 1448 -1452 */ "0101 1011 0101", "0010 1011 0110", "1010 0101 0110", "1110 0100 1101", "1011 0010 0101",
0x05B5, 0x02B6, 0x0A56, 0x0E4D, 0x0B25,
0x05B5, 0x02B6, 0x0A56, 0x0E4D, 0x0B25,
//* 1453 -1457 */ "1011 0101 0010", "1011 0110 1010", "0101 1010 1101", "0010 1010 1110", "1001 0010 1111",
0x0B52, 0x0B6A, 0x05AD, 0x02AE, 0x092F,
0x0B52, 0x0B6A, 0x05AD, 0x02AE, 0x092F,
//* 1458 -1462 */ "0100 1001 0111", "0110 0100 1011", "0110 1010 0101", "0110 1010 1100", "1010 1101 0110",
0x0497, 0x064B, 0x06A5, 0x06AC, 0x0AD6,
0x0497, 0x064B, 0x06A5, 0x06AC, 0x0AD6,
//* 1463 -1467 */ "0101 0101 1101", "0100 1001 1101", "1010 0100 1101", "1101 0001 0110", "1101 1001 0101",
0x055D, 0x049D, 0x0A4D, 0x0D16, 0x0D95,
0x055D, 0x049D, 0x0A4D, 0x0D16, 0x0D95,
//* 1468 -1472 */ "0101 1010 1010", "0101 1011 0101", "0010 1001 1010", "1001 0101 1011", "0100 1010 1100",
0x05AA, 0x05B5, 0x029A, 0x095B, 0x04AC,
0x05AA, 0x05B5, 0x029A, 0x095B, 0x04AC,
//* 1473 -1477 */ "0101 1001 0101", "0110 1100 1010", "0110 1110 0100", "1010 1110 1010", "0100 1111 0101",
0x0595, 0x06CA, 0x06E4, 0x0AEA, 0x04F5,
//* 1478 -1480 */ "0010 1011 0110", "1001 0101 0110", "1010 1010 1010"
0x02B6, 0x0956, 0x0AAA
0x0595, 0x06CA, 0x06E4, 0x0AEA, 0x04F5,
//* 1478 -1480 */ "0010 1011 0110", "1001 0101 0110", "1010 1010 1010"
0x02B6, 0x0956, 0x0AAA
};
private static final int UMALQURA_YEAR_START = 1318;
private static final int UMALQURA_YEAR_END = 1480;
/**
* @stable ICU 2.8
*/
@ -513,22 +513,22 @@ public class IslamicCalendar extends Calendar {
*/
private long yearStart(int year) {
long ys = 0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
ys = (year-1)*354 + (long)Math.floor((3+11*year)/30.0);
} else if(cType == CalculationType.ISLAMIC) {
ys = trueMonthStart(12*(year-1));
} else if(cType == CalculationType.ISLAMIC_UMALQURA){
ys = yearStart(UMALQURA_YEAR_START -1);
ys += handleGetYearLength(UMALQURA_YEAR_START -1);
for(int i=UMALQURA_YEAR_START; i< year; i++) {
for(int i=UMALQURA_YEAR_START; i< year; i++) {
ys+= handleGetYearLength(i);
}
}
}
return ys;
}
/**
* Return the day # on which the given month starts. Days are counted
* from the Hijri epoch, origin 0.
@ -544,18 +544,18 @@ public class IslamicCalendar extends Calendar {
long ms = 0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
|| (cType == CalculationType.ISLAMIC_UMALQURA && year < UMALQURA_YEAR_START )) {
ms = (long)Math.ceil(29.5*realMonth)
+ (realYear-1)*354 + (long)Math.floor((3+11*realYear)/30.0);
} else if(cType == CalculationType.ISLAMIC) {
ms = trueMonthStart(12*(realYear-1) + realMonth);
} else if(cType == CalculationType.ISLAMIC_UMALQURA) {
ms = yearStart(year);
for(int i=0; i< month; i++) {
for(int i=0; i< month; i++) {
ms+= handleGetMonthLength(year, i);
}
}
return ms;
}
@ -650,6 +650,7 @@ public class IslamicCalendar extends Calendar {
*
* @serial
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
private CalculationType cType = CalculationType.ISLAMIC_CIVIL;
@ -670,7 +671,7 @@ public class IslamicCalendar extends Calendar {
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
length = 29 + (month+1) % 2;
if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
length++;
@ -697,7 +698,7 @@ public class IslamicCalendar extends Calendar {
int length =0;
if (cType == CalculationType.ISLAMIC_CIVIL
|| cType == CalculationType.ISLAMIC_TBLA
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
|| (cType == CalculationType.ISLAMIC_UMALQURA && (extendedYear < UMALQURA_YEAR_START || extendedYear > UMALQURA_YEAR_END) )) {
length = 354 + (civilLeapYear(extendedYear) ? 1 : 0);
} else if (cType == CalculationType.ISLAMIC) {
int month = 12*(extendedYear-1);
@ -706,7 +707,7 @@ public class IslamicCalendar extends Calendar {
for(int i=0; i<12; i++)
length += handleGetMonthLength(extendedYear, i);
}
return length;
}
@ -790,24 +791,24 @@ public class IslamicCalendar extends Calendar {
month = months % 12;
} else if (cType == CalculationType.ISLAMIC_UMALQURA) {
long umalquraStartdays = yearStart(UMALQURA_YEAR_START);
if( days < umalquraStartdays) {
if( days < umalquraStartdays) {
// Use Civil calculation
year = (int)Math.floor( (30 * days + 10646) / 10631.0 );
month = (int)Math.ceil((days - 29 - yearStart(year)) / 29.5 );
month = Math.min(month, 11);
} else {
} else {
int y =UMALQURA_YEAR_START-1, m =0;
long d = 1;
while(d > 0) {
while(d > 0) {
y++;
d = days - yearStart(y) +1;
if(d == handleGetYearLength(y)) {
if(d == handleGetYearLength(y)) {
m=11;
break;
} else if(d < handleGetYearLength(y) ) {
} else if(d < handleGetYearLength(y) ) {
int monthLen = handleGetMonthLength(y, m);
m=0;
while(d > monthLen) {
while(d > monthLen) {
d -= monthLen;
m++;
monthLen = handleGetMonthLength(y, m);
@ -839,14 +840,56 @@ public class IslamicCalendar extends Calendar {
* enumeration of available calendar calculation types
*
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
public enum CalculationType {ISLAMIC, ISLAMIC_CIVIL, ISLAMIC_UMALQURA, ISLAMIC_TBLA};
public enum CalculationType {
/**
* Religious calendar (atronomical simulation)
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
ISLAMIC ("islamic"),
/**
* Tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29]) algorithm
* with civil (Friday) epoch.
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
ISLAMIC_CIVIL ("islamic-civil"),
/**
* Umm al-Qura calendar
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
ISLAMIC_UMALQURA ("islamic-umalqura"),
/**
* Tabular (intercalary years [2,5,7,10,13,16,18,21,24,26,29]) algorithm
* with astronomical (Thursday) epoch.
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
ISLAMIC_TBLA ("islamic-tbla");
private String bcpType;
CalculationType(String bcpType) {
this.bcpType = bcpType;
}
String bcpType() {
return bcpType;
}
};
/**
* sets the calculation type for this calendar.
*
* @draft ICU 52
* @provisional This API might change or be removed in a future release.
*/
// TODO: We should change the method name to setCalculationType, because
// corresponding getter (not yet available) will collide with String getType().
// See ticket#10426.
public void setType(CalculationType type) {
cType = type;
@ -880,15 +923,13 @@ public class IslamicCalendar extends Calendar {
* @stable ICU 3.8
*/
public String getType() {
if(cType == CalculationType.ISLAMIC_CIVIL) {
return "islamic-civil";
} else if (cType == CalculationType.ISLAMIC_TBLA) {
return "islamic-tbla";
} else if (cType == CalculationType.ISLAMIC) {
if (cType == null) {
// TODO: getType() is called during Islamic calendar
// construction and might be null at that point. We should
// check the initialization sequence. See ticket#10425.
return "islamic";
} else {
return "islamic-umalqura";
}
return cType.bcpType();
}
private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException

View file

@ -347,7 +347,7 @@ public class IslamicTest extends CalendarTest {
}
public void Test8449() {
public void TestIslamicUmAlQura() {
int firstYear = 1318;
//* use either 1 or 2 leading slashes to toggle
int lastYear = 1368; // just enough to be pretty sure