00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 static int lastDayOfGregorianMonth(int month, int year) {
00044
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;
00064 int month;
00065 int day;
00066
00067 public:
00068 GregorianDate(int m, int d, int y) { month = m; day = d; year = y; }
00069
00070 GregorianDate(int d) {
00071
00072
00073 year = d/366;
00074 while (d >= GregorianDate(1,1,year+1))
00075 year++;
00076
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() {
00084 int N = day;
00085 for (int m = month - 1; m > 0; m--)
00086 N = N + lastDayOfGregorianMonth(m, year);
00087 return
00088 (N
00089 + 365 * (year - 1)
00090 + (year - 1)/4
00091 - (year - 1)/100
00092 + (year - 1)/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
00103
00104 if ((((11 * year) + 14) % 30) < 11)
00105 return 1;
00106 else
00107 return 0;
00108 }
00109
00110 static const int IslamicEpoch = 227014;
00111
00112
00113 static int lastDayOfIslamicMonth(int month, int year) {
00114
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;
00125 int month;
00126 int day;
00127
00128 public:
00129 IslamicDate(int m, int d, int y) { month = m; day = d; year = y; }
00130
00131 IslamicDate(int d) {
00132 if (d <= IslamicEpoch) {
00133 month = 0;
00134 day = 0;
00135 year = 0;
00136 }
00137 else {
00138
00139 year = (d - IslamicEpoch) / 355;
00140 while (d >= IslamicDate(1,1,year+1))
00141 year++;
00142
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() {
00151 return (day
00152 + 29 * (month - 1)
00153 + month/2
00154 + 354 * (year - 1)
00155 + (3 + (11 * year)) / 30
00156 + IslamicEpoch);
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
00224
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
00239 setYMD(firstDayWeek1, y, 1, 1);
00240 weekDay1 = dayOfWeek(firstDayWeek1);
00241
00242
00243
00244 if (weekDay1 > 4 )
00245 firstDayWeek1 = addDays(firstDayWeek1 , 7 - weekDay1 + 1);
00246
00247 dayOfWeek1InYear = dayOfYear(firstDayWeek1);
00248
00249 if ( dayOfYear(date) < dayOfWeek1InYear )
00250 {
00251 if ( yearNum )
00252 *yearNum = y - 1;
00253 return weeksInYear(y - 1);
00254 }
00255
00256
00257 setYMD(lastDayOfYear, y, 12, lastDayOfIslamicMonth(12, y));
00258 if ( (dayOfYear(date) >= daysInYear(date) - dayOfWeek(lastDayOfYear) + 1)
00259
00260 && dayOfWeek(lastDayOfYear) < 4)
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
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();
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
00511 int KCalendarSystemHijri::minValidYear() const
00512 {
00513 QDate date(1753, 1, 1);
00514
00515 return year(date);
00516 }
00517
00518
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;
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;
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 }