/** * Return the number of days in the given Islamic year * @draft ICU 2.4 */ int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const { if (cType == CIVIL || cType == TBLA || (cType == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) { return 354 + (civilLeapYear(extendedYear) ? 1 : 0); } else if(cType == ASTRONOMICAL){ int32_t month = 12*(extendedYear-1); return (trueMonthStart(month + 12) - trueMonthStart(month)); } else { int len = 0; for(int i=0; i<12; i++) len += handleGetMonthLength(extendedYear, i); return len; } }
/** * Return the day # on which the given month starts. Days are counted * from the Hijri epoch, origin 0. * * @param year The hijri year * @param year The hijri month, 0-based */ int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const { if (cType == CIVIL || cType == TBLA) { return (int32_t)uprv_ceil(29.5*month) + (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*year),30); } else if(cType==ASTRONOMICAL){ return trueMonthStart(12*(year-1) + month); } else { int32_t ms = yearStart(year); for(int i=0; i< month; i++){ ms+= handleGetMonthLength(year, i); } return ms; } }
int32_t GregorianCalendar::monthLength(int32_t month) const { int32_t year = internalGet(UCAL_EXTENDED_YEAR); return handleGetMonthLength(year, month); }
/** * Override Calendar to compute several fields specific to the Islamic * calendar system. These are: * * <ul><li>ERA * <li>YEAR * <li>MONTH * <li>DAY_OF_MONTH * <li>DAY_OF_YEAR * <li>EXTENDED_YEAR</ul> * * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this * method is called. The getGregorianXxx() methods return Gregorian * calendar equivalents for the given Julian day. * @draft ICU 2.4 */ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) { int32_t year, month, dayOfMonth, dayOfYear; int32_t startDate; int32_t days = julianDay - CIVIL_EPOC; if (cType == CIVIL || cType == TBLA) { if(cType == TBLA) { days = julianDay - ASTRONOMICAL_EPOC; } // Use the civil calendar approximation, which is just arithmetic year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 ); month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); month = month<11?month:11; startDate = monthStart(year, month); } else if(cType == ASTRONOMICAL){ // Guess at the number of elapsed full months since the epoch int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); startDate = (int32_t)uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH); double age = moonAge(internalGetTime(), status); if (U_FAILURE(status)) { status = U_MEMORY_ALLOCATION_ERROR; return; } if ( days - startDate >= 25 && age > 0) { // If we're near the end of the month, assume next month and search backwards months++; } // Find out the last time that the new moon was actually visible at this longitude // This returns midnight the night that the moon was visible at sunset. while ((startDate = trueMonthStart(months)) > days) { // If it was after the date in question, back up a month and try again months--; } year = months / 12 + 1; month = months % 12; } else if(cType == UMALQURA) { int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ; if( days < umalquraStartdays){ //Use Civil calculation year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 ); month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); month = month<11?month:11; startDate = monthStart(year, month); }else{ int y =UMALQURA_YEAR_START-1, m =0; long d = 1; while(d > 0){ y++; d = days - yearStart(y) +1; if(d == handleGetYearLength(y)){ m=11; break; }else if(d < handleGetYearLength(y) ){ int monthLen = handleGetMonthLength(y, m); m=0; while(d > monthLen){ d -= monthLen; m++; monthLen = handleGetMonthLength(y, m); } break; } } year = y; month = m; } } else { // invalid 'civil' U_ASSERT(false); // should not get here, out of range year=month=0; } dayOfMonth = (days - monthStart(year, month)) + 1; // Now figure out the day of the year. dayOfYear = (days - monthStart(year, 0)) + 1; internalSet(UCAL_ERA, 0); internalSet(UCAL_YEAR, year); internalSet(UCAL_EXTENDED_YEAR, year); internalSet(UCAL_MONTH, month); internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); internalSet(UCAL_DAY_OF_YEAR, dayOfYear); }