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 }