summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBustamam Harun <bustamam@openoffice.org>2002-09-16 18:57:32 +0000
committerBustamam Harun <bustamam@openoffice.org>2002-09-16 18:57:32 +0000
commit003d3fedb5ef26f38d7b77ad6f45c7d72399c9d7 (patch)
treed10ef111d0ffd1e84d87703405763b6a9aca1acb
parent0043384f51863bafc2e40b3ccd14016fc486eb74 (diff)
#102027# Fix date offset problem with Hijri Calendar
-rw-r--r--i18npool/inc/calendar_hijri.hxx5
-rw-r--r--i18npool/source/calendar/calendar_hijri.cxx106
2 files changed, 69 insertions, 42 deletions
diff --git a/i18npool/inc/calendar_hijri.hxx b/i18npool/inc/calendar_hijri.hxx
index 6aa2537be905..90f508e2ae67 100644
--- a/i18npool/inc/calendar_hijri.hxx
+++ b/i18npool/inc/calendar_hijri.hxx
@@ -2,9 +2,9 @@
*
* $RCSfile: calendar_hijri.hxx,v $
*
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
*
- * last change: $Author: bustamam $ $Date: 2002-08-15 03:10:04 $
+ * last change: $Author: bustamam $ $Date: 2002-09-16 19:57:32 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -109,6 +109,7 @@ private:
double NewMoon(sal_Int32 n);
void getHijri(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year);
void ToGregorian(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year);
+ void getGregorianDay(sal_Int32 jd, sal_Int32 *pnDay, sal_Int32 *pnMonth, sal_Int32 *pnYear);
double getJulianDay(sal_Int32 day, sal_Int32 month, sal_Int32 year);
};
diff --git a/i18npool/source/calendar/calendar_hijri.cxx b/i18npool/source/calendar/calendar_hijri.cxx
index 4c8fdd155edd..8ec00c29d9be 100644
--- a/i18npool/source/calendar/calendar_hijri.cxx
+++ b/i18npool/source/calendar/calendar_hijri.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: calendar_hijri.cxx,v $
*
- * $Revision: 1.4 $
+ * $Revision: 1.5 $
*
- * last change: $Author: bustamam $ $Date: 2002-08-15 03:09:37 $
+ * last change: $Author: bustamam $ $Date: 2002-09-16 19:57:02 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -70,6 +70,8 @@ using namespace ::rtl;
#define ERROR RuntimeException()
+#define GREGORIAN_CROSSOVER 2299161
+
static UErrorCode status; // status is shared in all calls to Calendar, it has to be reset for each call.
// radians per degree (pi/180)
@@ -110,14 +112,14 @@ void SAL_CALL Calendar_hijri::mapToGregorian() throw(RuntimeException)
sal_Int32 month = (sal_Int32)fieldSetValue[CalendarFieldIndex::MONTH] + 1;
sal_Int32 year = (sal_Int32)fieldSetValue[CalendarFieldIndex::YEAR];
if (fieldSetValue[CalendarFieldIndex::ERA] == 0)
- year = 1 - year;
+ year *= -1;
ToGregorian(&day, &month, &year);
fieldSetValue[CalendarFieldIndex::ERA] = year <= 0 ? 0 : 1;
fieldSetValue[CalendarFieldIndex::MONTH] = (sal_Int32) (month - 1);
fieldSetValue[CalendarFieldIndex::DAY_OF_MONTH] = (sal_Int16) day;
- fieldSetValue[CalendarFieldIndex::YEAR] = (sal_Int16) year;
+ fieldSetValue[CalendarFieldIndex::YEAR] = (sal_Int16) abs(year);
fieldSet |= FIELDS;
}
}
@@ -131,14 +133,14 @@ void SAL_CALL Calendar_hijri::mapFromGregorian() throw(RuntimeException)
month = (sal_Int32)fieldValue[CalendarFieldIndex::MONTH] + 1;
year = (sal_Int32)fieldValue[CalendarFieldIndex::YEAR];
if (fieldValue[CalendarFieldIndex::ERA] == 0)
- year = 1 - year;
+ year *= -1;
// Get Hijri date
getHijri(&day, &month, &year);
fieldValue[CalendarFieldIndex::DAY_OF_MONTH] = (sal_Int16)day;
fieldValue[CalendarFieldIndex::MONTH] = month - 1;
- fieldValue[CalendarFieldIndex::YEAR] = (sal_Int16)year;
+ fieldValue[CalendarFieldIndex::YEAR] = (sal_Int16) abs(year);
fieldValue[CalendarFieldIndex::ERA] = (sal_Int16) year < 1 ? 0 : 1;
}
@@ -228,20 +230,6 @@ Calendar_hijri::getHijri(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
do {
newjd = NewMoon(newsyn);
- dayfraction = (newjd - (sal_Int32)newjd); // Get fraction of day
-
- // If new moon appears during the first half of the day, take the next day
- if (dayfraction <= 0.5) {
- newjd += 1.0;
- }
-
- // Convert to localtime (assuming Mecca)
- dayfraction = (dayfraction - 0.5) * 24.0 + SA_TimeZone;
-
- // if new moon starts after second half of the day
- if (dayfraction > EveningPeriod) {
- newjd += 1.0;
- }
// Decrement syndonic months
newsyn--;
@@ -262,11 +250,11 @@ Calendar_hijri::getHijri(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
// If month negative, consider it previous year
if (syndiff != 0 && *month <= 0) {
*month += 12;
- *year--;
+ (*year)--;
}
// If Before Hijri subtract 1
- if (*year <= 0) *year--;
+ if (*year <= 0) (*year)--;
}
void
@@ -277,10 +265,10 @@ Calendar_hijri::ToGregorian(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
double jday;
sal_Int32 dayint;
- if ( *year < 0 ) *year++;
+ if ( *year < 0 ) (*year)++;
// Number of month from reference point
- nmonth = (*month + 1) + *year * 12 - (GregRef * 12 + 1);
+ nmonth = *month + *year * 12 - (GregRef * 12 + 1);
// Add Synodic Reference point
nmonth += SynRef;
@@ -288,24 +276,62 @@ Calendar_hijri::ToGregorian(sal_Int32 *day, sal_Int32 *month, sal_Int32 *year)
// Get Julian days add time too
jday = NewMoon(nmonth) + *day;
- // Convert the julian day to Gregorian
- jday = jday - 1721119;
- *year = (4 * jday - 1)/146097;
- jday = 4 * jday - 1 - 146097 * *year;
- *day = jday/4;
- jday = (4 * *day + 3) /1461;
- *day = 4 * *day + 3 - 1461 * jday;
- *day = (*day + 4) /4;
- *month = (5 * *day - 3) / 153;
- *day = 5 * *day - 3 - 153 * *month;
- *day = (*day + 5) / 5;
- *year = 100 * *year + jday;
- if ( *month < 10 ) {
- *month = *month + 3;
+ // Round-up
+ jday = (double)((sal_Int32)(jday + 0.5));
+
+ // Use algorithm from "Numerical Recipes in C"
+ getGregorianDay((sal_Int32)jday, day, month, year);
+
+ // Julian -> Gregorian only works for non-negative year
+ if ( *year <= 0 ) {
+ *day = -1;
+ *month = -1;
+ *year = -1;
+ }
+}
+
+/* this algorithm is taken from "Numerical Recipes in C", 2nd ed, pp 14-15. */
+/* this algorithm only valid for non-negative gregorian year
+void
+Calendar_hijri::getGregorianDay(sal_Int32 lJulianDay, sal_Int32 *pnDay, sal_Int32 *pnMonth, sal_Int32 *pnYear)
+{
+ /* working variables */
+ long lFactorA, lFactorB, lFactorC, lFactorD, lFactorE;
+ long lAdjust;
+
+ /* test whether to adjust for the Gregorian calendar crossover */
+ if (lJulianDay >= GREGORIAN_CROSSOVER) {
+ /* calculate a small adjustment */
+ lAdjust = (long) (((float) (lJulianDay - 1867216) - 0.25) / 36524.25);
+
+ lFactorA = lJulianDay + 1 + lAdjust - ((long) (0.25 * lAdjust));
+
} else {
- *month = *month - 9;
- *year = *year + 1;
+ /* no adjustment needed */
+ lFactorA = lJulianDay;
}
+
+ lFactorB = lFactorA + 1524;
+ lFactorC = (long) (6680.0 + ((float) (lFactorB - 2439870) - 122.1) / 365.25);
+ lFactorD = (long) (365 * lFactorC + (0.25 * lFactorC));
+ lFactorE = (long) ((lFactorB - lFactorD) / 30.6001);
+
+ /* now, pull out the day number */
+ *pnDay = lFactorB - lFactorD - (long) (30.6001 * lFactorE);
+
+ /* ...and the month, adjusting it if necessary */
+ *pnMonth = lFactorE - 1;
+ if (*pnMonth > 12)
+ (*pnMonth) -= 12;
+
+ /* ...and similarly for the year */
+ *pnYear = lFactorC - 4715;
+ if (*pnMonth > 2)
+ (*pnYear)--;
+
+// Negative year adjustments
+ if (*pnYear <= 0)
+ (*pnYear)--;
}
double