[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/kdecore
From:       John Layt <john () layt ! net>
Date:       2010-12-13 1:57:41
Message-ID: 20101213015741.81E71AC8A7 () svn ! kde ! org
[Download RAW message or body]

SVN commit 1205932 by jlayt:

Change algorithm used in calculating Indian National calendar to use the real
formulas defined by the reform comittee rather than a conversion from
Gregorian which should be quicker and more robust.

Tested to confirm match exactly with the old formulas.



 M  +45 -104   date/kcalendarsystemindiannational.cpp  
 M  +2 -0      tests/kcalendartest.cpp  


--- trunk/KDE/kdelibs/kdecore/date/kcalendarsystemindiannational.cpp #1205931:1205932
@@ -19,7 +19,6 @@
 
 #include "kcalendarsystemindiannational_p.h"
 #include "kcalendarsystemprivate_p.h"
-#include "kcalendarsystemgregorianproleptic_p.h"
 
 #include "kdebug.h"
 #include "klocale.h"
@@ -48,21 +47,17 @@
     virtual int maxMonthsInYear() const;
     virtual int earliestValidYear() const;
     virtual int latestValidYear() const;
-
-    KCalendarSystemGregorianProleptic *gregorian;
 };
 
 // Shared d pointer base class definitions
 
 KCalendarSystemIndianNationalPrivate::KCalendarSystemIndianNationalPrivate( \
                KCalendarSystemIndianNational *q )
-                                     :KCalendarSystemPrivate( q ),
-                                      gregorian( new \
KCalendarSystemGregorianProleptic ) +                                     \
:KCalendarSystemPrivate( q )  {
 }
 
 KCalendarSystemIndianNationalPrivate::~KCalendarSystemIndianNationalPrivate()
 {
-    delete gregorian;
 }
 
 KLocale::CalendarSystem KCalendarSystemIndianNationalPrivate::calendarSystem() const
