[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