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 }