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 <qdatetime.h>
00025
#include <qstring.h>
00026
#include <qstringlist.h>
00027
#include <math.h>
00028
00029
#include <kglobal.h>
00030
#include <klocale.h>
00031
#include <kdebug.h>
00032
#include <stdio.h>
00033
00034
#include "kcalendarsystemjalali.h"
00035
00036
static const int gMonthDay[2][13]={
00037 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00038 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00039 };
00040
00041
static const int jMonthDay[2][13] = {
00042 {0, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29},
00043 {0, 31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 30},
00044 };
00045
00046
typedef struct {
00047
int day;
00048
int mon;
00049
int year;
00050 } SDATE;
00051
00052
00053
static int Ceil(
float number)
00054 {
00055
int ret;
00056
if(
number>0)
00057
number += 0.5;
00058 ret =(
int)
number;
00059
return ret;
00060 }
00061
00062
static long jalali_jdn(
int year,
int month,
int day)
00063 {
00064
const long PERSIAN_EPOCH = 1948321;
00065
int epbase;
00066
long epyear;
00067
long mdays;
00068
long jdn;
00069 epbase = year - 474;
00070 epyear = 474 + (epbase % 2820);
00071
if (month <= 7)
00072 mdays = (month - 1) * 31;
00073
else
00074 mdays = (month - 1) * 30 + 6;
00075 jdn = day + mdays ;
00076 jdn += (((epyear * 682) - 110) / 2816) ;
00077 jdn += (epyear - 1) * 365;
00078 jdn += (epbase / 2820) * 1029983 ;
00079 jdn += (PERSIAN_EPOCH - 1);
00080
return jdn;
00081 }
00082
00083
00084
static SDATE jdn_jalali(
long jdn)
00085 {
00086
static SDATE ret;
00087
int day, month, year;
00088
int iYear, iMonth, iDay;
00089
int depoch;
00090
int cycle;
00091
int cyear;
00092
int ycycle;
00093
int aux1, aux2;
00094
int yday;
00095 day = 1;
00096 month = 1;
00097 year = 475;
00098 depoch = jdn - jalali_jdn(year,month, day);
00099 cycle = (
int) (depoch / 1029983);
00100 cyear = depoch % 1029983;
00101
if( cyear == 1029982)
00102 ycycle = 2820;
00103
else{
00104 aux1 = cyear / 366;
00105 aux2 = cyear % 366;
00106 ycycle = (((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1;
00107 }
00108 iYear = ycycle + (2820 * cycle) + 474;
00109
if (iYear <= 0)
00110 iYear = iYear - 1;
00111 year = iYear;
00112 yday = (jdn - jalali_jdn(year, month, day)) + 1;
00113
if(yday <= 186 )
00114 iMonth = Ceil((yday-1) / 31);
00115
else
00116 iMonth = Ceil((yday - 7) / 30);
00117 iMonth++;
00118 month = iMonth;
00119 iDay = (jdn - jalali_jdn(year, month, day)) + 1;
00120 ret.day = iDay;
00121 ret.mon = iMonth;
00122 ret.year = iYear;
00123
return ret;
00124 }
00125
00126
00127
00128
static long civil_jdn(
int year,
int month,
int day)
00129 {
00130
long jdn = ((1461 * (year + 4800 + ((month - 14) / 12))) / 4)
00131 + ((367 * (month - 2 - 12 * (((month - 14) / 12)))) / 12)
00132 - ((3 * (((year + 4900 + ((month - 14) / 12)) / 100))) / 4)
00133 + day - 32075;
00134
return jdn;
00135 }
00136
00137
static SDATE jdn_civil(
long jdn)
00138 {
00139
long l, n, i, j;
00140
static SDATE ret;
00141
int iday, imonth, iyear;
00142 l = jdn + 68569;
00143 n = ((4 * l) / 146097);
00144 l = l - ((146097 * n + 3) / 4);
00145 i = ((4000 * (l + 1)) / 1461001);
00146 l = l - ((1461 * i) / 4) + 31;
00147 j = ((80 * l) / 2447);
00148 iday = l - ((2447 * j) / 80);
00149 l = (j / 11);
00150 imonth = j + 2 - 12 * l;
00151 iyear = 100 * (n - 49) + i + l;
00152 ret.day = iday;
00153 ret.mon = imonth;
00154 ret.year = iyear;
00155
return (ret);
00156 }
00157
00158
static SDATE *jalaliToGregorian(
int y,
int m,
int d)
00159 {
00160
static SDATE sd;
00161
long jday = jalali_jdn(y,m,d);
00162 sd= jdn_civil(jday);
00163
return (&sd);
00164 }
00165
static SDATE *gregorianToJalali(
int y,
int m,
int d)
00166 {
00167
static SDATE sd;
00168
long jdn = civil_jdn(y,m,d);
00169 sd = jdn_jalali(jdn);
00170
return(&sd);
00171 }
00172
static void gregorianToJalali(
const QDate & date,
int * pYear,
int * pMonth,
00173
int * pDay)
00174 {
00175 SDATE *sd;
00176 sd = gregorianToJalali(date.year(), date.month(), date.day());
00177
if (pYear)
00178 *pYear = sd->year;
00179
if (pMonth)
00180 *pMonth = sd->mon;
00181
if (pDay)
00182 *pDay = sd->day;
00183
00184 }
00185
00186
00187
00188
static int isJalaliLeap(
int year)
00189 {
00190
int tmp;
00191 tmp = year % 33;
00192
if (tmp == 1 || tmp == 5||tmp==9||tmp==13||tmp==17||tmp==22||tmp==26||tmp==30)
00193
return 1;
00194
else
00195
return 0;
00196 }
00197
static int hndays(
int m,
int y)
00198 {
00199
return jMonthDay[isJalaliLeap(y)][m];
00200 }
00201
00202
00203 KCalendarSystemJalali::KCalendarSystemJalali(
const KLocale * locale)
00204 :
KCalendarSystem(locale)
00205 {
00206 }
00207
00208 KCalendarSystemJalali::~KCalendarSystemJalali()
00209 {
00210 }
00211
00212 int KCalendarSystemJalali::year(
const QDate& date)
const
00213
00214
{
00215 kdDebug(5400) <<
"Jalali year..." <<
endl;
00216
int y;
00217 gregorianToJalali(date, &y, 0, 0);
00218
return y;
00219 }
00220
00221 int KCalendarSystemJalali::month (
const QDate& date)
const
00222
00223
{
00224 kdDebug(5400) <<
"Jalali month..." <<
endl;
00225
int m;
00226 gregorianToJalali(date, 0 , &m, 0);
00227
return m;
00228 }
00229
00230 int KCalendarSystemJalali::day(
const QDate& date)
const
00231
00232
{
00233 kdDebug(5400) <<
"Jalali day..." <<
endl;
00234
int d;
00235 gregorianToJalali(date, 0, 0, &d);
00236
return d;
00237 }
00238
00239 int KCalendarSystemJalali::dayOfWeek(
const QDate& date)
const
00240
{
00241
00242
return date.dayOfWeek();
00243
00244 }
00245
00246
00247 int KCalendarSystemJalali::dayOfYear(
const QDate & date)
const
00248
{
00249
QDate first;
00250
setYMD(first, year(date), 1, 1);
00251
00252
return first.daysTo(date) + 1;
00253 }
00254
00255
00256 bool KCalendarSystemJalali::setYMD(
QDate & date,
int y,
int m,
int d)
const
00257
{
00258
00259
if ( y < minValidYear() || y >
maxValidYear() )
00260
return false;
00261
00262
if ( m < 1 || m > 12 )
00263
return false;
00264
00265
if ( d < 1 || d > hndays(m, y) )
00266
return false;
00267
00268 SDATE *gd =jalaliToGregorian( y, m, d);
00269
00270
return date.setYMD(gd->year, gd->mon, gd->day);
00271 }
00272
00273 QDate KCalendarSystemJalali::addYears(
const QDate & date,
int nyears )
const
00274
{
00275
QDate result = date;
00276
int y = year(date) + nyears;
00277
setYMD( result, y, month(date), day(date) );
00278
00279
return result;
00280 }
00281
00282 QDate KCalendarSystemJalali::addMonths(
const QDate & date,
int nmonths )
const
00283
{
00284
QDate result = date;
00285
int m = month(date);
00286
int y = year(date);
00287
00288
if ( nmonths < 0 )
00289 {
00290 m += 12;
00291 y -= 1;
00292 }
00293
00294 --m;
00295 m += nmonths;
00296 y += m / 12;
00297 m %= 12;
00298 ++m;
00299
00300
setYMD( result, y, m, day(date) );
00301
00302
return result;
00303 }
00304
00305 QDate KCalendarSystemJalali::addDays(
const QDate & date,
int ndays )
const
00306
{
00307
return date.addDays( ndays );
00308 }
00309
00310 int KCalendarSystemJalali::monthsInYear(
const QDate & date )
const
00311
{
00312 Q_UNUSED( date )
00313
00314
return 12;
00315 }
00316
00317 int KCalendarSystemJalali::daysInYear(
const QDate & date)
const
00318
{
00319 Q_UNUSED(date);
00320
int result;
00321
00322
00323 result=366;
00324
00325
00326
return result;
00327 }
00328
00329 int KCalendarSystemJalali::daysInMonth(
const QDate & date)
const
00330
{
00331 SDATE *sd = gregorianToJalali(date.year(),date.month(),date.day());
00332
return hndays(sd->mon,sd->year);
00333 }
00334
00335 int KCalendarSystemJalali::weeksInYear(
int year)
const
00336
00337
{
00338 Q_UNUSED(year);
00339
00340
return 52;
00341 }
00342
00343 int KCalendarSystemJalali::weekNumber(
const QDate& date,
int * yearNum)
const
00344
{
00345
QDate firstDayWeek1, lastDayOfYear;
00346
int y = year(date);
00347
int week;
00348
int weekDay1, dayOfWeek1InYear;
00349
00350
00351
setYMD(firstDayWeek1, y, 1, 1);
00352 weekDay1 =
dayOfWeek(firstDayWeek1);
00353
00354
00355
00356
if (weekDay1 > 4 )
00357 firstDayWeek1 =
addDays(firstDayWeek1 , 7 - weekDay1 + 1);
00358
00359 dayOfWeek1InYear =
dayOfYear(firstDayWeek1);
00360
00361
if ( dayOfYear(date) < dayOfWeek1InYear )
00362 {
00363
if ( yearNum )
00364 *yearNum = y - 1;
00365
return weeksInYear(y - 1);
00366 }
00367
00368
setYMD(lastDayOfYear, y, 12, hndays(12, y));
00369
if ( (dayOfYear(date) >=
daysInYear(date) - dayOfWeek(lastDayOfYear) + 1)
00370
00371 && dayOfWeek(lastDayOfYear) < 4)
00372 {
00373
if ( yearNum )
00374 *yearNum = y + 1;
00375 week = 1;
00376 }
00377
else
00378 week = firstDayWeek1.daysTo(date) / 7 + 1;
00379
00380
return week;
00381 }
00382
00383 QString KCalendarSystemJalali::monthName(
int month,
int year,
bool shortName)
00384
const
00385 {
00386 Q_UNUSED(year);
00387
00388
if (shortName)
00389
switch ( month )
00390 {
00391
case 1:
00392
return locale()->translate(
"Far");
00393
case 2:
00394
return locale()->translate(
"Ord");
00395
case 3:
00396
return locale()->translate(
"Kho");
00397
case 4:
00398
return locale()->translate(
"Tir");
00399
case 5:
00400
return locale()->translate(
"Mor");
00401
case 6:
00402
return locale()->translate(
"Sha");
00403
case 7:
00404
return locale()->translate(
"Meh");
00405
case 8:
00406
return locale()->translate(
"Aba");
00407
case 9:
00408
return locale()->translate(
"Aza");
00409
case 10:
00410
return locale()->translate(
"Dei");
00411
case 11:
00412
return locale()->translate(
"Bah");
00413
case 12:
00414
return locale()->translate(
"Esf");
00415 }
00416
else
00417
switch ( month )
00418 {
00419
case 1:
00420
return locale()->translate(
"Farvardin");
00421
case 2:
00422
return locale()->translate(
"Ordibehesht");
00423
case 3:
00424
return locale()->translate(
"Khordad");
00425
case 4:
00426
return locale()->translate(
"Tir");
00427
case 5:
00428
return locale()->translate(
"Mordad");
00429
case 6:
00430
return locale()->translate(
"Shahrivar");
00431
case 7:
00432
return locale()->translate(
"Mehr");
00433
case 8:
00434
return locale()->translate(
"Aban");
00435
case 9:
00436
return locale()->translate(
"Azar");
00437
case 10:
00438
return locale()->translate(
"Dei");
00439
case 11:
00440
return locale()->translate(
"Bahman");
00441
case 12:
00442
return locale()->translate(
"Esfand");
00443 }
00444
00445
return QString::null;
00446 }
00447
00448 QString KCalendarSystemJalali::monthName(
const QDate& date,
bool shortName)
00449
const
00450 {
00451
int mon;
00452 gregorianToJalali(date,0,&mon,0);
00453
00454
return (monthName(mon, 0, shortName));
00455 }
00456
00457 QString KCalendarSystemJalali::monthNamePossessive(
const QDate& date,
00458
bool shortName )
const
00459
{
00460
return monthName(date,shortName);
00461 }
00462
00463 QString KCalendarSystemJalali::monthNamePossessive(
int month,
int year,
00464
bool shortName )
const
00465
{
00466
return monthName(month,year,shortName);
00467 }
00468
00469
00470 QString KCalendarSystemJalali::weekDayName(
int day,
bool shortName)
const
00471
{
00472
if ( shortName )
00473
switch (day)
00474 {
00475
case 1:
00476
return locale()->
translate(
"2sh");
00477
case 2:
00478
return locale()->
translate(
"3sh");
00479
case 3:
00480
return locale()->
translate(
"4sh");
00481
case 4:
00482
return locale()->
translate(
"5sh");
00483
case 5:
00484
return locale()->
translate(
"Jom");
00485
case 6:
00486
return locale()->
translate(
"shn");
00487
case 7:
00488
return locale()->
translate(
"1sh");
00489 }
00490
else
00491
switch ( day )
00492 {
00493
case 1:
00494
return locale()->
translate(
"Do shanbe");
00495
case 2:
00496
return locale()->
translate(
"Se shanbe");
00497
case 3:
00498
return locale()->
translate(
"Chahar shanbe");
00499
case 4:
00500
return locale()->
translate(
"Panj shanbe");
00501
case 5:
00502
return locale()->
translate(
"Jumee");
00503
case 6:
00504
return locale()->
translate(
"Shanbe");
00505
case 7:
00506
return locale()->
translate(
"Yek-shanbe");
00507 }
00508
00509
return QString::null;
00510 }
00511
00512 QString KCalendarSystemJalali::weekDayName(
const QDate &date,
bool shortName)
00513
const
00514 {
00515
return weekDayName(dayOfWeek(date), shortName);
00516 }
00517
00518
00519 int KCalendarSystemJalali::minValidYear()
const
00520
{
00521
QDate date(1753, 1, 1);
00522
00523
return year(date);
00524 }
00525
00526
00527 int KCalendarSystemJalali::maxValidYear()
const
00528
{
00529
00530
00531
00532
00533
00534
00535
00536
return 10000;
00537 }
00538 int KCalendarSystemJalali::weekDayOfPray()
const
00539
{
00540
return 5;
00541 }
00542 QString KCalendarSystemJalali::calendarName()
const
00543
{
00544
return QString::fromLatin1(
"jalali");
00545 }
00546
00547 bool KCalendarSystemJalali::isLunar()
const
00548
{
00549
return false;
00550 }
00551
00552 bool KCalendarSystemJalali::isLunisolar()
const
00553
{
00554
return false;
00555 }
00556
00557 bool KCalendarSystemJalali::isSolar()
const
00558
{
00559
return true;
00560 }