00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "kcalendarsystemhijri.h"
00025
00026 #include "kdebug.h"
00027 #include "klocale.h"
00028
00029 #include <QtCore/QDate>
00030 #include <QtCore/QCharRef>
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static int lastDayOfGregorianMonth( int month, int year )
00051 {
00052
00053
00054 switch ( month ) {
00055 case 2:
00056 if ( ( ( ( year % 4 ) == 0 ) && ( ( year % 100 ) != 0 ) )
00057 || ( ( year % 400 ) == 0 ) ) {
00058 return 29;
00059 } else {
00060 return 28;
00061 }
00062 case 4:
00063 case 6:
00064 case 9:
00065 case 11: return 30;
00066 default: return 31;
00067 }
00068 }
00069
00070 class GregorianDate
00071 {
00072 private:
00073 int year;
00074 int month;
00075 int day;
00076
00077 public:
00078 GregorianDate( int m, int d, int y )
00079 {
00080 month = m; day = d; year = y;
00081 }
00082
00083
00084 GregorianDate( int d )
00085 {
00086
00087 year = d / 366;
00088 while ( d >= GregorianDate( 1, 1, year + 1 ) ) {
00089 year++;
00090 }
00091
00092 month = 1;
00093 while ( d > GregorianDate( month, lastDayOfGregorianMonth( month, year ), year ) ) {
00094 month++;
00095 }
00096 day = d - GregorianDate( month, 1, year ) + 1;
00097 }
00098
00099
00100 operator int()
00101 {
00102 int N = day;
00103 for ( int m = month - 1; m > 0; m-- )
00104 N = N + lastDayOfGregorianMonth( m, year );
00105 return
00106 ( N
00107 + 365 * ( year - 1 )
00108 + ( year - 1 ) / 4
00109 - ( year - 1 ) / 100
00110 + ( year - 1 ) / 400 );
00111 }
00112
00113 int getMonth()
00114 {
00115 return month;
00116 }
00117
00118 int getDay()
00119 {
00120 return day;
00121 }
00122
00123 int getYear()
00124 {
00125 return year;
00126 }
00127
00128 };
00129
00130 static int IslamicLeapYear( int year )
00131 {
00132
00133
00134 if ( ( ( ( 11 * year ) + 14 ) % 30 ) < 11 ) {
00135 return 1;
00136 } else {
00137 return 0;
00138 }
00139 }
00140
00141 static const int IslamicEpoch = 227014;
00142
00143
00144 static int lastDayOfIslamicMonth( int month, int year )
00145 {
00146
00147
00148 if ( ( ( month % 2 ) == 1 ) || ( ( month == 12 ) && IslamicLeapYear( year ) ) ) {
00149 return 30;
00150 } else {
00151 return 29;
00152 }
00153 }
00154
00155 class IslamicDate
00156 {
00157 private:
00158 int year;
00159 int month;
00160 int day;
00161
00162 public:
00163 IslamicDate( int m, int d, int y )
00164 {
00165 month = m; day = d; year = y;
00166 }
00167
00168
00169 IslamicDate( int d )
00170 {
00171 if ( d <= IslamicEpoch ) {
00172 month = 0;
00173 day = 0;
00174 year = 0;
00175 } else {
00176
00177 year = ( d - IslamicEpoch ) / 355;
00178 while ( d >= IslamicDate( 1, 1, year + 1 ) ) {
00179 year++;
00180 }
00181
00182 month = 1;
00183 while ( d > IslamicDate( month, lastDayOfIslamicMonth( month, year ), year ) ) {
00184 month++;
00185 }
00186 day = d - IslamicDate( month, 1, year ) + 1;
00187 }
00188 }
00189
00190
00191 operator int()
00192 {
00193 return ( day
00194 + 29 * ( month - 1 )
00195 + month / 2
00196 + 354 * ( year - 1 )
00197 + ( 3 + ( 11 * year ) ) / 30
00198 + IslamicEpoch );
00199 }
00200
00201 int getMonth()
00202 {
00203 return month;
00204 }
00205
00206 int getDay()
00207 {
00208 return day;
00209 }
00210
00211 int getYear()
00212 {
00213 return year;
00214 }
00215
00216 };
00217
00218 static void gregorianToHijri( const QDate & date, int *pYear, int *pMonth, int * pDay )
00219 {
00220 GregorianDate gregorian( date.month(), date.day(), date.year() );
00221 int absolute = gregorian;
00222
00223 IslamicDate islamic( absolute );
00224
00225 if ( pYear ) {
00226 * pYear = islamic.getYear();
00227 }
00228
00229 if ( pMonth ) {
00230 * pMonth = islamic.getMonth();
00231 }
00232
00233 if ( pDay ) {
00234 * pDay = islamic.getDay();
00235 }
00236 }
00237
00238
00239
00240
00241
00242 KCalendarSystemHijri::KCalendarSystemHijri( const KLocale * locale )
00243 : KCalendarSystem( locale ), d( 0 )
00244 {
00245 }
00246
00247 KCalendarSystemHijri::~KCalendarSystemHijri()
00248 {
00249 }
00250
00251 QString KCalendarSystemHijri::calendarType() const
00252 {
00253 return QLatin1String( "hijri" );
00254 }
00255
00256 QDate KCalendarSystemHijri::epoch() const
00257 {
00258
00259 return QDate::fromJulianDay( 1948440 );
00260 }
00261
00262 QDate KCalendarSystemHijri::earliestValidDate() const
00263 {
00264 return KCalendarSystem::earliestValidDate();
00265 }
00266
00267 QDate KCalendarSystemHijri::latestValidDate() const
00268 {
00269
00270
00271
00272
00273
00274 return QDate( 10323, 10, 21 );
00275 }
00276
00277 bool KCalendarSystemHijri::isValid( int y, int month, int day ) const
00278 {
00279
00280 if ( y < year( earliestValidDate() ) || y > year( latestValidDate() ) ) {
00281 return false;
00282 }
00283
00284 if ( month < 1 || month > 12 ) {
00285 return false;
00286 }
00287
00288 if ( day < 1 || day > lastDayOfIslamicMonth( month, y ) ) {
00289 return false;
00290 }
00291
00292 return true;
00293 }
00294
00295 bool KCalendarSystemHijri::isValid( const QDate &date ) const
00296 {
00297 return KCalendarSystem::isValid( date );
00298 }
00299
00300 bool KCalendarSystemHijri::setDate( QDate &date, int year, int month, int day ) const
00301 {
00302 return KCalendarSystem::setDate( date, year, month, day );
00303 }
00304
00305
00306 bool KCalendarSystemHijri::setYMD( QDate &date, int y, int m, int d ) const
00307 {
00308
00309
00310
00311
00312
00313 if ( y < year( QDate( 1753, 1, 1 ) ) || y > 9999 ) {
00314 return false;
00315 }
00316
00317 if ( m < 1 || m > 12 ) {
00318 return false;
00319 }
00320
00321 if ( d < 1 || d > lastDayOfIslamicMonth( m, y ) ) {
00322 return false;
00323 }
00324
00325 IslamicDate islamic ( m, d, y );
00326 int absolute = islamic;
00327 GregorianDate gregorian( absolute );
00328
00329 return date.setYMD( gregorian.getYear(), gregorian.getMonth(), gregorian.getDay() );
00330 }
00331
00332 int KCalendarSystemHijri::year( const QDate &date ) const
00333 {
00334 int y;
00335
00336 gregorianToHijri( date, &y, 0, 0 );
00337
00338 return y;
00339 }
00340
00341 int KCalendarSystemHijri::month( const QDate &date ) const
00342 {
00343 int m;
00344 gregorianToHijri( date, 0, &m, 0 );
00345 return m;
00346 }
00347
00348 int KCalendarSystemHijri::day( const QDate &date ) const
00349 {
00350 int d;
00351
00352 gregorianToHijri( date, 0, 0, &d );
00353
00354 return d;
00355 }
00356
00357 QDate KCalendarSystemHijri::addYears( const QDate &date, int nyears ) const
00358 {
00359 QDate result = date;
00360
00361 int y = year( date ) + nyears;
00362 setYMD( result, y, month( date ), day( date ) );
00363
00364 return result;
00365 }
00366
00367 QDate KCalendarSystemHijri::addMonths( const QDate &date, int nmonths ) const
00368 {
00369 QDate result = date;
00370 int m = month( date );
00371 int y = year( date );
00372
00373 if ( nmonths < 0 ) {
00374 m += 12;
00375 y -= 1;
00376 }
00377
00378 --m;
00379 m += nmonths;
00380 y += m / 12;
00381 m %= 12;
00382 ++m;
00383
00384 setYMD( result, y, m, day( date ) );
00385
00386 return result;
00387 }
00388
00389 QDate KCalendarSystemHijri::addDays( const QDate &date, int ndays ) const
00390 {
00391 return date.addDays( ndays );
00392 }
00393
00394 int KCalendarSystemHijri::monthsInYear( const QDate &date ) const
00395 {
00396 Q_UNUSED( date )
00397
00398 return 12;
00399 }
00400
00401 int KCalendarSystemHijri::weeksInYear( const QDate &date ) const
00402 {
00403 return KCalendarSystem::weeksInYear( date );
00404 }
00405
00406 int KCalendarSystemHijri::weeksInYear( int year ) const
00407 {
00408 QDate temp;
00409 setYMD( temp, year, 12, lastDayOfIslamicMonth( 12, year ) );
00410
00411
00412
00413 if ( weekNumber( temp ) == 1 ) {
00414 temp = addDays( temp, -7 );
00415 }
00416
00417 return weekNumber( temp );
00418 }
00419
00420 int KCalendarSystemHijri::daysInYear( const QDate &date ) const
00421 {
00422 QDate first, last;
00423
00424 setYMD( first, year( date ), 1, 1 );
00425 setYMD( last, year( date ) + 1, 1, 1 );
00426
00427 return first.daysTo( last );
00428 }
00429
00430 int KCalendarSystemHijri::daysInMonth( const QDate &date ) const
00431 {
00432 int y, m;
00433
00434 gregorianToHijri( date, &y, &m, 0 );
00435
00436 return lastDayOfIslamicMonth( m, y );
00437 }
00438
00439 int KCalendarSystemHijri::daysInWeek( const QDate &date ) const
00440 {
00441 return KCalendarSystem::daysInWeek( date );
00442 }
00443
00444 int KCalendarSystemHijri::dayOfYear( const QDate &date ) const
00445 {
00446 QDate first;
00447
00448 setYMD( first, year( date ), 1, 1 );
00449
00450 return first.daysTo( date ) + 1;
00451 }
00452
00453 int KCalendarSystemHijri::dayOfWeek( const QDate &date ) const
00454 {
00455 return date.dayOfWeek();
00456 }
00457
00458 int KCalendarSystemHijri::weekNumber( const QDate &date, int *yearNum ) const
00459 {
00460 QDate firstDayWeek1, lastDayOfYear;
00461 int y = year( date );
00462 int week;
00463 int weekDay1, dayOfWeek1InYear;
00464
00465
00466 setYMD( firstDayWeek1, y, 1, 1 );
00467 weekDay1 = dayOfWeek( firstDayWeek1 );
00468
00469
00470
00471 if ( weekDay1 > 4 ) {
00472 firstDayWeek1 = addDays( firstDayWeek1 , 7 - weekDay1 + 1 );
00473 }
00474
00475 dayOfWeek1InYear = dayOfYear( firstDayWeek1 );
00476
00477
00478 if ( dayOfYear( date ) < dayOfWeek1InYear ) {
00479 if ( yearNum ) {
00480 * yearNum = y - 1;
00481 }
00482 return weeksInYear( y - 1 );
00483 }
00484
00485
00486 setYMD( lastDayOfYear, y, 12, lastDayOfIslamicMonth( 12, y ) );
00487
00488 if ( ( dayOfYear( date ) >= daysInYear( date ) - dayOfWeek( lastDayOfYear ) + 1 )
00489 && dayOfWeek( lastDayOfYear ) < 4 ) {
00490 if ( yearNum ) {
00491 * yearNum = y + 1;
00492 }
00493 week = 1;
00494 } else {
00495 if ( weekDay1 < 5 ) {
00496 firstDayWeek1 = addDays( firstDayWeek1, - ( weekDay1 - 1 ) );
00497 }
00498
00499 week = firstDayWeek1.daysTo( date ) / 7 + 1;
00500 }
00501
00502 return week;
00503 }
00504
00505 bool KCalendarSystemHijri::isLeapYear( int year ) const
00506 {
00507
00508 if ( ( ( ( 11 * year ) + 14 ) % 30 ) < 11 ) {
00509 return true;
00510 } else {
00511 return false;
00512 }
00513 }
00514
00515 bool KCalendarSystemHijri::isLeapYear( const QDate &date ) const
00516 {
00517 return KCalendarSystem::isLeapYear( year( date ) );
00518 }
00519
00520 QString KCalendarSystemHijri::monthName( int month, int year, MonthNameFormat format ) const
00521 {
00522 Q_UNUSED( year );
00523
00524 if ( format == ShortNamePossessive ) {
00525 switch ( month ) {
00526 case 1:
00527 return ki18n( "of Muharram" ).toString( locale() );
00528 case 2:
00529 return ki18n( "of Safar" ).toString( locale() );
00530 case 3:
00531 return ki18n( "of R. Awal" ).toString( locale() );
00532 case 4:
00533 return ki18n( "of R. Thaani" ).toString( locale() );
00534 case 5:
00535 return ki18n( "of J. Awal" ).toString( locale() );
00536 case 6:
00537 return ki18n( "of J. Thaani" ).toString( locale() );
00538 case 7:
00539 return ki18n( "of Rajab" ).toString( locale() );
00540 case 8:
00541 return ki18n( "of Sha`ban" ).toString( locale() );
00542 case 9:
00543 return ki18n( "of Ramadan" ).toString( locale() );
00544 case 10:
00545 return ki18n( "of Shawwal" ).toString( locale() );
00546 case 11:
00547 return ki18n( "of Qi`dah" ).toString( locale() );
00548 case 12:
00549 return ki18n( "of Hijjah" ).toString( locale() );
00550 default:
00551 return QString();
00552 }
00553 }
00554
00555 if ( format == LongNamePossessive ) {
00556 switch ( month ) {
00557 case 1:
00558 return ki18n( "of Muharram" ).toString( locale() );
00559 case 2:
00560 return ki18n( "of Safar" ).toString( locale() );
00561 case 3:
00562 return ki18n( "of Rabi` al-Awal" ).toString( locale() );
00563 case 4:
00564 return ki18n( "of Rabi` al-Thaani" ).toString( locale() );
00565 case 5:
00566 return ki18n( "of Jumaada al-Awal" ).toString( locale() );
00567 case 6:
00568 return ki18n( "of Jumaada al-Thaani" ).toString( locale() );
00569 case 7:
00570 return ki18n( "of Rajab" ).toString( locale() );
00571 case 8:
00572 return ki18n( "of Sha`ban" ).toString( locale() );
00573 case 9:
00574 return ki18n( "of Ramadan" ).toString( locale() );
00575 case 10:
00576 return ki18n( "of Shawwal" ).toString( locale() );
00577 case 11:
00578 return ki18n( "of Thu al-Qi`dah" ).toString( locale() );
00579 case 12:
00580 return ki18n( "of Thu al-Hijjah" ).toString( locale() );
00581 default:
00582 return QString();
00583 }
00584 }
00585
00586 if ( format == ShortName ) {
00587 switch ( month ) {
00588 case 1:
00589 return ki18n( "Muharram" ).toString( locale() );
00590 case 2:
00591 return ki18n( "Safar" ).toString( locale() );
00592 case 3:
00593 return ki18n( "R. Awal" ).toString( locale() );
00594 case 4:
00595 return ki18n( "R. Thaani" ).toString( locale() );
00596 case 5:
00597 return ki18n( "J. Awal" ).toString( locale() );
00598 case 6:
00599 return ki18n( "J. Thaani" ).toString( locale() );
00600 case 7:
00601 return ki18n( "Rajab" ).toString( locale() );
00602 case 8:
00603 return ki18n( "Sha`ban" ).toString( locale() );
00604 case 9:
00605 return ki18n( "Ramadan" ).toString( locale() );
00606 case 10:
00607 return ki18n( "Shawwal" ).toString( locale() );
00608 case 11:
00609 return ki18n( "Qi`dah" ).toString( locale() );
00610 case 12:
00611 return ki18n( "Hijjah" ).toString( locale() );
00612 default:
00613 return QString();
00614 }
00615 }
00616
00617
00618 switch ( month ) {
00619 case 1:
00620 return ki18n( "Muharram" ).toString( locale() );
00621 case 2:
00622 return ki18n( "Safar" ).toString( locale() );
00623 case 3:
00624 return ki18n( "Rabi` al-Awal" ).toString( locale() );
00625 case 4:
00626 return ki18n( "Rabi` al-Thaani" ).toString( locale() );
00627 case 5:
00628 return ki18n( "Jumaada al-Awal" ).toString( locale() );
00629 case 6:
00630 return ki18n( "Jumaada al-Thaani" ).toString( locale() );
00631 case 7:
00632 return ki18n( "Rajab" ).toString( locale() );
00633 case 8:
00634 return ki18n( "Sha`ban" ).toString( locale() );
00635 case 9:
00636 return ki18n( "Ramadan" ).toString( locale() );
00637 case 10:
00638 return ki18n( "Shawwal" ).toString( locale() );
00639 case 11:
00640 return ki18n( "Thu al-Qi`dah" ).toString( locale() );
00641 case 12:
00642 return ki18n( "Thu al-Hijjah" ).toString( locale() );
00643 default:
00644 return QString();
00645 }
00646 }
00647
00648 QString KCalendarSystemHijri::monthName( const QDate &date, MonthNameFormat format ) const
00649 {
00650 return monthName( month( date ), year( date ), format );
00651 }
00652
00653 QString KCalendarSystemHijri::weekDayName( int weekDay, WeekDayNameFormat format ) const
00654 {
00655 if ( format == ShortDayName ) {
00656 switch ( weekDay ) {
00657 case 1:
00658 return ki18n( "Ith" ).toString( locale() );
00659 case 2:
00660 return ki18n( "Thl" ).toString( locale() );
00661 case 3:
00662 return ki18n( "Arb" ).toString( locale() );
00663 case 4:
00664 return ki18n( "Kha" ).toString( locale() );
00665 case 5:
00666 return ki18n( "Jum" ).toString( locale() );
00667 case 6:
00668 return ki18n( "Sab" ).toString( locale() );
00669 case 7:
00670 return ki18n( "Ahd" ).toString( locale() );
00671 default:
00672 return QString();
00673 }
00674 }
00675
00676
00677 switch ( weekDay ) {
00678 case 1:
00679 return ki18n( "Yaum al-Ithnain" ).toString( locale() );
00680 case 2:
00681 return ki18n( "Yau al-Thulatha" ).toString( locale() );
00682 case 3:
00683 return ki18n( "Yaum al-Arbi'a" ).toString( locale() );
00684 case 4:
00685 return ki18n( "Yaum al-Khamees" ).toString( locale() );
00686 case 5:
00687 return ki18n( "Yaum al-Jumma" ).toString( locale() );
00688 case 6:
00689 return ki18n( "Yaum al-Sabt" ).toString( locale() );
00690 case 7:
00691 return ki18n( "Yaum al-Ahad" ).toString( locale() );
00692 default:
00693 return QString();
00694 }
00695 }
00696
00697 QString KCalendarSystemHijri::weekDayName( const QDate &date, WeekDayNameFormat format ) const
00698 {
00699 return weekDayName( dayOfWeek( date ), format );
00700 }
00701
00702 QString KCalendarSystemHijri::yearString( const QDate &pDate, StringFormat format ) const
00703 {
00704 return KCalendarSystem::yearString( pDate, format );
00705 }
00706
00707 QString KCalendarSystemHijri::monthString( const QDate &pDate, StringFormat format ) const
00708 {
00709 return KCalendarSystem::monthString( pDate, format );
00710 }
00711
00712 QString KCalendarSystemHijri::dayString( const QDate &pDate, StringFormat format ) const
00713 {
00714 return KCalendarSystem::dayString( pDate, format );
00715 }
00716
00717 int KCalendarSystemHijri::yearStringToInteger( const QString &sNum, int &iLength ) const
00718 {
00719 return KCalendarSystem::yearStringToInteger( sNum, iLength );
00720 }
00721
00722 int KCalendarSystemHijri::monthStringToInteger( const QString &sNum, int &iLength ) const
00723 {
00724 return KCalendarSystem::monthStringToInteger( sNum, iLength );
00725 }
00726
00727 int KCalendarSystemHijri::dayStringToInteger( const QString &sNum, int &iLength ) const
00728 {
00729 return KCalendarSystem::dayStringToInteger( sNum, iLength );
00730 }
00731
00732 QString KCalendarSystemHijri::formatDate( const QDate &date, KLocale::DateFormat format ) const
00733 {
00734 return KCalendarSystem::formatDate( date, format );
00735 }
00736
00737 QDate KCalendarSystemHijri::readDate( const QString &str, bool *ok ) const
00738 {
00739 return KCalendarSystem::readDate( str, ok );
00740 }
00741
00742 QDate KCalendarSystemHijri::readDate( const QString &intstr, const QString &fmt, bool *ok ) const
00743 {
00744 return KCalendarSystem::readDate( intstr, fmt, ok );
00745 }
00746
00747 QDate KCalendarSystemHijri::readDate( const QString &str, KLocale::ReadDateFlags flags, bool *ok ) const
00748 {
00749 return KCalendarSystem::readDate( str, flags, ok );
00750 }
00751
00752 int KCalendarSystemHijri::weekStartDay() const
00753 {
00754 return KCalendarSystem::weekStartDay();
00755 }
00756
00757 int KCalendarSystemHijri::weekDayOfPray() const
00758 {
00759 return 5;
00760 }
00761
00762 bool KCalendarSystemHijri::isLunar() const
00763 {
00764 return true;
00765 }
00766
00767 bool KCalendarSystemHijri::isLunisolar() const
00768 {
00769 return false;
00770 }
00771
00772 bool KCalendarSystemHijri::isSolar() const
00773 {
00774 return false;
00775 }
00776
00777 bool KCalendarSystemHijri::isProleptic() const
00778 {
00779 return false;
00780 }
00781
00782 bool KCalendarSystemHijri::julianDayToDate( int jd, int &year, int &month, int &day ) const
00783 {
00784
00785 if ( jd >= earliestValidDate().toJulianDay() && jd <= latestValidDate().toJulianDay() ) {
00786
00787 year = ( jd - epoch().toJulianDay() ) / 355;
00788 while ( jd >= IslamicDate( 1, 1, year + 1 ) ) {
00789 year++;
00790 }
00791
00792 month = 1;
00793 while ( jd > IslamicDate( month, lastDayOfIslamicMonth( month, year ), year ) ) {
00794 month++;
00795 }
00796 day = jd - IslamicDate( month, 1, year ) + 1;
00797 return true;
00798 }
00799
00800 return false;
00801 }
00802
00803 bool KCalendarSystemHijri::dateToJulianDay( int year, int month, int day, int &jd ) const
00804 {
00805
00806 if ( isValid( year, month, day ) ) {
00807 jd = ( day
00808 + 29 * ( month - 1 )
00809 + month / 2
00810 + 354 * ( year - 1 )
00811 + ( 3 + ( 11 * year ) ) / 30
00812 + epoch().toJulianDay() );
00813 return true;
00814 }
00815
00816 return false;
00817 }
00818