# kdecore Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# kcalendarsystemhijri.cpp

    00001 /*
    00002    Copyright (c) 2002-2003 Carlos Moro <cfmoro@correo.uniovi.es>
    00003    Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org>
    00004
    00005    This library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public
    00007    License as published by the Free Software Foundation; either
    00008    version 2 of the License, or (at your option) any later version.
    00009
    00010    This library is distributed in the hope that it will be useful,
    00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013    Library General Public License for more details.
    00014
    00015    You should have received a copy of the GNU Library General Public License
    00016    along with this library; see the file COPYING.LIB.  If not, write to
    00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018    Boston, MA 02111-1307, USA.
    00019 */
    00020
    00021 // Derived hijri kde calendar class
    00022
    00023 #include <qdatetime.h>
    00024 #include <qstring.h>
    00025
    00026 #include <klocale.h>
    00027 #include <kdebug.h>
    00028
    00029 #include "kcalendarsystemhijri.h"
    00030
    00031 /*
    00032   The following C++ code is translated from the Lisp code
    00033   in ``Calendrical Calculations'' by Nachum Dershowitz and
    00034   Edward M. Reingold, Software---Practice & Experience,
    00035   vol. 20, no. 9 (September, 1990), pp. 899--928.
    00036
    00037   This code is in the public domain, but any use of it
    00038   should publically acknowledge its source.
    00039
    00040   Classes GregorianDate, IslamicDate
    00041  */
    00042
    00043 static int lastDayOfGregorianMonth(int month, int year) {
    00044 // Compute the last date of the month for the Gregorian calendar.
    00045
    00046   switch (month) {
    00047   case 2:
    00048     if ((((year % 4) == 0) && ((year % 100) != 0))
    00049         || ((year % 400) == 0))
    00050       return 29;
    00051     else
    00052       return 28;
    00053   case 4:
    00054   case 6:
    00055   case 9:
    00056   case 11: return 30;
    00057   default: return 31;
    00058   }
    00059 }
    00060
    00061 class GregorianDate {
    00062 private:
    00063   int year;   // 1...
    00064   int month;  // 1 == January, ..., 12 == December
    00065   int day;    // 1..lastDayOfGregorianMonth(month, year)
    00066
    00067 public:
    00068   GregorianDate(int m, int d, int y) { month = m; day = d; year = y; }
    00069
    00070   GregorianDate(int d) { // Computes the Gregorian date from the absolute date.
    00071
    00072     // Search forward year by year from approximate year
    00073     year = d/366;
    00074     while (d >= GregorianDate(1,1,year+1))
    00075       year++;
    00076     // Search forward month by month from January
    00077     month = 1;
    00078     while (d > GregorianDate(month, lastDayOfGregorianMonth(month,year), year))
    00079       month++;
    00080     day = d - GregorianDate(month,1,year) + 1;
    00081   }
    00082
    00083   operator int() { // Computes the absolute date from the Gregorian date.
    00084     int N = day;           // days this month
    00085     for (int m = month - 1;  m > 0; m--) // days in prior months this year
    00086       N = N + lastDayOfGregorianMonth(m, year);
    00087     return
    00088       (N                    // days this year
    00089        + 365 * (year - 1)   // days in previous years ignoring leap days
    00090        + (year - 1)/4       // Julian leap days before this year...
    00091        - (year - 1)/100     // ...minus prior century years...
    00092        + (year - 1)/400);   // ...plus prior years divisible by 400
    00093   }
    00094
    00095   int getMonth() { return month; }
    00096   int getDay() { return day; }
    00097   int getYear() { return year; }
    00098
    00099 };
    00100
    00101 static int IslamicLeapYear(int year) {
    00102 // True if year is an Islamic leap year
    00103
    00104   if ((((11 * year) + 14) % 30) < 11)
    00105     return 1;
    00106   else
    00107     return 0;
    00108 }
    00109
    00110 static const int IslamicEpoch = 227014; // Absolute date of start of
    00111                                         // Islamic calendar
    00112
    00113 static int lastDayOfIslamicMonth(int month, int year) {
    00114 // Last day in month during year on the Islamic calendar.
    00115
    00116   if (((month % 2) == 1) || ((month == 12) && IslamicLeapYear(year)))
    00117     return 30;
    00118   else
    00119     return 29;
    00120 }
    00121
    00122 class IslamicDate {
    00123 private:
    00124   int year;   // 1...
    00125   int month;  // 1..13 (12 in a common year)
    00126   int day;    // 1..lastDayOfIslamicMonth(month,year)
    00127
    00128 public:
    00129   IslamicDate(int m, int d, int y) { month = m; day = d; year = y; }
    00130
    00131   IslamicDate(int d) { // Computes the Islamic date from the absolute date.
    00132     if (d <= IslamicEpoch) { // Date is pre-Islamic
    00133       month = 0;
    00134       day = 0;
    00135       year = 0;
    00136     }
    00137     else {
    00138       // Search forward year by year from approximate year
    00139       year = (d - IslamicEpoch) / 355;
    00140       while (d >= IslamicDate(1,1,year+1))
    00141         year++;
    00142       // Search forward month by month from Muharram
    00143       month = 1;
    00144       while (d > IslamicDate(month, lastDayOfIslamicMonth(month,year), year))
    00145         month++;
    00146       day = d - IslamicDate(month,1,year) + 1;
    00147     }
    00148   }
    00149
    00150   operator int() { // Computes the absolute date from the Islamic date.
    00151     return (day                      // days so far this month
    00152             + 29 * (month - 1)       // days so far...
    00153             + month/2                //            ...this year
    00154             + 354 * (year - 1)       // non-leap days in prior years
    00155             + (3 + (11 * year)) / 30 // leap days in prior years
    00156             + IslamicEpoch);                // days before start of calendar
    00157   }
    00158
    00159   int getMonth() { return month; }
    00160   int getDay() { return day; }
    00161   int getYear() { return year; }
    00162
    00163 };
    00164
    00165 static void gregorianToHijri(const QDate & date, int * pYear, int * pMonth,
    00166    int * pDay)
    00167 {
    00168   GregorianDate gregorian(date.month(),date.day(),date.year());
    00169   int absolute = gregorian;
    00170
    00171   IslamicDate islamic(absolute);
    00172
    00173   if (pYear)
    00174     *pYear = islamic.getYear();
    00175   if (pMonth)
    00176     *pMonth = islamic.getMonth();
    00177   if (pDay)
    00178     *pDay = islamic.getDay();
    00179 }
    00180
    00181 KCalendarSystemHijri::KCalendarSystemHijri(const KLocale * locale)
    00182   : KCalendarSystem(locale)
    00183 {
    00184 }
    00185
    00186 KCalendarSystemHijri::~KCalendarSystemHijri()
    00187 {
    00188 }
    00189
    00190 int KCalendarSystemHijri::year(const QDate& date) const
    00191 {
    00192   int y;
    00193   gregorianToHijri(date, &y, 0, 0);
    00194   return y;
    00195 }
    00196
    00197 int KCalendarSystemHijri::month(const QDate& date) const
    00198 {
    00199   int m;
    00200   gregorianToHijri(date, 0, &m, 0);
    00201   return m;
    00202 }
    00203
    00204 int KCalendarSystemHijri::day(const QDate& date) const
    00205 {
    00206   int d;
    00207   gregorianToHijri(date, 0, 0, &d);
    00208   return d;
    00209 }
    00210
    00211 int KCalendarSystemHijri::monthsInYear( const QDate & date ) const
    00212 {
    00213   Q_UNUSED( date )
    00214
    00215   return 12;
    00216 }
    00217
    00218 int KCalendarSystemHijri::weeksInYear(int year) const
    00219 {
    00220   QDate temp;
    00221   setYMD(temp, year, 12, lastDayOfIslamicMonth(12, year));
    00222
    00223   // If the last day of the year is in the first week, we have to check the
    00224   // week before
    00225   if ( weekNumber(temp) == 1 )
    00226     temp = addDays(temp, -7);
    00227
    00228   return weekNumber(temp);
    00229 }
    00230
    00231 int KCalendarSystemHijri::weekNumber(const QDate& date, int * yearNum) const
    00232 {
    00233   QDate firstDayWeek1, lastDayOfYear;
    00234   int y = year(date);
    00235   int week;
    00236   int weekDay1, dayOfWeek1InYear;
    00237
    00238   // let's guess 1st day of 1st week
    00239   setYMD(firstDayWeek1, y, 1, 1);
    00240   weekDay1 = dayOfWeek(firstDayWeek1);
    00241
    00242   // iso 8601: week 1  is the first containing thursday and week starts on
    00243   // monday
    00244   if (weekDay1 > 4 )
    00245     firstDayWeek1 = addDays(firstDayWeek1 , 7 - weekDay1 + 1); // next monday
    00246
    00247   dayOfWeek1InYear = dayOfYear(firstDayWeek1);
    00248
    00249   if ( dayOfYear(date) < dayOfWeek1InYear ) // our date in prev year's week
    00250   {
    00251     if ( yearNum )
    00252       *yearNum = y - 1;
    00253     return weeksInYear(y - 1);
    00254   }
    00255
    00256   // let' check if its last week belongs to next year
    00257   setYMD(lastDayOfYear, y, 12, lastDayOfIslamicMonth(12, y));
    00258   if ( (dayOfYear(date) >= daysInYear(date) - dayOfWeek(lastDayOfYear) + 1)
    00259        // our date is in last week
    00260        && dayOfWeek(lastDayOfYear) < 4) // 1st week in next year has thursday
    00261     {
    00262       if ( yearNum )
    00263         *yearNum = y + 1;
    00264       week = 1;
    00265     }
    00266   else
    00267   {
    00268     if ( weekDay1 < 5 )
    00269       firstDayWeek1 = addDays(firstDayWeek1, - (weekDay1 - 1));
    00270
    00271     week = firstDayWeek1.daysTo(date) / 7 + 1;
    00272   }
    00273
    00274   return week;
    00275 }
    00276
    00277 QString KCalendarSystemHijri::monthName(const QDate& date,
    00278                                         bool shortName) const
    00279 {
    00280   return monthName(month(date), year(date), shortName);
    00281 }
    00282
    00283 QString KCalendarSystemHijri::monthNamePossessive(const QDate& date,
    00284                                                   bool shortName) const
    00285 {
    00286   return monthNamePossessive(month(date), year(date), shortName);
    00287 }
    00288
    00289 QString KCalendarSystemHijri::monthName(int month, int year, bool shortName)
    00290   const {
    00291
    00292   Q_UNUSED(year);
    00293
    00294   if (shortName)
    00295     switch ( month )
    00296       {
    00297       case 1:
    00298         return locale()->translate("Muharram");
    00299       case 2:
    00300         return locale()->translate("Safar");
    00301       case 3:
    00302         return locale()->translate("R. Awal");
    00303       case 4:
    00304         return locale()->translate("R. Thaani");
    00305       case 5:
    00306         return locale()->translate("J. Awal");
    00307       case 6:
    00308         return locale()->translate("J. Thaani");
    00309       case 7:
    00310         return locale()->translate("Rajab");
    00311       case 8:
    00312         return locale()->translate("Sha`ban");
    00313       case 9:
    00314         return locale()->translate("Ramadan");
    00315       case 10:
    00316         return locale()->translate("Shawwal");
    00317       case 11:
    00318         return locale()->translate("Qi`dah");
    00319       case 12:
    00320         return locale()->translate("Hijjah");
    00321     }
    00322   else
    00323     switch ( month )
    00324       {
    00325       case 1:
    00326         return locale()->translate("Muharram");
    00327       case 2:
    00328         return locale()->translate("Safar");
    00329       case 3:
    00330         return locale()->translate("Rabi` al-Awal");
    00331       case 4:
    00332         return locale()->translate("Rabi` al-Thaani");
    00333       case 5:
    00334         return locale()->translate("Jumaada al-Awal");
    00335       case 6:
    00336         return locale()->translate("Jumaada al-Thaani");
    00337       case 7:
    00338         return locale()->translate("Rajab");
    00339       case 8:
    00340         return locale()->translate("Sha`ban");
    00341       case 9:
    00342         return locale()->translate("Ramadan");
    00343       case 10:
    00344         return locale()->translate("Shawwal");
    00345       case 11:
    00346         return locale()->translate("Thu al-Qi`dah");
    00347       case 12:
    00348         return locale()->translate("Thu al-Hijjah");
    00349       }
    00350
    00351   return QString::null;
    00352 }
    00353
    00354 QString KCalendarSystemHijri::monthNamePossessive(int month, int year,
    00355                                                   bool shortName) const
    00356 {
    00357   Q_UNUSED(year);
    00358
    00359   if (shortName)
    00360     switch ( month )
    00361       {
    00362       case 1:
    00363         return locale()->translate("of Muharram");
    00364       case 2:
    00365         return locale()->translate("of Safar");
    00366       case 3:
    00367         return locale()->translate("of R. Awal");
    00368       case 4:
    00369         return locale()->translate("of R. Thaani");
    00370       case 5:
    00371         return locale()->translate("of J. Awal");
    00372       case 6:
    00373         return locale()->translate("of J. Thaani");
    00374       case 7:
    00375         return locale()->translate("of Rajab");
    00376       case 8:
    00377         return locale()->translate("of Sha`ban");
    00378       case 9:
    00379         return locale()->translate("of Ramadan");
    00380       case 10:
    00381         return locale()->translate("of Shawwal");
    00382       case 11:
    00383         return locale()->translate("of Qi`dah");
    00384       case 12:
    00385         return locale()->translate("of Hijjah");
    00386     }
    00387   else
    00388     switch ( month )
    00389       {
    00390       case 1:
    00391         return locale()->translate("of Muharram");
    00392       case 2:
    00393         return locale()->translate("of Safar");
    00394       case 3:
    00395         return locale()->translate("of Rabi` al-Awal");
    00396       case 4:
    00397         return locale()->translate("of Rabi` al-Thaani");
    00398       case 5:
    00399         return locale()->translate("of Jumaada al-Awal");
    00400       case 6:
    00401         return locale()->translate("of Jumaada al-Thaani");
    00402       case 7:
    00403         return locale()->translate("of Rajab");
    00404       case 8:
    00405         return locale()->translate("of Sha`ban");
    00406       case 9:
    00407         return locale()->translate("of Ramadan");
    00408       case 10:
    00409         return locale()->translate("of Shawwal");
    00410       case 11:
    00411         return locale()->translate("of Thu al-Qi`dah");
    00412       case 12:
    00413         return locale()->translate("of Thu al-Hijjah");
    00414       }
    00415
    00416   return QString::null;
    00417 }
    00418
    00419 bool KCalendarSystemHijri::setYMD(QDate & date, int y, int m, int d) const
    00420 {
    00421   // range checks
    00422   if ( y < minValidYear() || y > maxValidYear() )
    00423     return false;
    00424
    00425   if ( m < 1 || m > 12 )
    00426     return false;
    00427
    00428   if ( d < 1 || d > lastDayOfIslamicMonth(m, y) )
    00429     return false;
    00430
    00431   IslamicDate islamic (m, d, y);
    00432   int absolute = islamic;
    00433   GregorianDate gregorian(absolute);
    00434
    00435   return date.setYMD(gregorian.getYear(), gregorian.getMonth(),
    00436     gregorian.getDay());
    00437 }
    00438
    00439 QString KCalendarSystemHijri::weekDayName(int day, bool shortName) const
    00440 {
    00441   if ( shortName )
    00442     switch (day)
    00443       {
    00444       case 1:
    00445         return locale()->translate("Ith");
    00446       case 2:
    00447         return locale()->translate("Thl");
    00448       case 3:
    00449         return locale()->translate("Arb");
    00450       case 4:
    00451         return locale()->translate("Kha");
    00452       case 5:
    00453         return locale()->translate("Jum");
    00454       case 6:
    00455         return locale()->translate("Sab");
    00456       case 7:
    00457         return locale()->translate("Ahd");
    00458       }
    00459   else
    00460     switch ( day )
    00461       {
    00462       case 1:
    00463         return locale()->translate("Yaum al-Ithnain");
    00464       case 2:
    00465         return locale()->translate("Yau al-Thulatha");
    00466       case 3:
    00467         return locale()->translate("Yaum al-Arbi'a");
    00468       case 4:
    00469         return locale()->translate("Yaum al-Khamees");
    00470       case 5:
    00471         return locale()->translate("Yaum al-Jumma");
    00472       case 6:
    00473         return locale()->translate("Yaum al-Sabt");
    00474       case 7:
    00475         return locale()->translate("Yaum al-Ahad");
    00476       }
    00477
    00478   return QString::null;
    00479 }
    00480
    00481 QString KCalendarSystemHijri::weekDayName(const QDate& date,
    00482                                           bool shortName) const
    00483 {
    00484   return weekDayName(dayOfWeek(date), shortName);
    00485 }
    00486
    00487 int KCalendarSystemHijri::dayOfWeek(const QDate& date) const
    00488 {
    00489   return date.dayOfWeek(); // same as gregorian
    00490 }
    00491
    00492 int KCalendarSystemHijri::dayOfYear(const QDate & date) const
    00493 {
    00494   QDate first;
    00495   setYMD(first, year(date), 1, 1);
    00496
    00497   return first.daysTo(date) + 1;
    00498
    00499   return 100;
    00500 }
    00501
    00502 int KCalendarSystemHijri::daysInMonth(const QDate& date) const
    00503 {
    00504   int y, m;
    00505   gregorianToHijri(date, &y, &m, 0);
    00506
    00507   return lastDayOfIslamicMonth(m, y);
    00508 }
    00509
    00510 // Min valid year that may be converted to QDate
    00511 int KCalendarSystemHijri::minValidYear() const
    00512 {
    00513   QDate date(1753, 1, 1);
    00514
    00515   return year(date);
    00516 }
    00517
    00518 // Max valid year that may be converted to QDate
    00519 int KCalendarSystemHijri::maxValidYear() const
    00520 {
    00521   QDate date(8000, 1, 1);
    00522
    00523   return year(date);
    00524 }
    00525
    00526 int KCalendarSystemHijri::daysInYear(const QDate & date) const
    00527 {
    00528   QDate first, last;
    00529   setYMD(first, year(date), 1, 1);
    00530   setYMD(last, year(date) + 1, 1, 1);
    00531
    00532   return first.daysTo(last);
    00533 }
    00534
    00535 int KCalendarSystemHijri::weekDayOfPray() const
    00536 {
    00537   return 5; // friday
    00538 }
    00539
    00540 QDate KCalendarSystemHijri::addDays( const QDate & date, int ndays ) const
    00541 {
    00542   return date.addDays( ndays );
    00543 }
    00544
    00545 QDate KCalendarSystemHijri::addMonths( const QDate & date, int nmonths ) const
    00546 {
    00547   QDate result = date;
    00548   int m = month(date);
    00549   int y = year(date);
    00550
    00551   if ( nmonths < 0 )
    00552   {
    00553     m += 12;
    00554     y -= 1;
    00555   }
    00556
    00557   --m; // this only works if we start counting at zero
    00558   m += nmonths;
    00559   y += m / 12;
    00560   m %= 12;
    00561   ++m;
    00562
    00563   setYMD( result, y, m, day(date) );
    00564
    00565   return result;
    00566 }
    00567
    00568 QDate KCalendarSystemHijri::addYears( const QDate & date, int nyears ) const
    00569 {
    00570   QDate result = date;
    00571   int y = year(date) + nyears;
    00572
    00573   setYMD( result, y, month(date), day(date) );
    00574
    00575   return result;
    00576 }
    00577
    00578 QString KCalendarSystemHijri::calendarName() const
    00579 {
    00580   return QString::fromLatin1("hijri");
    00581 }
    00582
    00583 bool KCalendarSystemHijri::isLunar() const
    00584 {
    00585   return true;
    00586 }
    00587
    00588 bool KCalendarSystemHijri::isLunisolar() const
    00589 {
    00590   return false;
    00591 }
    00592
    00593 bool KCalendarSystemHijri::isSolar() const
    00594 {
    00595   return false;
    00596 }

This file is part of the documentation for kdecore Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:18:01 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003