|
From: Lutter, C. <chr...@sa...> - 2009-04-02 15:39:59
|
Hello,
The Islamic calendar of the ICU currently supports civil and non civil
calendar by calculation of the month start.
There are a few ways to calculate the non civil (religious) Islamic
calendar, which was already discussed here.
However in our case a customization of the month start is needed
(although rarely).
In case this requirement exists for other developers, here is how the
calendar can be customized:
class ICUIslamicCalendar extends com.ibm.icu.util.IslamicCalendar {
// for own customization of month start
private CalendarCache customizedCache = new CalendarCache();
@Override
protected void handleComputeFields(int julianDay) {
int year, month, dayOfMonth, dayOfYear;
long days = julianDay - 1948440;
{
// guess the month start
int months = (int) Math.floor(days /
CalendarAstronomer.SYNODIC_MONTH);
/*
* Always also check the next month, since
customization can
* differ. It can differ for not more than 3
days. so that
* checking the next month is enough.
*/
months++;
/*
* Check the true month start for the given
month. If it is
* later, check the previous month, until a
suitable is found.
*/
while (getCustomMonthStart(months) > days) {
months--;
}
year = months / 12 + 1;
month = months % 12;
}
dayOfMonth = (int) (days - getCustomMonthStart(12 *
(year - 1) + month)) + 1;
// Now figure out the day of the year.
dayOfYear = (int) (days - getCustomMonthStart(12 * (year
- 1)) + 1);
internalSet(ERA, 0);
internalSet(YEAR, year);
internalSet(EXTENDED_YEAR, year);
internalSet(MONTH, month);
internalSet(DAY_OF_MONTH, dayOfMonth);
internalSet(DAY_OF_YEAR, dayOfYear);
}
@Override
protected int handleComputeMonthStart(int eyear, int month,
boolean useMonth) {
long months = 12 * (eyear - 1) + month;
int daysFromHijraTo1970 = 1948439; // Hijra = 7/16/622
return (int) getCustomMonthStart(months) +
daysFromHijraTo1970;
}
@Override
protected int handleGetMonthLength(int extendedYear, int month)
{
int months = 12 * (extendedYear - 1) + month;
int length = (int) (getCustomMonthStart(months + 1) -
getCustomMonthStart(months));
return length;
}
@Override
protected int handleGetYearLength(int extendedYear) {
int months = 12*(extendedYear-1);
return (int)(getCustomMonthStart(months + 12) -
getCustomMonthStart(months));
}
private long getCustomMonthStart(long months) {
long start = customizedCache.get(months);
if (start == CalendarCache.EMPTY) {
start = // whatever
customizedCache.put(months, start);
}
return start;
}
}
Here the customizedCache object is not static, because different
customizations might exist.
A flag to set customization instead of civil calendar is not used. I
assume that in case no customization exists, the civil calculation is
correct. Finally civil flag is ignored.
Best regards
Christian
|