aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/icu/i18n/islamcal.cpp
diff options
context:
space:
mode:
authorromankoshelev <romankoshelev@yandex-team.com>2023-08-14 19:51:50 +0300
committerromankoshelev <romankoshelev@yandex-team.com>2023-08-15 01:24:11 +0300
commitcfcd865e05c0d0525ea27d1e153a043b32a85138 (patch)
tree68d3b3b25271e8a4998505897a269ff7ce119b76 /contrib/libs/icu/i18n/islamcal.cpp
parentccb790c507bd5e8ffe2ef9886ce5ee0a7ce22a15 (diff)
downloadydb-cfcd865e05c0d0525ea27d1e153a043b32a85138.tar.gz
Update ICU to 73.2
Diffstat (limited to 'contrib/libs/icu/i18n/islamcal.cpp')
-rw-r--r--contrib/libs/icu/i18n/islamcal.cpp607
1 files changed, 411 insertions, 196 deletions
diff --git a/contrib/libs/icu/i18n/islamcal.cpp b/contrib/libs/icu/i18n/islamcal.cpp
index de37e6b939..c21530a736 100644
--- a/contrib/libs/icu/i18n/islamcal.cpp
+++ b/contrib/libs/icu/i18n/islamcal.cpp
@@ -54,20 +54,20 @@ static void debug_islamcal_msg(const char *pat, ...)
// --- The cache --
// cache of months
-static icu::CalendarCache *gMonthCache = NULL;
-static icu::CalendarAstronomer *gIslamicCalendarAstro = NULL;
+static icu::CalendarCache *gMonthCache = nullptr;
+static icu::CalendarAstronomer *gIslamicCalendarAstro = nullptr;
U_CDECL_BEGIN
-static UBool calendar_islamic_cleanup(void) {
+static UBool calendar_islamic_cleanup() {
if (gMonthCache) {
delete gMonthCache;
- gMonthCache = NULL;
+ gMonthCache = nullptr;
}
if (gIslamicCalendarAstro) {
delete gIslamicCalendarAstro;
- gIslamicCalendarAstro = NULL;
+ gIslamicCalendarAstro = nullptr;
}
- return TRUE;
+ return true;
}
U_CDECL_END
@@ -206,67 +206,22 @@ int32_t getUmalqura_MonthLength(int32_t y, int32_t m) {
//-------------------------------------------------------------------------
const char *IslamicCalendar::getType() const {
- const char *sType = NULL;
-
- switch (cType) {
- case CIVIL:
- sType = "islamic-civil";
- break;
- case ASTRONOMICAL:
- sType = "islamic";
- break;
- case TBLA:
- sType = "islamic-tbla";
- break;
- case UMALQURA:
- sType = "islamic-umalqura";
- break;
- default:
- UPRV_UNREACHABLE_EXIT; // out of range
- }
- return sType;
+ return "islamic";
}
IslamicCalendar* IslamicCalendar::clone() const {
return new IslamicCalendar(*this);
}
-IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success, ECalculationType type)
-: Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success),
-cType(type)
+IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success)
+: Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success)
{
setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
}
-IslamicCalendar::IslamicCalendar(const IslamicCalendar& other) : Calendar(other), cType(other.cType) {
-}
-
IslamicCalendar::~IslamicCalendar()
{
}
-
-void IslamicCalendar::setCalculationType(ECalculationType type, UErrorCode &status)
-{
- if (cType != type) {
- // The fields of the calendar will become invalid, because the calendar
- // rules are different
- UDate m = getTimeInMillis(status);
- cType = type;
- clear();
- setTimeInMillis(m, status);
- }
-}
-
-/**
-* Returns <code>true</code> if this object is using the fixed-cycle civil
-* calendar, or <code>false</code> if using the religious, astronomical
-* calendar.
-* @draft ICU 2.4
-*/
-UBool IslamicCalendar::isCivil() {
- return (cType == CIVIL);
-}
-
//-------------------------------------------------------------------------
// Minimum / Maximum access functions
//-------------------------------------------------------------------------
@@ -304,6 +259,7 @@ static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = {
{/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
{/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
{/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH
+ { 0, 0, 11, 11}, // ORDINAL_MONTH
};
/**
@@ -365,19 +321,7 @@ UBool IslamicCalendar::civilLeapYear(int32_t year)
* from the Hijri epoch, origin 0.
*/
int32_t IslamicCalendar::yearStart(int32_t year) const{
- if (cType == CIVIL || cType == TBLA ||
- (cType == UMALQURA && (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END)))
- {
- return (year-1)*354 + ClockMath::floorDivide((3+11*(int64_t)year),(int64_t)30);
- } else if(cType==ASTRONOMICAL){
- return trueMonthStart(12*(year-1));
- } else {
- year -= UMALQURA_YEAR_START;
- // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration
- int32_t yrStartLinearEstimate = (int32_t)((354.36720 * (double)year) + 460322.05 + 0.5);
- // need a slight correction to some
- return yrStartLinearEstimate + umAlQuraYrStartEstimateFix[year];
- }
+ return trueMonthStart(12*(year-1));
}
/**
@@ -388,19 +332,7 @@ int32_t IslamicCalendar::yearStart(int32_t year) const{
* @param month The hijri month, 0-based (assumed to be in range 0..11)
*/
int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const {
- if (cType == CIVIL || cType == TBLA) {
- // This does not handle months out of the range 0..11
- return (int32_t)uprv_ceil(29.5*month)
- + (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*(int64_t)year),(int64_t)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;
- }
+ return trueMonthStart(12*(year-1) + month);
}
/**
@@ -473,9 +405,9 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status)
static UMutex astroLock; // pod bay door lock
umtx_lock(&astroLock);
- if(gIslamicCalendarAstro == NULL) {
+ if(gIslamicCalendarAstro == nullptr) {
gIslamicCalendarAstro = new CalendarAstronomer();
- if (gIslamicCalendarAstro == NULL) {
+ if (gIslamicCalendarAstro == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
return age;
}
@@ -506,22 +438,8 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status)
* @draft ICU 2.4
*/
int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
-
- int32_t length = 0;
-
- if (cType == CIVIL || cType == TBLA ||
- (cType == UMALQURA && (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END)) ) {
- length = 29 + (month+1) % 2;
- if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
- length++;
- }
- } else if(cType == ASTRONOMICAL){
- month = 12*(extendedYear-1) + month;
- length = trueMonthStart(month+1) - trueMonthStart(month) ;
- } else {
- length = getUmalqura_MonthLength(extendedYear - UMALQURA_YEAR_START, month);
- }
- return length;
+ month = 12*(extendedYear-1) + month;
+ return trueMonthStart(month+1) - trueMonthStart(month) ;
}
/**
@@ -529,19 +447,8 @@ int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t mont
* @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;
- }
+ int32_t month = 12*(extendedYear-1);
+ return (trueMonthStart(month + 12) - trueMonthStart(month));
}
//-------------------------------------------------------------------------
@@ -567,8 +474,8 @@ int32_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, U
eyear += (month / 12) - 1;
month = (month % 12) + 11;
}
- return monthStart(eyear, month) + ((cType == TBLA)? ASTRONOMICAL_EPOC: CIVIL_EPOC) - 1;
-}
+ return monthStart(eyear, month) + getEpoc() - 1;
+}
//-------------------------------------------------------------------------
// Functions for converting from milliseconds to field values
@@ -604,105 +511,97 @@ int32_t IslamicCalendar::handleGetExtendedYear() {
* @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 (U_FAILURE(status)) return;
+ int32_t days = julianDay - getEpoc();
- if (cType == CIVIL || cType == TBLA) {
- if(cType == TBLA) {
- days = julianDay - ASTRONOMICAL_EPOC;
- }
- // Use the civil calendar approximation, which is just arithmetic
- year = (int32_t)ClockMath::floorDivide(30 * (int64_t)days + 10646, (int64_t)10631);
- 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);
+ // Guess at the number of elapsed full months since the epoch
+ int32_t month = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH);
- startDate = (int32_t)uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH);
+ int32_t startDate = (int32_t)uprv_floor(month * 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--;
- }
+ 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
+ month++;
+ }
- year = months >= 0 ? ((months / 12) + 1) : ((months + 1 ) / 12);
- month = ((months % 12) + 12 ) % 12;
- } else if(cType == UMALQURA) {
- int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ;
- if( days < umalquraStartdays){
- //Use Civil calculation
- year = (int32_t)ClockMath::floorDivide(
- (30 * (int64_t)days + 10646) , (int64_t)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'
- UPRV_UNREACHABLE_EXIT; // should not get here, out of range
+ // 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(month)) > days) {
+ // If it was after the date in question, back up a month and try again
+ month--;
}
- dayOfMonth = (days - monthStart(year, month)) + 1;
+ int32_t year = month >= 0 ? ((month / 12) + 1) : ((month + 1 ) / 12);
+ month = ((month % 12) + 12 ) % 12;
+ int32_t dayOfMonth = (days - monthStart(year, month)) + 1;
// Now figure out the day of the year.
- dayOfYear = (days - monthStart(year, 0)) + 1;
-
+ int32_t 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_ORDINAL_MONTH, month);
internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
- internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
-}
+ internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
+}
+
+int32_t IslamicCalendar::getEpoc() const {
+ return CIVIL_EPOC;
+}
-UBool
-IslamicCalendar::inDaylightTime(UErrorCode& status) const
+static int32_t gregoYearFromIslamicStart(int32_t year) {
+ // ad hoc conversion, improve under #10752
+ // rough est for now, ok for grego 1846-2138,
+ // otherwise occasionally wrong (for 3% of years)
+ int cycle, offset, shift = 0;
+ if (year >= 1397) {
+ cycle = (year - 1397) / 67;
+ offset = (year - 1397) % 67;
+ shift = 2*cycle + ((offset >= 33)? 1: 0);
+ } else {
+ cycle = (year - 1396) / 67 - 1;
+ offset = -(year - 1396) % 67;
+ shift = 2*cycle + ((offset <= 33)? 1: 0);
+ }
+ return year + 579 - shift;
+}
+
+int32_t IslamicCalendar::getRelatedYear(UErrorCode &status) const
{
- // copied from GregorianCalendar
- if (U_FAILURE(status) || !getTimeZone().useDaylightTime())
- return FALSE;
+ int32_t year = get(UCAL_EXTENDED_YEAR, status);
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ return gregoYearFromIslamicStart(year);
+}
- // Force an update of the state of the Calendar.
- ((IslamicCalendar*)this)->complete(status); // cast away const
+static int32_t firstIslamicStartYearFromGrego(int32_t year) {
+ // ad hoc conversion, improve under #10752
+ // rough est for now, ok for grego 1846-2138,
+ // otherwise occasionally wrong (for 3% of years)
+ int cycle, offset, shift = 0;
+ if (year >= 1977) {
+ cycle = (year - 1977) / 65;
+ offset = (year - 1977) % 65;
+ shift = 2*cycle + ((offset >= 32)? 1: 0);
+ } else {
+ cycle = (year - 1976) / 65 - 1;
+ offset = -(year - 1976) % 65;
+ shift = 2*cycle + ((offset <= 32)? 1: 0);
+ }
+ return year - 579 + shift;
+}
- return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
+void IslamicCalendar::setRelatedYear(int32_t year)
+{
+ set(UCAL_EXTENDED_YEAR, firstIslamicStartYearFromGrego(year));
}
/**
@@ -712,12 +611,12 @@ IslamicCalendar::inDaylightTime(UErrorCode& status) const
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
-static icu::UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
+static icu::UInitOnce gSystemDefaultCenturyInit {};
UBool IslamicCalendar::haveDefaultCentury() const
{
- return TRUE;
+ return true;
}
UDate IslamicCalendar::defaultCenturyStart() const
@@ -734,6 +633,14 @@ int32_t IslamicCalendar::defaultCenturyStartYear() const
return gSystemDefaultCenturyStartYear;
}
+bool
+IslamicCalendar::inTemporalLeapYear(UErrorCode &status) const
+{
+ int32_t days = getActualMaximum(UCAL_DAY_OF_YEAR, status);
+ if (U_FAILURE(status)) return false;
+ return days == 355;
+}
+
U_CFUNC void U_CALLCONV
IslamicCalendar::initializeSystemDefaultCentury()
@@ -754,9 +661,317 @@ IslamicCalendar::initializeSystemDefaultCentury()
// out.
}
+/*****************************************************************************
+ * IslamicCivilCalendar
+ *****************************************************************************/
+IslamicCivilCalendar::IslamicCivilCalendar(const Locale& aLocale, UErrorCode& success)
+ : IslamicCalendar(aLocale, success)
+{
+}
+
+IslamicCivilCalendar::~IslamicCivilCalendar()
+{
+}
+
+const char *IslamicCivilCalendar::getType() const {
+ return "islamic-civil";
+}
+
+IslamicCivilCalendar* IslamicCivilCalendar::clone() const {
+ return new IslamicCivilCalendar(*this);
+}
+
+/**
+* Return the day # on which the given year starts. Days are counted
+* from the Hijri epoch, origin 0.
+*/
+int32_t IslamicCivilCalendar::yearStart(int32_t year) const{
+ return static_cast<int32_t>(
+ (year-1)*354 + ClockMath::floorDivide((3+11*static_cast<int64_t>(year)),
+ static_cast<int64_t>(30)));
+}
+
+/**
+* Return the day # on which the given month starts. Days are counted
+* from the Hijri epoch, origin 0.
+*
+* @param year The hijri year
+* @param month The hijri month, 0-based (assumed to be in range 0..11)
+*/
+int32_t IslamicCivilCalendar::monthStart(int32_t year, int32_t month) const {
+ // This does not handle months out of the range 0..11
+ return static_cast<int32_t>(
+ uprv_ceil(29.5*month) + (year-1)*354 +
+ static_cast<int32_t>(ClockMath::floorDivide(
+ 3+11*static_cast<int64_t>(year),
+ static_cast<int64_t>(30))));
+}
+
+/**
+* Return the length (in days) of the given month.
+*
+* @param year The hijri year
+* @param year The hijri month, 0-based
+* @draft ICU 2.4
+*/
+int32_t IslamicCivilCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
+ int32_t length = 29 + (month+1) % 2;
+ if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
+ length++;
+ }
+ return length;
+}
+
+/**
+* Return the number of days in the given Islamic year
+* @draft ICU 2.4
+*/
+int32_t IslamicCivilCalendar::handleGetYearLength(int32_t extendedYear) const {
+ return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
+}
+
+/**
+* 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 IslamicCivilCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
+ if (U_FAILURE(status)) return;
+ int32_t days = julianDay - getEpoc();
+
+ // Use the civil calendar approximation, which is just arithmetic
+ int32_t year = static_cast<int32_t>(
+ ClockMath::floorDivide(30 * static_cast<int64_t>(days) + 10646,
+ static_cast<int64_t>(10631)));
+ int32_t month = static_cast<int32_t>(
+ uprv_ceil((days - 29 - yearStart(year)) / 29.5 ));
+ month = month<11?month:11;
+
+ int32_t dayOfMonth = (days - monthStart(year, month)) + 1;
+
+ // Now figure out the day of the year.
+ int32_t 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_ORDINAL_MONTH, month);
+ internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
+ internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
+}
+/*****************************************************************************
+ * IslamicTBLACalendar
+ *****************************************************************************/
+IslamicTBLACalendar::IslamicTBLACalendar(const Locale& aLocale, UErrorCode& success)
+ : IslamicCivilCalendar(aLocale, success)
+{
+}
+
+IslamicTBLACalendar::~IslamicTBLACalendar()
+{
+}
+
+const char *IslamicTBLACalendar::getType() const {
+ return "islamic-tbla";
+}
+
+IslamicTBLACalendar* IslamicTBLACalendar::clone() const {
+ return new IslamicTBLACalendar(*this);
+}
+
+int32_t IslamicTBLACalendar::getEpoc() const {
+ return ASTRONOMICAL_EPOC;
+}
+
+/*****************************************************************************
+ * IslamicUmalquraCalendar
+ *****************************************************************************/
+IslamicUmalquraCalendar::IslamicUmalquraCalendar(const Locale& aLocale, UErrorCode& success)
+ : IslamicCalendar(aLocale, success)
+{
+}
+
+IslamicUmalquraCalendar::~IslamicUmalquraCalendar()
+{
+}
+const char *IslamicUmalquraCalendar::getType() const {
+ return "islamic-umalqura";
+}
+
+IslamicUmalquraCalendar* IslamicUmalquraCalendar::clone() const {
+ return new IslamicUmalquraCalendar(*this);
+}
+
+/**
+* Return the day # on which the given year starts. Days are counted
+* from the Hijri epoch, origin 0.
+*/
+int32_t IslamicUmalquraCalendar::yearStart(int32_t year) const {
+ if (year < UMALQURA_YEAR_START || year > UMALQURA_YEAR_END) {
+ return static_cast<int32_t>(
+ (year-1)*354 + ClockMath::floorDivide((3+11*static_cast<int64_t>(year)),
+ static_cast<int64_t>(30)));
+ }
+ year -= UMALQURA_YEAR_START;
+ // rounded least-squares fit of the dates previously calculated from UMALQURA_MONTHLENGTH iteration
+ int32_t yrStartLinearEstimate = static_cast<int32_t>(
+ (354.36720 * (double)year) + 460322.05 + 0.5);
+ // need a slight correction to some
+ return yrStartLinearEstimate + umAlQuraYrStartEstimateFix[year];
+}
+
+/**
+* Return the day # on which the given month starts. Days are counted
+* from the Hijri epoch, origin 0.
+*
+* @param year The hijri year
+* @param month The hijri month, 0-based (assumed to be in range 0..11)
+*/
+int32_t IslamicUmalquraCalendar::monthStart(int32_t year, int32_t month) const {
+ int32_t ms = yearStart(year);
+ for(int i=0; i< month; i++){
+ ms+= handleGetMonthLength(year, i);
+ }
+ return ms;
+}
+
+/**
+* Return the length (in days) of the given month.
+*
+* @param year The hijri year
+* @param year The hijri month, 0-based
+*/
+int32_t IslamicUmalquraCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
+ int32_t length = 0;
+ if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) {
+ length = 29 + (month+1) % 2;
+ if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
+ length++;
+ }
+ return length;
+ }
+ return getUmalqura_MonthLength(extendedYear - UMALQURA_YEAR_START, month);
+}
+
+/**
+* Return the number of days in the given Islamic year
+* @draft ICU 2.4
+*/
+int32_t IslamicUmalquraCalendar::handleGetYearLength(int32_t extendedYear) const {
+ if (extendedYear<UMALQURA_YEAR_START || extendedYear>UMALQURA_YEAR_END) {
+ return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
+ }
+ int len = 0;
+ for(int i=0; i<12; i++) {
+ len += handleGetMonthLength(extendedYear, i);
+ }
+ return len;
+}
+
+/**
+* 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 IslamicUmalquraCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
+ if (U_FAILURE(status)) return;
+ int32_t year, month, dayOfMonth, dayOfYear;
+ int32_t days = julianDay - getEpoc();
+
+ int32_t umalquraStartdays = yearStart(UMALQURA_YEAR_START) ;
+ if (days < umalquraStartdays) {
+ //Use Civil calculation
+ year = (int32_t)ClockMath::floorDivide(
+ (30 * (int64_t)days + 10646) , (int64_t)10631.0 );
+ month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 );
+ month = month < 11 ? month : 11;
+ } 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;
+ }
+ 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;
+ }
+
+ 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_ORDINAL_MONTH, month);
+ internalSet(UCAL_DAY_OF_MONTH, dayOfMonth);
+ internalSet(UCAL_DAY_OF_YEAR, dayOfYear);
+}
+/*****************************************************************************
+ * IslamicRGSACalendar
+ *****************************************************************************/
+IslamicRGSACalendar::IslamicRGSACalendar(const Locale& aLocale, UErrorCode& success)
+ : IslamicCalendar(aLocale, success)
+{
+}
+
+IslamicRGSACalendar::~IslamicRGSACalendar()
+{
+}
+
+const char *IslamicRGSACalendar::getType() const {
+ return "islamic-rgsa";
+}
+
+IslamicRGSACalendar* IslamicRGSACalendar::clone() const {
+ return new IslamicRGSACalendar(*this);
+}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCivilCalendar)
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicUmalquraCalendar)
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicTBLACalendar)
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicRGSACalendar)
U_NAMESPACE_END