summaryrefslogtreecommitdiffstats
path: root/kdecore/kcalendarsystemhijri.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /kdecore/kcalendarsystemhijri.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kdecore/kcalendarsystemhijri.cpp')
-rw-r--r--kdecore/kcalendarsystemhijri.cpp596
1 files changed, 596 insertions, 0 deletions
diff --git a/kdecore/kcalendarsystemhijri.cpp b/kdecore/kcalendarsystemhijri.cpp
new file mode 100644
index 000000000..c594cf22b
--- /dev/null
+++ b/kdecore/kcalendarsystemhijri.cpp
@@ -0,0 +1,596 @@
+/*
+ Copyright (c) 2002-2003 Carlos Moro <cfmoro@correo.uniovi.es>
+ Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Derived hijri kde calendar class
+
+#include <qdatetime.h>
+#include <qstring.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kcalendarsystemhijri.h"
+
+/*
+ The following C++ code is translated from the Lisp code
+ in ``Calendrical Calculations'' by Nachum Dershowitz and
+ Edward M. Reingold, Software---Practice & Experience,
+ vol. 20, no. 9 (September, 1990), pp. 899--928.
+
+ This code is in the public domain, but any use of it
+ should publically acknowledge its source.
+
+ Classes GregorianDate, IslamicDate
+ */
+
+static int lastDayOfGregorianMonth(int month, int year) {
+// Compute the last date of the month for the Gregorian calendar.
+
+ switch (month) {
+ case 2:
+ if ((((year % 4) == 0) && ((year % 100) != 0))
+ || ((year % 400) == 0))
+ return 29;
+ else
+ return 28;
+ case 4:
+ case 6:
+ case 9:
+ case 11: return 30;
+ default: return 31;
+ }
+}
+
+class GregorianDate {
+private:
+ int year; // 1...
+ int month; // 1 == January, ..., 12 == December
+ int day; // 1..lastDayOfGregorianMonth(month, year)
+
+public:
+ GregorianDate(int m, int d, int y) { month = m; day = d; year = y; }
+
+ GregorianDate(int d) { // Computes the Gregorian date from the absolute date.
+
+ // Search forward year by year from approximate year
+ year = d/366;
+ while (d >= GregorianDate(1,1,year+1))
+ year++;
+ // Search forward month by month from January
+ month = 1;
+ while (d > GregorianDate(month, lastDayOfGregorianMonth(month,year), year))
+ month++;
+ day = d - GregorianDate(month,1,year) + 1;
+ }
+
+ operator int() { // Computes the absolute date from the Gregorian date.
+ int N = day; // days this month
+ for (int m = month - 1; m > 0; m--) // days in prior months this year
+ N = N + lastDayOfGregorianMonth(m, year);
+ return
+ (N // days this year
+ + 365 * (year - 1) // days in previous years ignoring leap days
+ + (year - 1)/4 // Julian leap days before this year...
+ - (year - 1)/100 // ...minus prior century years...
+ + (year - 1)/400); // ...plus prior years divisible by 400
+ }
+
+ int getMonth() { return month; }
+ int getDay() { return day; }
+ int getYear() { return year; }
+
+};
+
+static int IslamicLeapYear(int year) {
+// True if year is an Islamic leap year
+
+ if ((((11 * year) + 14) % 30) < 11)
+ return 1;
+ else
+ return 0;
+}
+
+static const int IslamicEpoch = 227014; // Absolute date of start of
+ // Islamic calendar
+
+static int lastDayOfIslamicMonth(int month, int year) {
+// Last day in month during year on the Islamic calendar.
+
+ if (((month % 2) == 1) || ((month == 12) && IslamicLeapYear(year)))
+ return 30;
+ else
+ return 29;
+}
+
+class IslamicDate {
+private:
+ int year; // 1...
+ int month; // 1..13 (12 in a common year)
+ int day; // 1..lastDayOfIslamicMonth(month,year)
+
+public:
+ IslamicDate(int m, int d, int y) { month = m; day = d; year = y; }
+
+ IslamicDate(int d) { // Computes the Islamic date from the absolute date.
+ if (d <= IslamicEpoch) { // Date is pre-Islamic
+ month = 0;
+ day = 0;
+ year = 0;
+ }
+ else {
+ // Search forward year by year from approximate year
+ year = (d - IslamicEpoch) / 355;
+ while (d >= IslamicDate(1,1,year+1))
+ year++;
+ // Search forward month by month from Muharram
+ month = 1;
+ while (d > IslamicDate(month, lastDayOfIslamicMonth(month,year), year))
+ month++;
+ day = d - IslamicDate(month,1,year) + 1;
+ }
+ }
+
+ operator int() { // Computes the absolute date from the Islamic date.
+ return (day // days so far this month
+ + 29 * (month - 1) // days so far...
+ + month/2 // ...this year
+ + 354 * (year - 1) // non-leap days in prior years
+ + (3 + (11 * year)) / 30 // leap days in prior years
+ + IslamicEpoch); // days before start of calendar
+ }
+
+ int getMonth() { return month; }
+ int getDay() { return day; }
+ int getYear() { return year; }
+
+};
+
+static void gregorianToHijri(const QDate & date, int * pYear, int * pMonth,
+ int * pDay)
+{
+ GregorianDate gregorian(date.month(),date.day(),date.year());
+ int absolute = gregorian;
+
+ IslamicDate islamic(absolute);
+
+ if (pYear)
+ *pYear = islamic.getYear();
+ if (pMonth)
+ *pMonth = islamic.getMonth();
+ if (pDay)
+ *pDay = islamic.getDay();
+}
+
+KCalendarSystemHijri::KCalendarSystemHijri(const KLocale * locale)
+ : KCalendarSystem(locale)
+{
+}
+
+KCalendarSystemHijri::~KCalendarSystemHijri()
+{
+}
+
+int KCalendarSystemHijri::year(const QDate& date) const
+{
+ int y;
+ gregorianToHijri(date, &y, 0, 0);
+ return y;
+}
+
+int KCalendarSystemHijri::month(const QDate& date) const
+{
+ int m;
+ gregorianToHijri(date, 0, &m, 0);
+ return m;
+}
+
+int KCalendarSystemHijri::day(const QDate& date) const
+{
+ int d;
+ gregorianToHijri(date, 0, 0, &d);
+ return d;
+}
+
+int KCalendarSystemHijri::monthsInYear( const QDate & date ) const
+{
+ Q_UNUSED( date )
+
+ return 12;
+}
+
+int KCalendarSystemHijri::weeksInYear(int year) const
+{
+ QDate temp;
+ setYMD(temp, year, 12, lastDayOfIslamicMonth(12, year));
+
+ // If the last day of the year is in the first week, we have to check the
+ // week before
+ if ( weekNumber(temp) == 1 )
+ temp = addDays(temp, -7);
+
+ return weekNumber(temp);
+}
+
+int KCalendarSystemHijri::weekNumber(const QDate& date, int * yearNum) const
+{
+ QDate firstDayWeek1, lastDayOfYear;
+ int y = year(date);
+ int week;
+ int weekDay1, dayOfWeek1InYear;
+
+ // let's guess 1st day of 1st week
+ setYMD(firstDayWeek1, y, 1, 1);
+ weekDay1 = dayOfWeek(firstDayWeek1);
+
+ // iso 8601: week 1 is the first containing thursday and week starts on
+ // monday
+ if (weekDay1 > 4 )
+ firstDayWeek1 = addDays(firstDayWeek1 , 7 - weekDay1 + 1); // next monday
+
+ dayOfWeek1InYear = dayOfYear(firstDayWeek1);
+
+ if ( dayOfYear(date) < dayOfWeek1InYear ) // our date in prev year's week
+ {
+ if ( yearNum )
+ *yearNum = y - 1;
+ return weeksInYear(y - 1);
+ }
+
+ // let' check if its last week belongs to next year
+ setYMD(lastDayOfYear, y, 12, lastDayOfIslamicMonth(12, y));
+ if ( (dayOfYear(date) >= daysInYear(date) - dayOfWeek(lastDayOfYear) + 1)
+ // our date is in last week
+ && dayOfWeek(lastDayOfYear) < 4) // 1st week in next year has thursday
+ {
+ if ( yearNum )
+ *yearNum = y + 1;
+ week = 1;
+ }
+ else
+ {
+ if ( weekDay1 < 5 )
+ firstDayWeek1 = addDays(firstDayWeek1, - (weekDay1 - 1));
+
+ week = firstDayWeek1.daysTo(date) / 7 + 1;
+ }
+
+ return week;
+}
+
+QString KCalendarSystemHijri::monthName(const QDate& date,
+ bool shortName) const
+{
+ return monthName(month(date), year(date), shortName);
+}
+
+QString KCalendarSystemHijri::monthNamePossessive(const QDate& date,
+ bool shortName) const
+{
+ return monthNamePossessive(month(date), year(date), shortName);
+}
+
+QString KCalendarSystemHijri::monthName(int month, int year, bool shortName)
+ const {
+
+ Q_UNUSED(year);
+
+ if (shortName)
+ switch ( month )
+ {
+ case 1:
+ return locale()->translate("Muharram");
+ case 2:
+ return locale()->translate("Safar");
+ case 3:
+ return locale()->translate("R. Awal");
+ case 4:
+ return locale()->translate("R. Thaani");
+ case 5:
+ return locale()->translate("J. Awal");
+ case 6:
+ return locale()->translate("J. Thaani");
+ case 7:
+ return locale()->translate("Rajab");
+ case 8:
+ return locale()->translate("Sha`ban");
+ case 9:
+ return locale()->translate("Ramadan");
+ case 10:
+ return locale()->translate("Shawwal");
+ case 11:
+ return locale()->translate("Qi`dah");
+ case 12:
+ return locale()->translate("Hijjah");
+ }
+ else
+ switch ( month )
+ {
+ case 1:
+ return locale()->translate("Muharram");
+ case 2:
+ return locale()->translate("Safar");
+ case 3:
+ return locale()->translate("Rabi` al-Awal");
+ case 4:
+ return locale()->translate("Rabi` al-Thaani");
+ case 5:
+ return locale()->translate("Jumaada al-Awal");
+ case 6:
+ return locale()->translate("Jumaada al-Thaani");
+ case 7:
+ return locale()->translate("Rajab");
+ case 8:
+ return locale()->translate("Sha`ban");
+ case 9:
+ return locale()->translate("Ramadan");
+ case 10:
+ return locale()->translate("Shawwal");
+ case 11:
+ return locale()->translate("Thu al-Qi`dah");
+ case 12:
+ return locale()->translate("Thu al-Hijjah");
+ }
+
+ return QString::null;
+}
+
+QString KCalendarSystemHijri::monthNamePossessive(int month, int year,
+ bool shortName) const
+{
+ Q_UNUSED(year);
+
+ if (shortName)
+ switch ( month )
+ {
+ case 1:
+ return locale()->translate("of Muharram");
+ case 2:
+ return locale()->translate("of Safar");
+ case 3:
+ return locale()->translate("of R. Awal");
+ case 4:
+ return locale()->translate("of R. Thaani");
+ case 5:
+ return locale()->translate("of J. Awal");
+ case 6:
+ return locale()->translate("of J. Thaani");
+ case 7:
+ return locale()->translate("of Rajab");
+ case 8:
+ return locale()->translate("of Sha`ban");
+ case 9:
+ return locale()->translate("of Ramadan");
+ case 10:
+ return locale()->translate("of Shawwal");
+ case 11:
+ return locale()->translate("of Qi`dah");
+ case 12:
+ return locale()->translate("of Hijjah");
+ }
+ else
+ switch ( month )
+ {
+ case 1:
+ return locale()->translate("of Muharram");
+ case 2:
+ return locale()->translate("of Safar");
+ case 3:
+ return locale()->translate("of Rabi` al-Awal");
+ case 4:
+ return locale()->translate("of Rabi` al-Thaani");
+ case 5:
+ return locale()->translate("of Jumaada al-Awal");
+ case 6:
+ return locale()->translate("of Jumaada al-Thaani");
+ case 7:
+ return locale()->translate("of Rajab");
+ case 8:
+ return locale()->translate("of Sha`ban");
+ case 9:
+ return locale()->translate("of Ramadan");
+ case 10:
+ return locale()->translate("of Shawwal");
+ case 11:
+ return locale()->translate("of Thu al-Qi`dah");
+ case 12:
+ return locale()->translate("of Thu al-Hijjah");
+ }
+
+ return QString::null;
+}
+
+bool KCalendarSystemHijri::setYMD(QDate & date, int y, int m, int d) const
+{
+ // range checks
+ if ( y < minValidYear() || y > maxValidYear() )
+ return false;
+
+ if ( m < 1 || m > 12 )
+ return false;
+
+ if ( d < 1 || d > lastDayOfIslamicMonth(m, y) )
+ return false;
+
+ IslamicDate islamic (m, d, y);
+ int absolute = islamic;
+ GregorianDate gregorian(absolute);
+
+ return date.setYMD(gregorian.getYear(), gregorian.getMonth(),
+ gregorian.getDay());
+}
+
+QString KCalendarSystemHijri::weekDayName(int day, bool shortName) const
+{
+ if ( shortName )
+ switch (day)
+ {
+ case 1:
+ return locale()->translate("Ith");
+ case 2:
+ return locale()->translate("Thl");
+ case 3:
+ return locale()->translate("Arb");
+ case 4:
+ return locale()->translate("Kha");
+ case 5:
+ return locale()->translate("Jum");
+ case 6:
+ return locale()->translate("Sab");
+ case 7:
+ return locale()->translate("Ahd");
+ }
+ else
+ switch ( day )
+ {
+ case 1:
+ return locale()->translate("Yaum al-Ithnain");
+ case 2:
+ return locale()->translate("Yau al-Thulatha");
+ case 3:
+ return locale()->translate("Yaum al-Arbi'a");
+ case 4:
+ return locale()->translate("Yaum al-Khamees");
+ case 5:
+ return locale()->translate("Yaum al-Jumma");
+ case 6:
+ return locale()->translate("Yaum al-Sabt");
+ case 7:
+ return locale()->translate("Yaum al-Ahad");
+ }
+
+ return QString::null;
+}
+
+QString KCalendarSystemHijri::weekDayName(const QDate& date,
+ bool shortName) const
+{
+ return weekDayName(dayOfWeek(date), shortName);
+}
+
+int KCalendarSystemHijri::dayOfWeek(const QDate& date) const
+{
+ return date.dayOfWeek(); // same as gregorian
+}
+
+int KCalendarSystemHijri::dayOfYear(const QDate & date) const
+{
+ QDate first;
+ setYMD(first, year(date), 1, 1);
+
+ return first.daysTo(date) + 1;
+
+ return 100;
+}
+
+int KCalendarSystemHijri::daysInMonth(const QDate& date) const
+{
+ int y, m;
+ gregorianToHijri(date, &y, &m, 0);
+
+ return lastDayOfIslamicMonth(m, y);
+}
+
+// Min valid year that may be converted to QDate
+int KCalendarSystemHijri::minValidYear() const
+{
+ QDate date(1753, 1, 1);
+
+ return year(date);
+}
+
+// Max valid year that may be converted to QDate
+int KCalendarSystemHijri::maxValidYear() const
+{
+ QDate date(8000, 1, 1);
+
+ return year(date);
+}
+
+int KCalendarSystemHijri::daysInYear(const QDate & date) const
+{
+ QDate first, last;
+ setYMD(first, year(date), 1, 1);
+ setYMD(last, year(date) + 1, 1, 1);
+
+ return first.daysTo(last);
+}
+
+int KCalendarSystemHijri::weekDayOfPray() const
+{
+ return 5; // friday
+}
+
+QDate KCalendarSystemHijri::addDays( const QDate & date, int ndays ) const
+{
+ return date.addDays( ndays );
+}
+
+QDate KCalendarSystemHijri::addMonths( const QDate & date, int nmonths ) const
+{
+ QDate result = date;
+ int m = month(date);
+ int y = year(date);
+
+ if ( nmonths < 0 )
+ {
+ m += 12;
+ y -= 1;
+ }
+
+ --m; // this only works if we start counting at zero
+ m += nmonths;
+ y += m / 12;
+ m %= 12;
+ ++m;
+
+ setYMD( result, y, m, day(date) );
+
+ return result;
+}
+
+QDate KCalendarSystemHijri::addYears( const QDate & date, int nyears ) const
+{
+ QDate result = date;
+ int y = year(date) + nyears;
+
+ setYMD( result, y, month(date), day(date) );
+
+ return result;
+}
+
+QString KCalendarSystemHijri::calendarName() const
+{
+ return QString::fromLatin1("hijri");
+}
+
+bool KCalendarSystemHijri::isLunar() const
+{
+ return true;
+}
+
+bool KCalendarSystemHijri::isLunisolar() const
+{
+ return false;
+}
+
+bool KCalendarSystemHijri::isSolar() const
+{
+ return false;
+}