kdecore Library API Documentation

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), shortName); 00281 } 00282 00283 QString KCalendarSystemHijri::monthNamePossessive(const QDate& date, 00284 bool shortName) const 00285 { 00286 return monthNamePossessive(month(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 }
KDE Logo
This file is part of the documentation for kdecore Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Oct 8 11:13:59 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003