@@ -120,10 +115,23 @@
 bool KCalendarSystemIndianNationalPrivate::isLeapYear( int year ) const
 {
     //Uses same rule as Gregorian, and is explicitly synchronized to Gregorian
-    //so add 78 years to get Gregorian year and call Gregorian implementation
-    return gregorian->isLeapYear( year + 78 );
+    //so add 78 years to get Gregorian year and apply Gregorian calculation
+    year = year + 78;
+    if ( !hasYearZero() && year < 1 ) {
+        year = year + 1;
 }
 
+    if ( year % 4 == 0 ) {
+        if ( year % 100 != 0 ) {
+            return true;
+        } else if ( year % 400 == 0 ) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 bool KCalendarSystemIndianNationalPrivate::hasLeapMonths() const
 {
     return false;
@@ -564,111 +572,44 @@
 
 bool KCalendarSystemIndianNational::julianDayToDate( int jd, int &year, int &month, \
int &day ) const  {
-    Q_D( const KCalendarSystemIndianNational );
+    int L, N, I, J, D, M, Y;
 
-    // The calendar is closely synchronized to the Gregorian Calendar, always \
                starting on the same day
-    // We can use this and the regular sequence of days in months to do a simple \
                conversion by finding
-    // what day in the Gregorian year the Julian Day number is, converting this to \
                the day in the
-    // Indian year and subtracting off the required number of months and days to get \
the final date +    // "Explanatory Supplement to the Astronomical Almanac" 2006 \
section 12.94 pp 605-606 +    // Originally from "Report of the Calendar Reform \
Committee" 1955 +    L = jd + 68518;
+    N = ( 4 * L ) / 146097;
+    L = L - ( 146097 * N + 3 ) / 4;
+    I = ( 4000 * ( L + 1 ) ) / 1461001;
+    L = L - ( 1461 * I ) / 4 + 1;
+    J = ( ( L - 1 ) / 31 ) * ( 1 - L / 185 ) + ( L / 185 ) * ( ( L - 156 ) / 30 + 5 \
) - L / 366; +    D = L - 31 * J + ( ( J + 2 ) / 8 ) * ( J - 5 );
+    L = J / 11;
+    M = J + 2 - 12 * L;
+    Y = 100 * ( N - 49 ) + L + I - 78;
 
-    // Calculate the Day of Year in the Gregorian calendar
-    // Need to use julianDayToDate() and dateToJulianDay() to calculate instead of \
                QDate::fromJulianDay()
-    // and dayOfYear() to avoid the Gregorian year > 9999 validation check
-    int gregorianYear, gregorianMonth, gregorianDay, jdGregorianFirstDayOfYear;
-    d->gregorian->julianDayToDate( jd, gregorianYear, gregorianMonth, gregorianDay \
                );
-    d->gregorian->dateToJulianDay( gregorianYear, 1, 1, jdGregorianFirstDayOfYear );
-    int gregorianDayOfYear = jd - jdGregorianFirstDayOfYear + 1;
+    day = D;
+    month = M;
+    year = Y;
 
-    // There is a fixed 78 year difference between year numbers, but the years do \
                not exactly match up,
-    // there is a fixed 80 day difference between the first day of the year, if the \
                Gregorian day of
-    // the year is 80 or less then the equivalent Indian day actually falls in the \
                preceding  year
-    if ( gregorianDayOfYear > 80 ) {
-        year = gregorianYear - 78;
-    } else {
-        year = gregorianYear - 79;
-    }
-
-    // If it is a leap year then the first month has 31 days, otherwise 30.
-    int daysInMonth1;
-    if ( isLeapYear( year ) ) {
-        daysInMonth1 = 31;
-    } else {
-        daysInMonth1 = 30;
-    }
-
-    // The Indian year always starts 80 days after the Gregorian year, calculate the \
                Indian day of
-    // the year, taking into account if it falls into the previous Gregorian year
-    int indianDayOfYear;
-    if ( gregorianDayOfYear > 80 ) {
-        indianDayOfYear = gregorianDayOfYear - 80;
-    } else {
-        indianDayOfYear = gregorianDayOfYear + ( daysInMonth1 + ( 5 * 31 ) + ( 6 * \
                30 ) ) - 80;
-    }
-
-    // Then simply remove the whole months from the day of the year and you are left \
                with the day of month
-    if ( indianDayOfYear <= daysInMonth1 ) {
-        month = 1;
-        day = indianDayOfYear;
-    } else if ( indianDayOfYear <= ( daysInMonth1 + ( 5 * 31 ) ) ) {
-        month = ( ( indianDayOfYear - daysInMonth1 - 1 ) / 31 ) + 2;
-        day = indianDayOfYear - daysInMonth1 - ( ( month - 2 ) * 31 );
-    } else {
-        month = ( ( indianDayOfYear - daysInMonth1 - ( 5 * 31 ) - 1 ) / 30 ) + 7;
-        day = indianDayOfYear - daysInMonth1 - ( 5 * 31 ) - ( ( month - 7 ) * 30 );
-    }
-
     return true;
 }
 
 bool KCalendarSystemIndianNational::dateToJulianDay( int year, int month, int day, \
int &jd ) const  {
-    Q_D( const KCalendarSystemIndianNational );
+    int Y = year;
+    int M = month;
+    int D = day;
 
-    // The calendar is closely synchronized to the Gregorian Calendar, always \
                starting on the same day
-    // We can use this and the regular sequence of days in months to do a simple \
                conversion by finding
-    // the Julian Day number of the first day of the year and adding on the required \
                number of months
-    // and days to get the final Julian Day number
+    // "Explanatory Supplement to the Astronomical Almanac" 2006 section 12.94 pp \
605-606 +    // Originally from "Report of the Calendar Reform Committee" 1955
+    jd = 365 * Y
+         + ( Y + 78 - 1 / M ) / 4
+         + 31 * M
+         - ( M + 9 ) / 11
+         - ( M / 7 ) * ( M - 7 )
+         - ( 3 * ( ( Y  + 78 - 1 / M ) / 100 + 1 ) ) / 4
+         + D
+         + 1749579;
 
-    int jdFirstDayOfYear;
-    int daysInMonth1;
-
-    // Calculate the jd of 1 Chaitra for this year and how many days are in Chaitra \
                this year
-    // If a Leap Year, then 1 Chaitra == 21 March of the Gregorian year and Chaitra \
                has 31 days
-    // If not a Leap Year, then 1 Chaitra == 22 March of the Gregorian year and \
                Chaitra has 30 days
-    // Need to use dateToJulianDay() to calculate instead of setDate() to avoid the \
                year 9999 validation
-    if ( isLeapYear( year ) ) {
-        d->gregorian->dateToJulianDay( year + 78, 3, 21, jdFirstDayOfYear );
-        daysInMonth1 = 31;
-    } else {
-        d->gregorian->dateToJulianDay( year + 78, 3, 22, jdFirstDayOfYear );
-        daysInMonth1 = 30;
-    }
-
-    // Add onto the jd of the first day of the year the number of days required
-    // Calculate the number of days in the months before the required month
-    // Then add on the required days
-    // The first month has 30 or 31 days depending on if it is a Leap Year \
                (determined above)
-    // The second to sixth months have 31 days each
-    // The seventh to twelth months have 30 days each
-    // Note: could be expressed more efficiently, but I think this is clearer
-    if ( month == 1) {
-        jd = jdFirstDayOfYear             // Start with jd of first day of year
-           + day                          // Add on required day in required month
-           - 1;                           // Adjust for fact we double count 1 \
                Chaitra
-    } else if ( month <= 6 ){
-        jd = jdFirstDayOfYear             // Start with jd of first day of year
-           + daysInMonth1                 // Add on days in month 1
-           + ( ( month - 2 ) * 31 )       // Add on days after month 1 up to month \
                before required month
-           + day                          // Add on required day in required month
-           - 1;                           // Adjust for fact we double count 1 \
                Chaitra
-    } else { // month > 6
-        jd = jdFirstDayOfYear             // Start with jd of first day of year
-           + daysInMonth1                 // Add on days in month 1
-           + ( 5 * 31 )                   // Add on days in months 2 to 6
-           + ( ( month - 7 ) * 30 )       // Add on days after month 6 up to month \
                before required month
-           + day                          // Add on required day in required month
-           - 1;                           // Adjust for fact we double count 1 \
                Chaitra
-    }
-
     return true;
 }
--- trunk/KDE/kdelibs/kdecore/tests/kcalendartest.cpp #1205931:1205932
@@ -1335,6 +1335,8 @@
     testYmd( calendar, 1932,  1,  1, QDate( 2010,  3, 22 ).toJulianDay() );
     testYmd( calendar, 1932, 12, 30, QDate( 2011,  3, 21 ).toJulianDay() );
 
+    testRoundTrip( calendar );
+
     delete calendar;
 }
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic