KDECore
kcalendarsystem.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> 00003 Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> 00004 Copyright 2007, 2008, 2009, 2010 John Layt <john@layt.net> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kcalendarsystem.h" 00023 #include "kcalendarsystemprivate_p.h" 00024 00025 #include "kdebug.h" 00026 #include "kconfiggroup.h" 00027 00028 #include <QtCore/QDateTime> 00029 00030 #include "kdatetime.h" 00031 #include "kdatetimeformatter_p.h" 00032 #include "kdatetimeparser_p.h" 00033 #include "kcalendarera_p.h" 00034 #include "kcalendarsystemcoptic_p.h" 00035 #include "kcalendarsystemethiopian_p.h" 00036 #include "kcalendarsystemgregorian_p.h" 00037 #include "kcalendarsystemhebrew_p.h" 00038 #include "kcalendarsystemindiannational_p.h" 00039 #include "kcalendarsystemislamiccivil_p.h" 00040 #include "kcalendarsystemjalali_p.h" 00041 #include "kcalendarsystemjapanese_p.h" 00042 #include "kcalendarsystemjulian_p.h" 00043 #include "kcalendarsystemminguo_p.h" 00044 #include "kcalendarsystemqdate_p.h" 00045 #include "kcalendarsystemthai_p.h" 00046 00047 KCalendarSystem *KCalendarSystem::create(const QString &calendarType, const KLocale *locale) 00048 { 00049 return create(calendarSystem(calendarType), locale); 00050 } 00051 00052 KCalendarSystem *KCalendarSystem::create(const QString &calendarType, KSharedConfig::Ptr config, 00053 const KLocale *locale) 00054 { 00055 return create(calendarSystem(calendarType), config, locale); 00056 } 00057 00058 QStringList KCalendarSystem::calendarSystems() 00059 { 00060 QStringList lst; 00061 00062 lst.append(QLatin1String("coptic")); 00063 lst.append(QLatin1String("ethiopian")); 00064 lst.append(QLatin1String("gregorian")); 00065 lst.append(QLatin1String("gregorian-proleptic")); 00066 lst.append(QLatin1String("hebrew")); 00067 lst.append(QLatin1String("hijri")); 00068 lst.append(QLatin1String("indian-national")); 00069 lst.append(QLatin1String("jalali")); 00070 lst.append(QLatin1String("japanese")); 00071 lst.append(QLatin1String("julian")); 00072 lst.append(QLatin1String("minguo")); 00073 lst.append(QLatin1String("thai")); 00074 00075 return lst; 00076 } 00077 00078 QString KCalendarSystem::calendarLabel(const QString &calendarType) 00079 { 00080 if (calendarSystemsList().contains(calendarSystem(calendarType))) { 00081 return KCalendarSystem::calendarLabel(KCalendarSystem::calendarSystem(calendarType)); 00082 } else { 00083 return ki18nc("@item Calendar system", "Invalid Calendar Type").toString(KGlobal::locale()); 00084 } 00085 } 00086 00087 KCalendarSystem *KCalendarSystem::create(KLocale::CalendarSystem calendarSystem, const KLocale *locale) 00088 { 00089 return create(calendarSystem, KSharedConfig::Ptr(), locale); 00090 } 00091 00092 KCalendarSystem *KCalendarSystem::create(KLocale::CalendarSystem calendarSystem, 00093 KSharedConfig::Ptr config, 00094 const KLocale *locale) 00095 { 00096 switch (calendarSystem) { 00097 case KLocale::QDateCalendar: 00098 return new KCalendarSystemQDate(config, locale); 00099 case KLocale::CopticCalendar: 00100 return new KCalendarSystemCoptic(config, locale); 00101 case KLocale::EthiopianCalendar: 00102 return new KCalendarSystemEthiopian(config, locale); 00103 case KLocale::GregorianCalendar: 00104 return new KCalendarSystemGregorian(config, locale); 00105 case KLocale::HebrewCalendar: 00106 return new KCalendarSystemHebrew(config, locale); 00107 case KLocale::IndianNationalCalendar: 00108 return new KCalendarSystemIndianNational(config, locale); 00109 case KLocale::IslamicCivilCalendar: 00110 return new KCalendarSystemIslamicCivil(config, locale); 00111 case KLocale::JalaliCalendar: 00112 return new KCalendarSystemJalali(config, locale); 00113 case KLocale::JapaneseCalendar: 00114 return new KCalendarSystemJapanese(config, locale); 00115 case KLocale::JulianCalendar: 00116 return new KCalendarSystemJulian(config, locale); 00117 case KLocale::MinguoCalendar: 00118 return new KCalendarSystemMinguo(config, locale); 00119 case KLocale::ThaiCalendar: 00120 return new KCalendarSystemThai(config, locale); 00121 default: 00122 return new KCalendarSystemQDate(config, locale); 00123 } 00124 } 00125 00126 QList<KLocale::CalendarSystem> KCalendarSystem::calendarSystemsList() 00127 { 00128 QList<KLocale::CalendarSystem> list; 00129 00130 list.append(KLocale::QDateCalendar); 00131 list.append(KLocale::CopticCalendar); 00132 list.append(KLocale::EthiopianCalendar); 00133 list.append(KLocale::GregorianCalendar); 00134 list.append(KLocale::HebrewCalendar); 00135 list.append(KLocale::IslamicCivilCalendar); 00136 list.append(KLocale::IndianNationalCalendar); 00137 list.append(KLocale::JalaliCalendar); 00138 list.append(KLocale::JapaneseCalendar); 00139 list.append(KLocale::JulianCalendar); 00140 list.append(KLocale::MinguoCalendar); 00141 list.append(KLocale::ThaiCalendar); 00142 00143 return list; 00144 } 00145 00146 QString KCalendarSystem::calendarLabel(KLocale::CalendarSystem calendarSystem, const KLocale *locale) 00147 { 00148 switch (calendarSystem) { 00149 case KLocale::QDateCalendar: 00150 return ki18nc("@item Calendar system", "Gregorian").toString(locale); 00151 case KLocale::CopticCalendar: 00152 return ki18nc("@item Calendar system", "Coptic").toString(locale); 00153 case KLocale::EthiopianCalendar: 00154 return ki18nc("@item Calendar system", "Ethiopian").toString(locale); 00155 case KLocale::GregorianCalendar: 00156 return ki18nc("@item Calendar system", "Gregorian (Proleptic)").toString(locale); 00157 case KLocale::HebrewCalendar: 00158 return ki18nc("@item Calendar system", "Hebrew").toString(locale); 00159 case KLocale::IslamicCivilCalendar: 00160 return ki18nc("@item Calendar system", "Islamic / Hijri (Civil)").toString(locale); 00161 case KLocale::IndianNationalCalendar: 00162 return ki18nc("@item Calendar system", "Indian National").toString(locale); 00163 case KLocale::JalaliCalendar: 00164 return ki18nc("@item Calendar system", "Jalali").toString(locale); 00165 case KLocale::JapaneseCalendar: 00166 return ki18nc("@item Calendar system", "Japanese").toString(locale); 00167 case KLocale::JulianCalendar: 00168 return ki18nc("@item Calendar system", "Julian").toString(locale); 00169 case KLocale::MinguoCalendar: 00170 return ki18nc("@item Calendar system", "Taiwanese").toString(locale); 00171 case KLocale::ThaiCalendar: 00172 return ki18nc("@item Calendar system", "Thai").toString(locale); 00173 } 00174 00175 return ki18nc("@item Calendar system", "Invalid Calendar Type").toString(locale); 00176 } 00177 00178 KLocale::CalendarSystem KCalendarSystem::calendarSystemForCalendarType(const QString &calendarType ) 00179 { 00180 return calendarSystem( calendarType ); 00181 } 00182 00183 KLocale::CalendarSystem KCalendarSystem::calendarSystem(const QString &calendarType ) 00184 { 00185 if (calendarType == QLatin1String("coptic")) { 00186 return KLocale::CopticCalendar; 00187 } else if (calendarType == QLatin1String("ethiopian")) { 00188 return KLocale::EthiopianCalendar; 00189 } else if (calendarType == QLatin1String("gregorian")) { 00190 return KLocale::QDateCalendar; 00191 } else if (calendarType == QLatin1String("gregorian-proleptic")) { 00192 return KLocale::GregorianCalendar; 00193 } else if (calendarType == QLatin1String("hebrew")) { 00194 return KLocale::HebrewCalendar; 00195 } else if (calendarType == QLatin1String("hijri")) { 00196 return KLocale::IslamicCivilCalendar; 00197 } else if (calendarType == QLatin1String("indian-national")) { 00198 return KLocale::IndianNationalCalendar; 00199 } else if (calendarType == QLatin1String("jalali")) { 00200 return KLocale::JalaliCalendar; 00201 } else if (calendarType == QLatin1String("japanese")) { 00202 return KLocale::JapaneseCalendar; 00203 } else if (calendarType == QLatin1String("julian")) { 00204 return KLocale::JulianCalendar; 00205 } else if (calendarType == QLatin1String("minguo")) { 00206 return KLocale::MinguoCalendar; 00207 } else if (calendarType == QLatin1String("thai")) { 00208 return KLocale::ThaiCalendar; 00209 } else { 00210 return KLocale::QDateCalendar; 00211 } 00212 } 00213 00214 QString KCalendarSystem::calendarType(KLocale::CalendarSystem calendarSystem) 00215 { 00216 if (calendarSystem == KLocale::QDateCalendar) { 00217 return QLatin1String("gregorian"); 00218 } else if (calendarSystem == KLocale::CopticCalendar) { 00219 return QLatin1String("coptic"); 00220 } else if (calendarSystem == KLocale::EthiopianCalendar) { 00221 return QLatin1String("ethiopian"); 00222 } else if (calendarSystem == KLocale::GregorianCalendar) { 00223 return QLatin1String("gregorian-proleptic"); 00224 } else if (calendarSystem == KLocale::HebrewCalendar) { 00225 return QLatin1String("hebrew"); 00226 } else if (calendarSystem == KLocale::IndianNationalCalendar) { 00227 return QLatin1String("indian-national"); 00228 } else if (calendarSystem == KLocale::IslamicCivilCalendar) { 00229 return QLatin1String("hijri"); 00230 } else if (calendarSystem == KLocale::JalaliCalendar) { 00231 return QLatin1String("jalali"); 00232 } else if (calendarSystem == KLocale::JapaneseCalendar) { 00233 return QLatin1String("japanese"); 00234 } else if (calendarSystem == KLocale::JulianCalendar) { 00235 return QLatin1String("julian"); 00236 } else if (calendarSystem == KLocale::MinguoCalendar) { 00237 return QLatin1String("minguo"); 00238 } else if (calendarSystem == KLocale::ThaiCalendar) { 00239 return QLatin1String("thai"); 00240 } else { 00241 return QLatin1String("gregorian"); 00242 } 00243 } 00244 00245 // Shared d pointer base class definitions 00246 00247 KCalendarSystemPrivate::KCalendarSystemPrivate(KCalendarSystem *q_ptr) 00248 : q(q_ptr), 00249 m_eraList(0), 00250 m_shortYearWindowStartYear(2000) 00251 { 00252 } 00253 00254 KCalendarSystemPrivate::~KCalendarSystemPrivate() 00255 { 00256 delete m_eraList; 00257 } 00258 00259 // Dummy version using Gregorian as an example 00260 // This method MUST be re-implemented in any new Calendar System 00261 KLocale::CalendarSystem KCalendarSystemPrivate::calendarSystem() const 00262 { 00263 return KLocale::QDateCalendar; 00264 } 00265 00266 // Dummy version as an example, remember to translate (see Gregorian for example) 00267 // Add the Era's in chronological order, from earliest to latest 00268 // This method MUST be re-implemented in any new Calendar System 00269 void KCalendarSystemPrivate::loadDefaultEraList() 00270 { 00271 addEra('-', 1, q->epoch().addDays(-1), -1, q->earliestValidDate(), QLatin1String("Before KDE"), QLatin1String("BK"), QLatin1String("%Ey %EC")); 00272 addEra('+', 1, q->epoch(), 1, q->latestValidDate(), QLatin1String("Anno KDE"), QLatin1String("AK"), QLatin1String("%Ey %EC")); 00273 } 00274 00275 // Dummy version using Gregorian as an example 00276 // This method MUST be re-implemented in any new Calendar System 00277 int KCalendarSystemPrivate::monthsInYear(int year) const 00278 { 00279 Q_UNUSED(year) 00280 return 12; 00281 } 00282 00283 // Dummy version using Gregorian as an example 00284 // This method MUST be re-implemented in any new Calendar System 00285 int KCalendarSystemPrivate::daysInMonth(int year, int month) const 00286 { 00287 if (month == 2) { 00288 if (isLeapYear(year)) { 00289 return 29; 00290 } else { 00291 return 28; 00292 } 00293 } 00294 00295 if (month == 4 || month == 6 || month == 9 || month == 11) { 00296 return 30; 00297 } 00298 00299 return 31; 00300 } 00301 00302 // Dummy version using Gregorian as an example 00303 // This method MUST be re-implemented in any new Calendar System 00304 int KCalendarSystemPrivate::daysInYear(int year) const 00305 { 00306 if (isLeapYear(year)) { 00307 return 366; 00308 } else { 00309 return 365; 00310 } 00311 } 00312 00313 // Dummy version using Gregorian as an example 00314 // This method MUST be re-implemented in any new Calendar System 00315 int KCalendarSystemPrivate::daysInWeek() const 00316 { 00317 return 7; 00318 } 00319 00320 // Dummy version using Gregorian as an example 00321 // This method MUST be re-implemented in any new Calendar System 00322 bool KCalendarSystemPrivate::isLeapYear(int year) const 00323 { 00324 if (year < 1) { 00325 year = year + 1; 00326 } 00327 00328 if (year % 4 == 0) { 00329 if (year % 100 != 0) { 00330 return true; 00331 } else if (year % 400 == 0) { 00332 return true; 00333 } 00334 } 00335 00336 return false; 00337 } 00338 00339 // Dummy version using Gregorian as an example 00340 // This method MUST be re-implemented in any new Calendar System 00341 bool KCalendarSystemPrivate::hasLeapMonths() const 00342 { 00343 return false; 00344 } 00345 00346 // Dummy version using Gregorian as an example 00347 // This method MUST be re-implemented in any new Calendar System 00348 bool KCalendarSystemPrivate::hasYearZero() const 00349 { 00350 return false; 00351 } 00352 00353 // Dummy version using Gregorian as an example 00354 // This method MUST be re-implemented in any new Calendar System 00355 int KCalendarSystemPrivate::maxDaysInWeek() const 00356 { 00357 return 7; 00358 } 00359 00360 // Dummy version using Gregorian as an example 00361 // This method MUST be re-implemented in any new Calendar System 00362 int KCalendarSystemPrivate::maxMonthsInYear() const 00363 { 00364 return 12; 00365 } 00366 00367 // Convenince, faster than calling year( ealiestValidDate() ), 00368 // needed in fake-virtual functions so don't remove 00369 // Dummy version using Gregorian as an example 00370 // This method MUST be re-implemented in any new Calendar System 00371 int KCalendarSystemPrivate::earliestValidYear() const 00372 { 00373 return -4712; 00374 } 00375 00376 // Convenince, faster than calling year( latestValidDate() ), 00377 // needed in fake-virtual functions so don't remove 00378 // Dummy version using Gregorian as an example 00379 // This method MUST be re-implemented in any new Calendar System 00380 int KCalendarSystemPrivate::latestValidYear() const 00381 { 00382 return 9999; 00383 } 00384 00385 // Dummy version 00386 // This method MUST be re-implemented in any new Calendar System 00387 QString KCalendarSystemPrivate::monthName(int month, int year, KLocale::DateTimeComponentFormat format, bool possessive) const 00388 { 00389 Q_UNUSED(month); 00390 Q_UNUSED(year); 00391 Q_UNUSED(format); 00392 Q_UNUSED(possessive); 00393 return QString(); 00394 } 00395 00396 // Dummy version 00397 // This method MUST be re-implemented in any new Calendar System 00398 QString KCalendarSystemPrivate::weekDayName(int weekDay, KLocale::DateTimeComponentFormat format) const 00399 { 00400 Q_UNUSED(weekDay); 00401 Q_UNUSED(format); 00402 return QString(); 00403 } 00404 00405 // Reimplement if special maths handling required, e.g. Hebrew. 00406 int KCalendarSystemPrivate::week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const 00407 { 00408 int y, m, d; 00409 q->julianDayToDate(date.toJulianDay(), y, m, d); 00410 00411 switch (weekNumberSystem) { 00412 case KLocale::IsoWeekNumber: 00413 return isoWeekNumber(date, yearNum); 00414 case KLocale::FirstFullWeek: 00415 return regularWeekNumber(date, locale()->weekStartDay(), 0, yearNum); 00416 case KLocale::FirstPartialWeek: 00417 return regularWeekNumber(date, locale()->weekStartDay(), 1, yearNum); 00418 case KLocale::SimpleWeek: 00419 return simpleWeekNumber(date, yearNum); 00420 case KLocale::DefaultWeekNumber: 00421 default: 00422 return week(date, locale()->weekNumberSystem(), yearNum); 00423 } 00424 } 00425 00426 // Reimplement if special maths handling required, e.g. Hebrew. 00427 int KCalendarSystemPrivate::isoWeekNumber(const QDate &date, int *yearNum) const 00428 { 00429 int y, m, d; 00430 q->julianDayToDate(date.toJulianDay(), y, m, d); 00431 00432 QDate firstDayWeek1, lastDay; 00433 int week; 00434 int weekDay1, dayOfWeek1InYear; 00435 00436 // let's guess 1st day of 1st week 00437 firstDayWeek1 = firstDayOfYear(y); 00438 weekDay1 = dayOfWeek(firstDayWeek1); 00439 00440 // iso 8601: week 1 is the first containing thursday and week starts on monday 00441 if (weekDay1 > 4 /*Thursday*/) { 00442 firstDayWeek1 = q->addDays(firstDayWeek1 , daysInWeek() - weekDay1 + 1); // next monday 00443 } 00444 00445 dayOfWeek1InYear = dayOfYear(firstDayWeek1); 00446 00447 // our date in prev year's week 00448 if (dayOfYear(date) < dayOfWeek1InYear) { 00449 if (yearNum) { 00450 *yearNum = addYears(y, - 1); 00451 } 00452 return isoWeeksInYear(addYears(y, - 1)); 00453 } 00454 00455 // let's check if its last week belongs to next year 00456 lastDay = lastDayOfYear(y); 00457 00458 // if our date is in last week && 1st week in next year has thursday 00459 if ((dayOfYear(date) >= daysInYear(y) - dayOfWeek(lastDay) + 1) 00460 && dayOfWeek(lastDay) < 4) { 00461 if (yearNum) { 00462 * yearNum = addYears(y, 1); 00463 } 00464 week = 1; 00465 } else { 00466 // To calculate properly the number of weeks from day a to x let's make a day 1 of week 00467 if (weekDay1 < 5) { 00468 firstDayWeek1 = q->addDays(firstDayWeek1, -(weekDay1 - 1)); 00469 } 00470 00471 if (yearNum) { 00472 * yearNum = y; 00473 } 00474 00475 week = firstDayWeek1.daysTo(date) / daysInWeek() + 1; 00476 } 00477 00478 return week; 00479 } 00480 00481 // Reimplement if special maths handling required, e.g. Hebrew. 00482 int KCalendarSystemPrivate::regularWeekNumber(const QDate &date, int weekStartDay, int firstWeekNumber, int *weekYear) const 00483 { 00484 int y, m, d; 00485 q->julianDayToDate(date.toJulianDay(), y, m, d); 00486 00487 int firstWeekDayOffset = (dayOfWeek(date) - weekStartDay + daysInWeek()) % daysInWeek(); 00488 int dayInYear = date.toJulianDay() - firstDayOfYear(y).toJulianDay(); // 0 indexed 00489 int week = ((dayInYear - firstWeekDayOffset + daysInWeek()) / daysInWeek()); 00490 00491 if (dayOfWeek(firstDayOfYear(y)) != weekStartDay) { 00492 week = week + firstWeekNumber; 00493 } 00494 00495 if (week < 1) { 00496 y = y - 1; 00497 week = regularWeeksInYear(y, weekStartDay, firstWeekNumber); 00498 } 00499 00500 if (weekYear) { 00501 *weekYear = y; 00502 } 00503 00504 return week; 00505 } 00506 00507 // Reimplement if special maths handling required, e.g. Hebrew. 00508 int KCalendarSystemPrivate::simpleWeekNumber(const QDate &date, int *yearNum) const 00509 { 00510 int y, m, d; 00511 q->julianDayToDate(date.toJulianDay(), y, m, d); 00512 if (yearNum) { 00513 *yearNum = y; 00514 } 00515 return ((date.toJulianDay() - firstDayOfYear(y).toJulianDay()) / daysInWeek()) + 1; 00516 } 00517 00518 // Reimplement if special maths handling required, e.g. Hebrew. 00519 int KCalendarSystemPrivate::weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem) const 00520 { 00521 switch (weekNumberSystem) { 00522 case KLocale::IsoWeekNumber: 00523 return isoWeeksInYear(year); 00524 case KLocale::FirstFullWeek: 00525 return regularWeeksInYear(year, locale()->weekStartDay(), 0); 00526 case KLocale::FirstPartialWeek: 00527 return regularWeeksInYear(year, locale()->weekStartDay(), 1); 00528 case KLocale::SimpleWeek: 00529 return simpleWeeksInYear(year); 00530 case KLocale::DefaultWeekNumber: 00531 default: 00532 return weeksInYear(year, locale()->weekNumberSystem()); 00533 } 00534 } 00535 00536 // Reimplement if special maths handling required, e.g. Hebrew. 00537 int KCalendarSystemPrivate::isoWeeksInYear(int year) const 00538 { 00539 QDate lastDayOfThisYear = lastDayOfYear(year); 00540 00541 int weekYear = year; 00542 int lastWeekInThisYear = isoWeekNumber(lastDayOfThisYear, &weekYear); 00543 00544 // If error, or the last day of the year is in the first week of next year use the week before 00545 if (lastWeekInThisYear < 1 || weekYear != year) { 00546 lastWeekInThisYear = isoWeekNumber(q->addDays(lastDayOfThisYear, -7), &weekYear); 00547 } 00548 00549 return lastWeekInThisYear; 00550 } 00551 00552 // Reimplement if special maths handling required, e.g. Hebrew. 00553 int KCalendarSystemPrivate::regularWeeksInYear(int year, int weekStartDay, int firstWeekNumber) const 00554 { 00555 return regularWeekNumber(lastDayOfYear(year), weekStartDay, firstWeekNumber, 0); 00556 } 00557 00558 // Reimplement if special maths handling required, e.g. Hebrew. 00559 int KCalendarSystemPrivate::simpleWeeksInYear(int year) const 00560 { 00561 return simpleWeekNumber(lastDayOfYear(year), 0); 00562 } 00563 00564 // Reimplement if special maths handling required, e.g. Hebrew. 00565 // Works for calendars with constant number of months, or where leap month is last month of year 00566 // Will not work for Hebrew or others where leap month is inserted in middle of year 00567 void KCalendarSystemPrivate::dateDifference(const QDate &fromDate, const QDate &toDate, 00568 int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const 00569 { 00570 // This could be optimised a little but is left in full as it's easier to understand 00571 int dy = 0; 00572 int dm = 0; 00573 int dd = 0; 00574 int dir = 1; 00575 00576 if (toDate < fromDate) { 00577 dateDifference(toDate, fromDate, &dy, &dm, &dd, 0); 00578 dir = -1; 00579 } else if (toDate > fromDate) { 00580 00581 int fromYear = q->year(fromDate); 00582 int toYear = q->year(toDate); 00583 int fromMonth = q->month(fromDate); 00584 int toMonth = q->month(toDate); 00585 int fromDay = q->day(fromDate); 00586 int toDay = q->day(toDate); 00587 00588 int monthsInPrevYear = monthsInYear(addYears(toYear, -1)); 00589 int daysInPrevMonth = q->daysInMonth(q->addMonths(toDate, -1)); 00590 int daysInFromMonth = daysInMonth(fromYear, fromMonth); 00591 int daysInToMonth = daysInMonth(toYear, toMonth); 00592 00593 // Calculate years difference 00594 if (toYear == fromYear) { 00595 dy = 0; 00596 } else if (toMonth > fromMonth) { 00597 dy = differenceYearNumbers(fromYear, toYear); 00598 } else if (toMonth < fromMonth) { 00599 dy = differenceYearNumbers(fromYear, toYear) - 1; 00600 } else { // toMonth == fromMonth 00601 // Allow for last day of month to last day of month and leap days 00602 // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years 00603 if ((toDay >= fromDay) || (fromDay == daysInFromMonth && toDay == daysInToMonth)) { 00604 dy = differenceYearNumbers(fromYear, toYear); 00605 } else { 00606 dy = differenceYearNumbers(fromYear, toYear) - 1; 00607 } 00608 } 00609 00610 // Calculate months and days difference 00611 if (toDay >= fromDay) { 00612 dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear; 00613 dd = toDay - fromDay; 00614 } else { // toDay < fromDay 00615 // Allow for last day of month to last day of month and leap days 00616 // e.g. 2010-03-31 to 2010-04-30 is 1 month 00617 // 2000-02-29 to 2001-02-28 is 1 year 00618 // 2000-02-29 to 2001-03-01 is 1 year 1 day 00619 int prevMonth = q->month(q->addMonths(toDate, -1)); 00620 if (fromDay == daysInFromMonth && toDay == daysInToMonth) { 00621 dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear; 00622 dd = 0; 00623 } else if (prevMonth == fromMonth && daysInPrevMonth < daysInFromMonth) { 00624 // Special case where fromDate = leap day and toDate in month following but non-leap year 00625 // e.g. 2000-02-29 to 2001-03-01 needs to use 29 to calculate day number not 28 00626 dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear; 00627 dd = (daysInFromMonth + toDay - fromDay) % daysInFromMonth; 00628 } else { 00629 dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear; 00630 dd = (daysInPrevMonth + toDay - fromDay) % daysInPrevMonth; 00631 } 00632 } 00633 00634 } 00635 00636 // Only return values if we have a valid pointer 00637 if (yearsDiff) { 00638 *yearsDiff = dy; 00639 } 00640 if (monthsDiff) { 00641 *monthsDiff = dm; 00642 } 00643 if (daysDiff) { 00644 *daysDiff = dd; 00645 } 00646 if (direction) { 00647 *direction = dir; 00648 } 00649 } 00650 00651 // Reimplement if special maths handling required, e.g. Hebrew 00652 // Allows for calendars with leap months at end of year but not during year 00653 int KCalendarSystemPrivate::yearsDifference(const QDate &fromDate, const QDate &toDate) const 00654 { 00655 // This could be optimised a little but is left in full as it's easier to understand 00656 // Alternatively could just call dateDifference(), but this is slightly more efficient 00657 00658 if (toDate < fromDate) { 00659 return 0 - yearsDifference(toDate, fromDate); 00660 } 00661 00662 if (toDate == fromDate) { 00663 return 0; 00664 } 00665 00666 int fromYear = q->year(fromDate); 00667 int toYear = q->year(toDate); 00668 00669 if (toYear == fromYear) { 00670 return 0; 00671 } 00672 00673 int fromMonth = q->month(fromDate); 00674 int toMonth = q->month(toDate); 00675 00676 if (toMonth > fromMonth) { 00677 return differenceYearNumbers(fromYear, toYear); 00678 } 00679 00680 if (toMonth < fromMonth) { 00681 return differenceYearNumbers(fromYear, toYear) - 1; 00682 } 00683 00684 // toMonth == fromMonth 00685 int fromDay = q->day(fromDate); 00686 int toDay = q->day(toDate); 00687 00688 // Adjust for month numbers in from and to year 00689 // Allow for last day of month to last day of month and leap days 00690 // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years 00691 if ((toDay >= fromDay) || 00692 (fromDay == daysInMonth(fromYear, fromMonth) && 00693 toDay == daysInMonth(toYear, toMonth))) { 00694 return differenceYearNumbers(fromYear, toYear); 00695 } else { 00696 return differenceYearNumbers(fromYear, toYear) - 1; 00697 } 00698 00699 } 00700 00701 // Reimplement if special maths handling required, e.g. maybe Hebrew? 00702 // Allows for calendars with leap months 00703 int KCalendarSystemPrivate::monthsDifference(const QDate &fromDate, const QDate &toDate) const 00704 { 00705 if (toDate < fromDate) { 00706 return 0 - monthsDifference(toDate, fromDate); 00707 } 00708 00709 if (toDate == fromDate) { 00710 return 0; 00711 } 00712 00713 int fromYear = q->year(fromDate); 00714 int toYear = q->year(toDate); 00715 int fromMonth = q->month(fromDate); 00716 int toMonth = q->month(toDate); 00717 int fromDay = q->day(fromDate); 00718 int toDay = q->day(toDate); 00719 00720 int monthsInPreceedingYears; 00721 00722 // Calculate number of months in full years preceding toYear 00723 if (toYear == fromYear) { 00724 monthsInPreceedingYears = 0; 00725 } else if (hasLeapMonths()) { 00726 monthsInPreceedingYears = 0; 00727 for (int y = fromYear; y < toYear; y = addYears(y, 1)) { 00728 monthsInPreceedingYears = monthsInPreceedingYears + monthsInYear(y); 00729 } 00730 } else { 00731 monthsInPreceedingYears = differenceYearNumbers(fromYear, toYear) * monthsInYear(toYear); 00732 } 00733 00734 // Adjust for months in from and to year 00735 // Allow for last day of month to last day of month and leap days 00736 // e.g. 2010-03-31 to 2010-04-30 is 1 month not 0 months 00737 // also 2000-02-29 to 2001-02-28 is 12 months not 11 months 00738 if ((toDay >= fromDay) || 00739 (fromDay == daysInMonth(fromYear, fromMonth) && 00740 toDay == daysInMonth(toYear, toMonth))) { 00741 return monthsInPreceedingYears + toMonth - fromMonth; 00742 } else { 00743 return monthsInPreceedingYears + toMonth - fromMonth - 1; 00744 } 00745 } 00746 00747 // Reimplement if special string to integer handling required, e.g. Hebrew. 00748 // Peel a number off the front of a string which may have other trailing chars after the number 00749 // Stop either at either maxLength, eos, or first non-digit char 00750 int KCalendarSystemPrivate::integerFromString(const QString &string, int maxLength, int &readLength) const 00751 { 00752 int value = -1; 00753 int position = 0; 00754 readLength = 0; 00755 bool ok = false; 00756 00757 if (maxLength < 0) { 00758 maxLength = string.length(); 00759 } 00760 00761 while (position < string.length() && 00762 position < maxLength && 00763 string.at(position).isDigit()) { 00764 position++; 00765 } 00766 00767 if (position > 0) { 00768 value = string.left(position).toInt(&ok); 00769 if (ok) { 00770 readLength = position; 00771 } else { 00772 value = -1; 00773 } 00774 } 00775 00776 return value; 00777 } 00778 00779 // Reimplement if special integer to string handling required, e.g. Hebrew. 00780 // Utility to convert an integer into the correct display string form 00781 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar) const 00782 { 00783 return stringFromInteger(number, padWidth, padChar, q->locale()->dateTimeDigitSet()); 00784 } 00785 00786 // Reimplement if special integer to string handling required, e.g. Hebrew. 00787 // Utility to convert an integer into the correct display string form 00788 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar, KLocale::DigitSet digitSet) const 00789 { 00790 if (padChar == QLatin1Char('\0') || padWidth == 0) { 00791 return q->locale()->convertDigits(QString::number(number), digitSet); 00792 } else { 00793 return q->locale()->convertDigits(QString::number(number).rightJustified(padWidth, padChar), digitSet); 00794 } 00795 } 00796 00797 // Allows us to set dates outside publically valid range, USE WITH CARE!!!! 00798 bool KCalendarSystemPrivate::setAnyDate(QDate &date, int year, int month, int day) const 00799 { 00800 int jd; 00801 q->dateToJulianDay(year, month, day, jd); 00802 date = QDate::fromJulianDay(jd); 00803 return true; 00804 } 00805 00806 // Utility to correctly add years to a year number because some systems such as 00807 // Julian and Gregorian calendars don't have a year 0 00808 int KCalendarSystemPrivate::addYears(int originalYear, int addYears) const 00809 { 00810 int newYear = originalYear + addYears; 00811 00812 if (!hasYearZero()) { 00813 if (originalYear > 0 && newYear <= 0) { 00814 newYear = newYear - 1; 00815 } else if (originalYear < 0 && newYear >= 0) { 00816 newYear = newYear + 1; 00817 } 00818 } 00819 00820 return newYear; 00821 } 00822 00823 // Utility to correctly return number of years between two year numbers because some systems such as 00824 // Julian and Gregorian calendars don't have a year 0 00825 int KCalendarSystemPrivate::differenceYearNumbers(int fromYear, int toYear) const 00826 { 00827 int dy = toYear - fromYear; 00828 00829 if (!hasYearZero()) { 00830 if (toYear > 0 && fromYear < 0) { 00831 dy = dy - 1; 00832 } else if (toYear < 0 && fromYear > 0) { 00833 dy = dy + 1; 00834 } 00835 } 00836 00837 return dy; 00838 } 00839 00840 QDate KCalendarSystemPrivate::invalidDate() const 00841 { 00842 //Is QDate's way of saying is invalid 00843 return QDate(); 00844 } 00845 00846 QString KCalendarSystemPrivate::simpleDateString(const QString &str) const 00847 { 00848 QString newStr; 00849 for (int i = 0; i < str.length(); i++) { 00850 if (str.at(i).isLetterOrNumber()) { 00851 newStr.append(str.at(i)); 00852 } else { 00853 newStr.append(QLatin1Char(' ')); 00854 } 00855 } 00856 newStr.simplified(); 00857 return newStr; 00858 } 00859 00860 int KCalendarSystemPrivate::dayOfYear(const QDate &date) const 00861 { 00862 int y, m, d, jdFirstDayOfYear; 00863 q->julianDayToDate(date.toJulianDay(), y, m, d); 00864 q->dateToJulianDay(y, 1, 1, jdFirstDayOfYear); 00865 //Take the jd of the given date, and subtract the jd of the first day of that year 00866 return (date.toJulianDay() - jdFirstDayOfYear + 1); 00867 } 00868 00869 int KCalendarSystemPrivate::dayOfWeek(const QDate &date) const 00870 { 00871 // Makes assumption that Julian Day 0 was day 1 of week 00872 // This is true for Julian/Gregorian calendar with jd 0 being Monday 00873 // We add 1 for ISO compliant numbering for 7 day week 00874 // Assumes we've never skipped weekdays 00875 return ((date.toJulianDay() % daysInWeek()) + 1); 00876 } 00877 00878 QDate KCalendarSystemPrivate::firstDayOfYear(int year) const 00879 { 00880 int jd; 00881 q->dateToJulianDay(year, 1, 1, jd); 00882 return QDate::fromJulianDay(jd); 00883 } 00884 00885 QDate KCalendarSystemPrivate::lastDayOfYear(int year) const 00886 { 00887 int jd; 00888 q->dateToJulianDay(year, 1, 1, jd); 00889 jd = jd + daysInYear(year) - 1; 00890 return QDate::fromJulianDay(jd); 00891 } 00892 00893 QDate KCalendarSystemPrivate::firstDayOfMonth(int year, int month) const 00894 { 00895 int jd; 00896 q->dateToJulianDay(year, month, 1, jd); 00897 return QDate::fromJulianDay(jd); 00898 } 00899 00900 QDate KCalendarSystemPrivate::lastDayOfMonth(int year, int month) const 00901 { 00902 int jd; 00903 q->dateToJulianDay(year, month, 1, jd); 00904 jd = jd + daysInMonth(year, month) - 1; 00905 return QDate::fromJulianDay(jd); 00906 } 00907 00908 const KLocale * KCalendarSystemPrivate::locale() const 00909 { 00910 if (m_locale) { 00911 return m_locale; 00912 } else { 00913 return KGlobal::locale(); 00914 } 00915 } 00916 00917 QList<KCalendarEra> *KCalendarSystemPrivate::eraList() const 00918 { 00919 return m_eraList; 00920 } 00921 00922 KCalendarEra KCalendarSystemPrivate::era(const QDate &eraDate) const 00923 { 00924 for (int i = m_eraList->count() - 1; i >= 0; --i) { 00925 if (m_eraList->at(i).isInEra(eraDate)) { 00926 return m_eraList->at(i); 00927 } 00928 } 00929 return KCalendarEra(); 00930 } 00931 00932 KCalendarEra KCalendarSystemPrivate::era(const QString &eraName, int yearInEra) const 00933 { 00934 Q_UNUSED(yearInEra) 00935 00936 for (int i = m_eraList->count() - 1; i >= 0; --i) { 00937 KCalendarEra era = m_eraList->at(i); 00938 if (era.name(KLocale::LongName).toLower() == eraName.toLower() || 00939 era.name(KLocale::ShortName).toLower() == eraName.toLower()) { 00940 return era; 00941 } 00942 } 00943 return KCalendarEra(); 00944 } 00945 00946 void KCalendarSystemPrivate::loadEraList(const KConfigGroup & cg) 00947 { 00948 delete m_eraList; 00949 m_eraList = new QList<KCalendarEra>; 00950 QString eraKey = QString::fromLatin1("Era1"); 00951 int i = 1; 00952 while (cg.hasKey(eraKey)) { 00953 QString eraEntry = cg.readEntry(eraKey, QString()); 00954 if (!eraEntry.isEmpty()) { 00955 // Based on LC_TIME, but different! 00956 // Includes long and short names, uses ISO fomat dates 00957 // e.g. +:1:0001-01-01:9999-12-31:Anno Domini:AD:%EC %Ey 00958 QChar direction = eraEntry.section(QLatin1Char(':'), 0, 0).at(0); 00959 QDate startDate, endDate; 00960 int startYear; 00961 QString buffer = eraEntry.section(QLatin1Char(':'), 2, 2); 00962 if (buffer.isEmpty()) { 00963 if (direction == QLatin1Char('-')) { 00964 startDate = q->latestValidDate(); 00965 } else { 00966 startDate = q->earliestValidDate(); 00967 } 00968 } else { 00969 startDate = q->readDate(buffer, KLocale::IsoFormat); 00970 } 00971 if (q->isValid(startDate)) { 00972 startYear = q->year(startDate); 00973 } else { 00974 startYear = eraEntry.section(QLatin1Char(':'), 1, 1).toInt(); //Use offset 00975 } 00976 00977 buffer = eraEntry.section(QLatin1Char(':'), 3, 3); 00978 if (buffer.isEmpty()) { 00979 if (direction == QLatin1Char('-')) { 00980 endDate = q->earliestValidDate(); 00981 } else { 00982 endDate = q->latestValidDate(); 00983 } 00984 } else { 00985 endDate = q->readDate(buffer, KLocale::IsoFormat); 00986 } 00987 addEra(direction.toLatin1(), eraEntry.section(QLatin1Char(':'), 1, 1).toInt(), 00988 startDate, startYear, endDate, eraEntry.section(QLatin1Char(':'), 4, 4), 00989 eraEntry.section(QLatin1Char(':'), 5, 5), eraEntry.section(QLatin1Char(':'), 6)); 00990 } 00991 ++i; 00992 eraKey = QString::fromLatin1("Era%1").arg(i); 00993 } 00994 00995 if (m_eraList->isEmpty()) { 00996 loadDefaultEraList(); 00997 } 00998 } 00999 01000 void KCalendarSystemPrivate::addEra(char direction, int offset, 01001 const QDate &startDate, int startYear, const QDate &endDate, 01002 const QString &name, const QString &shortName, 01003 const QString &format) 01004 { 01005 KCalendarEra newEra; 01006 01007 newEra.m_sequence = m_eraList->count() + 1; 01008 if (direction == '-') { 01009 newEra.m_direction = -1; 01010 } else { 01011 newEra.m_direction = 1; 01012 } 01013 newEra.m_offset = offset; 01014 newEra.m_startDate = startDate; 01015 newEra.m_startYear = startYear; 01016 newEra.m_endDate = endDate; 01017 newEra.m_longName = name; 01018 newEra.m_shortName = shortName; 01019 newEra.m_format = format; 01020 01021 m_eraList->append(newEra); 01022 } 01023 01024 int KCalendarSystemPrivate::shortYearWindowStartYear() const 01025 { 01026 return m_shortYearWindowStartYear; 01027 } 01028 01029 int KCalendarSystemPrivate::applyShortYearWindow(int inputYear) const 01030 { 01031 if (inputYear >= 0 && inputYear <= 99) { 01032 int shortStartYear = m_shortYearWindowStartYear % 100; 01033 int yearOffset = m_shortYearWindowStartYear - shortStartYear; 01034 if (inputYear >= shortStartYear) { 01035 return inputYear + yearOffset; 01036 } else { 01037 return inputYear + yearOffset + 100; 01038 } 01039 } else { 01040 return inputYear; 01041 } 01042 } 01043 01044 void KCalendarSystemPrivate::loadShortYearWindowStartYear(const KConfigGroup & cg) 01045 { 01046 // Default to 2000 for backwards compatibility 01047 // as that's the old readDate() default value 01048 int startYear = 2000; 01049 if (cg.exists()) { 01050 startYear = cg.readEntry("ShortYearWindowStartYear", 2000); 01051 } 01052 m_shortYearWindowStartYear = startYear; 01053 } 01054 01055 KSharedConfig::Ptr KCalendarSystemPrivate::config() 01056 { 01057 if (m_config == KSharedConfig::Ptr()) { 01058 return KGlobal::config(); 01059 } else { 01060 return m_config; 01061 } 01062 } 01063 01064 void KCalendarSystemPrivate::loadConfig(const QString & calendarType) 01065 { 01066 KConfigGroup localeGroup(config(), QString::fromLatin1("Locale")); 01067 KConfigGroup calendarGroup = localeGroup.group(QString::fromLatin1("KCalendarSystem %1").arg(calendarType)); 01068 loadEraList(calendarGroup); 01069 loadShortYearWindowStartYear(calendarGroup); 01070 } 01071 01072 01073 KCalendarSystem::KCalendarSystem(const KLocale *locale) 01074 : d_ptr(new KCalendarSystemPrivate(this)) 01075 { 01076 d_ptr->m_config = KSharedConfig::Ptr(); 01077 d_ptr->m_locale = locale; 01078 } 01079 01080 KCalendarSystem::KCalendarSystem(const KSharedConfig::Ptr config, const KLocale *locale) 01081 : d_ptr(new KCalendarSystemPrivate(this)) 01082 { 01083 d_ptr->m_config = config; 01084 d_ptr->m_locale = locale; 01085 } 01086 01087 KCalendarSystem::KCalendarSystem(KCalendarSystemPrivate &dd, const KSharedConfig::Ptr config, const KLocale *locale) 01088 : d_ptr(&dd) 01089 { 01090 d_ptr->m_config = config; 01091 d_ptr->m_locale = locale; 01092 } 01093 01094 KCalendarSystem::~KCalendarSystem() 01095 { 01096 delete d_ptr; 01097 } 01098 01099 // NOT VIRTUAL - If override needed use shared-d 01100 KLocale::CalendarSystem KCalendarSystem::calendarSystem() const 01101 { 01102 Q_D(const KCalendarSystem); 01103 01104 return d->calendarSystem(); 01105 } 01106 01107 // NOT VIRTUAL - If override needed use shared-d 01108 QString KCalendarSystem::calendarLabel() const 01109 { 01110 return KCalendarSystem::calendarLabel(calendarSystem()); 01111 } 01112 01113 // Dummy version using Gregorian as an example 01114 // This method MUST be re-implemented in any new Calendar System 01115 QDate KCalendarSystem::epoch() const 01116 { 01117 return QDate::fromJulianDay(38); 01118 } 01119 01120 QDate KCalendarSystem::earliestValidDate() const 01121 { 01122 return epoch(); 01123 } 01124 01125 // Dummy version using Gregorian as an example 01126 // This method MUST be re-implemented in any new Calendar System 01127 QDate KCalendarSystem::latestValidDate() const 01128 { 01129 // Default to Gregorian 9999-12-31 01130 return QDate::fromJulianDay(5373484); 01131 } 01132 01133 bool KCalendarSystem::isValid(int year, int month, int day) const 01134 { 01135 Q_D(const KCalendarSystem); 01136 01137 if (year < d->earliestValidYear() || year > d->latestValidYear() || 01138 (!d->hasYearZero() && year == 0)) { 01139 return false; 01140 } 01141 01142 if (month < 1 || month > d->monthsInYear(year)) { 01143 return false; 01144 } 01145 01146 if (day < 1 || day > d->daysInMonth(year, month)) { 01147 return false; 01148 } 01149 01150 return true; 01151 } 01152 01153 // NOT VIRTUAL - If override needed use shared-d 01154 bool KCalendarSystem::isValid(int year, int dayOfYear) const 01155 { 01156 Q_D(const KCalendarSystem); 01157 01158 return (isValid(year, 1, 1) && dayOfYear > 0 && dayOfYear <= d->daysInYear(year)); 01159 } 01160 01161 // NOT VIRTUAL - If override needed use shared-d 01162 bool KCalendarSystem::isValid(const QString &eraName, int yearInEra, int month, int day) const 01163 { 01164 Q_D(const KCalendarSystem); 01165 01166 KCalendarEra era = d->era(eraName, yearInEra); 01167 return (era.isValid() && isValid(era.year(yearInEra), month, day)); 01168 } 01169 01170 // NOT VIRTUAL - If override needed use shared-d 01171 bool KCalendarSystem::isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const 01172 { 01173 Q_D(const KCalendarSystem); 01174 01175 //Tests Year value in standard YMD isValid() 01176 if (!isValid(year, 1, 1)) { 01177 return false; 01178 } 01179 01180 //Test Week Number falls in valid range for this year 01181 int weeksInThisYear = weeksInYear(year); 01182 if (isoWeekNumber < 1 || isoWeekNumber > weeksInThisYear) { 01183 return false; 01184 } 01185 01186 //Test Day of Week Number falls in valid range 01187 if (dayOfIsoWeek < 1 || dayOfIsoWeek > d->daysInWeek()) { 01188 return false; 01189 } 01190 01191 //If not in earliest or latest years then all OK 01192 //Otherwise need to check don't fall into previous or next year that would be invalid 01193 if (year == d->earliestValidYear() && isoWeekNumber == 1) { 01194 //If firstDayOfYear falls on or before Thursday then firstDayOfYear falls in week 1 this 01195 //year and if wanted dayOfIsoWeek falls before firstDayOfYear then falls in previous year 01196 //and so in invalid year 01197 int dowFirstDay = dayOfWeek(d->firstDayOfYear(year)); 01198 if (dowFirstDay <= 4 && dayOfIsoWeek < dowFirstDay) { 01199 return false; 01200 } 01201 } else if (year == d->latestValidYear() && isoWeekNumber == weeksInThisYear) { 01202 //If lastDayOfYear falls on or after Thursday then lastDayOfYear falls in last week this 01203 //year and if wanted dayOfIsoWeek falls after lastDayOfYear then falls in next year 01204 //and so in invalid year 01205 int dowLastDay = dayOfWeek(d->lastDayOfYear(year)); 01206 if (dowLastDay >= 4 && dayOfIsoWeek > dowLastDay) { 01207 return false; 01208 } 01209 } 01210 01211 return true; 01212 } 01213 01214 bool KCalendarSystem::isValid(const QDate &date) const 01215 { 01216 if (date.isNull() || date < earliestValidDate() || date > latestValidDate()) { 01217 return false; 01218 } 01219 return true; 01220 } 01221 01222 bool KCalendarSystem::setDate(QDate &date, int year, int month, int day) const 01223 { 01224 Q_D(const KCalendarSystem); 01225 01226 date = d->invalidDate(); 01227 01228 if (isValid(year, month, day)) { 01229 int jd; 01230 dateToJulianDay(year, month, day, jd); 01231 QDate calcDate = QDate::fromJulianDay(jd); 01232 01233 if (isValid(calcDate)) { 01234 date = calcDate; 01235 return true; 01236 } 01237 } 01238 01239 return false; 01240 } 01241 01242 // NOT VIRTUAL - If override needed use shared-d 01243 bool KCalendarSystem::setDate(QDate &date, int year, int dayOfYear) const 01244 { 01245 Q_D(const KCalendarSystem); 01246 01247 date = d->invalidDate(); 01248 01249 if (isValid(year, dayOfYear)) { 01250 int jd; 01251 dateToJulianDay(year, 1, 1, jd); 01252 QDate calcDate = QDate::fromJulianDay(jd + dayOfYear - 1); 01253 if (isValid(calcDate)) { 01254 date = calcDate; 01255 return true; 01256 } 01257 } 01258 01259 return false; 01260 } 01261 01262 // NOT VIRTUAL - If override needed use shared-d 01263 bool KCalendarSystem::setDate(QDate &date, QString eraName, int yearInEra, int month, int day) const 01264 { 01265 Q_D(const KCalendarSystem); 01266 01267 KCalendarEra era = d->era(eraName, yearInEra); 01268 return (era.isValid() && setDate(date, era.year(yearInEra), month, day)); 01269 } 01270 01271 // NOT VIRTUAL - If override needed use shared-d 01272 bool KCalendarSystem::setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const 01273 { 01274 Q_D(const KCalendarSystem); 01275 01276 date = d->invalidDate(); 01277 01278 if (isValidIsoWeekDate(year, isoWeekNumber, dayOfIsoWeek)) { 01279 01280 QDate calcDate = d->firstDayOfYear(year); 01281 int dowFirstDayOfYear = dayOfWeek(calcDate); 01282 01283 int daysToAdd = (d->daysInWeek() * (isoWeekNumber - 1)) + dayOfIsoWeek; 01284 01285 if (dowFirstDayOfYear <= 4) { 01286 calcDate = calcDate.addDays(daysToAdd - dowFirstDayOfYear); 01287 } else { 01288 calcDate = calcDate.addDays(daysInWeek(calcDate) + daysToAdd - dowFirstDayOfYear); 01289 } 01290 01291 if (isValid(calcDate)) { 01292 date = calcDate; 01293 return true; 01294 } 01295 } 01296 01297 return false; 01298 } 01299 01300 // Deprecated 01301 bool KCalendarSystem::setYMD(QDate &date, int year, int month, int day) const 01302 { 01303 return setDate(date, year, month, day); 01304 } 01305 01306 // NOT VIRTUAL - If override needed use shared-d 01307 void KCalendarSystem::getDate(const QDate date, int *year, int *month, int *day) const 01308 { 01309 int y, m, d; 01310 01311 if (isValid(date)) { 01312 julianDayToDate(date.toJulianDay(), y, m, d); 01313 } else { 01314 y = 0; // How do you denote invalid year when we support -ve years? 01315 m = 0; 01316 d = 0; 01317 } 01318 01319 if (year) { 01320 *year = y; 01321 } 01322 if (month) { 01323 *month = m; 01324 } 01325 if (day) { 01326 *day = d; 01327 } 01328 01329 } 01330 01331 int KCalendarSystem::year(const QDate &date) const 01332 { 01333 if (isValid(date)) { 01334 int year, month, day; 01335 01336 julianDayToDate(date.toJulianDay(), year, month, day); 01337 01338 return year; 01339 } 01340 01341 return 0; // How do you denote invalid year when we support -ve years? 01342 } 01343 01344 int KCalendarSystem::month(const QDate &date) const 01345 { 01346 if (isValid(date)) { 01347 int year, month, day; 01348 01349 julianDayToDate(date.toJulianDay(), year, month, day); 01350 01351 return month; 01352 } 01353 01354 return 0; 01355 } 01356 01357 int KCalendarSystem::day(const QDate &date) const 01358 { 01359 if (isValid(date)) { 01360 int year, month, day; 01361 01362 julianDayToDate(date.toJulianDay(), year, month, day); 01363 01364 return day; 01365 } 01366 01367 return 0; 01368 } 01369 01370 // NOT VIRTUAL - If override needed use shared-d 01371 QString KCalendarSystem::eraName(const QDate &date, StringFormat format) const 01372 { 01373 Q_D(const KCalendarSystem); 01374 01375 if (isValid(date)) { 01376 if (format == LongFormat) { 01377 return d->era(date).name(KLocale::LongName); 01378 } else { 01379 return d->era(date).name(KLocale::ShortName); 01380 } 01381 } 01382 01383 return QString(); 01384 } 01385 01386 // NOT VIRTUAL - If override needed use shared-d 01387 QString KCalendarSystem::eraYear(const QDate &date, StringFormat format) const 01388 { 01389 Q_UNUSED(format) 01390 Q_D(const KCalendarSystem); 01391 01392 if (isValid(date)) { 01393 return formatDate(date, d->era(date).format()); 01394 } 01395 01396 return QString(); 01397 } 01398 01399 // NOT VIRTUAL - If override needed use shared-d 01400 int KCalendarSystem::yearInEra(const QDate &date) const 01401 { 01402 Q_D(const KCalendarSystem); 01403 01404 if (isValid(date)) { 01405 return d->era(date).yearInEra(year(date)); 01406 } 01407 01408 return -1; 01409 } 01410 01411 // NOT VIRTUAL - If override needed use shared-d 01412 QList<KCalendarEra> *KCalendarSystem::eraList() const 01413 { 01414 Q_D(const KCalendarSystem); 01415 01416 return d->eraList(); 01417 } 01418 01419 // NOT VIRTUAL - If override needed use shared-d 01420 KCalendarEra KCalendarSystem::era(const QDate &eraDate) const 01421 { 01422 Q_D(const KCalendarSystem); 01423 01424 return d->era(eraDate); 01425 } 01426 01427 // NOT VIRTUAL - If override needed use shared-d 01428 KCalendarEra KCalendarSystem::era(const QString &eraName, int yearInEra) const 01429 { 01430 Q_D(const KCalendarSystem); 01431 01432 return d->era(eraName, yearInEra); 01433 } 01434 01435 QDate KCalendarSystem::addYears(const QDate &date, int numYears) const 01436 { 01437 Q_D(const KCalendarSystem); 01438 01439 if (isValid(date)) { 01440 01441 int originalYear, originalMonth, originalDay; 01442 julianDayToDate(date.toJulianDay(), originalYear, originalMonth, originalDay); 01443 01444 int newYear = d->addYears(originalYear, numYears); 01445 int newMonth = originalMonth; 01446 int newDay = originalDay; 01447 01448 //Adjust day number if new month has fewer days than old month 01449 int daysInNewMonth = d->daysInMonth(newYear, newMonth); 01450 if (daysInNewMonth < originalDay) { 01451 newDay = daysInNewMonth; 01452 } 01453 01454 QDate newDate; 01455 setDate(newDate, newYear, newMonth, newDay); 01456 return newDate; 01457 01458 } 01459 01460 return d->invalidDate(); 01461 } 01462 01463 QDate KCalendarSystem::addMonths(const QDate &date, int numMonths) const 01464 { 01465 Q_D(const KCalendarSystem); 01466 01467 if (isValid(date)) { 01468 01469 int originalYear, originalMonth, originalDay; 01470 julianDayToDate(date.toJulianDay(), originalYear, originalMonth, originalDay); 01471 01472 int monthsInOriginalYear = d->monthsInYear(originalYear); 01473 01474 int newYear = d->addYears(originalYear, (originalMonth + numMonths) / monthsInOriginalYear); 01475 int newMonth = (originalMonth + numMonths) % monthsInOriginalYear; 01476 int newDay = originalDay; 01477 01478 if (newMonth == 0) { 01479 newYear = d->addYears(newYear, - 1); 01480 newMonth = monthsInOriginalYear; 01481 } 01482 if (newMonth < 0) { 01483 newYear = d->addYears(newYear, - 1); 01484 newMonth = newMonth + monthsInOriginalYear; 01485 } 01486 01487 //Adjust day number if new month has fewer days than old month 01488 int daysInNewMonth = d->daysInMonth(newYear, newMonth); 01489 if (daysInNewMonth < originalDay) { 01490 newDay = daysInNewMonth; 01491 } 01492 01493 QDate newDate; 01494 setDate(newDate, newYear, newMonth, newDay); 01495 return newDate; 01496 01497 } 01498 01499 return d->invalidDate(); 01500 } 01501 01502 QDate KCalendarSystem::addDays(const QDate &date, int numDays) const 01503 { 01504 Q_D(const KCalendarSystem); 01505 01506 // QDate only holds a uint and has no boundary checking in addDays(), so we need to check 01507 if (isValid(date) && (long) date.toJulianDay() + (long) numDays > 0) { 01508 // QDate adds straight to jd 01509 QDate temp = date.addDays(numDays); 01510 if (isValid(temp)) { 01511 return temp; 01512 } 01513 } 01514 01515 return d->invalidDate(); 01516 } 01517 01518 // NOT VIRTUAL - Uses shared-d instead 01519 void KCalendarSystem::dateDifference(const QDate &fromDate, const QDate &toDate, 01520 int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const 01521 { 01522 Q_D(const KCalendarSystem); 01523 01524 if (isValid(fromDate) && isValid(toDate)) { 01525 d->dateDifference(fromDate, toDate, yearsDiff, monthsDiff, daysDiff, direction); 01526 } 01527 } 01528 01529 // NOT VIRTUAL - Uses shared-d instead 01530 int KCalendarSystem::yearsDifference(const QDate &fromDate, const QDate &toDate) const 01531 { 01532 Q_D(const KCalendarSystem); 01533 01534 if (isValid(fromDate) && isValid(toDate)) { 01535 return d->yearsDifference(fromDate, toDate); 01536 } 01537 01538 return 0; 01539 } 01540 01541 // NOT VIRTUAL - Uses shared-d instead 01542 int KCalendarSystem::monthsDifference(const QDate &fromDate, const QDate &toDate) const 01543 { 01544 Q_D(const KCalendarSystem); 01545 01546 if (isValid(fromDate) && isValid(toDate)) { 01547 return d->monthsDifference(fromDate, toDate); 01548 } 01549 01550 return 0; 01551 } 01552 01553 // NOT VIRTUAL - Uses shared-d instead 01554 int KCalendarSystem::daysDifference(const QDate &fromDate, const QDate &toDate) const 01555 { 01556 if (isValid(fromDate) && isValid(toDate)) { 01557 return toDate.toJulianDay() - fromDate.toJulianDay(); 01558 } 01559 01560 return 0; 01561 } 01562 01563 int KCalendarSystem::monthsInYear(const QDate &date) const 01564 { 01565 Q_D(const KCalendarSystem); 01566 01567 if (isValid(date)) { 01568 return d->monthsInYear(year(date)); 01569 } 01570 01571 return -1; 01572 } 01573 01574 // NOT VIRTUAL - Uses shared-d instead 01575 int KCalendarSystem::monthsInYear(int year) const 01576 { 01577 Q_D(const KCalendarSystem); 01578 01579 if (isValid(year, 1, 1)) { 01580 return d->monthsInYear(year); 01581 } 01582 01583 return -1; 01584 } 01585 01586 int KCalendarSystem::weeksInYear(const QDate &date) const 01587 { 01588 return weeksInYear(date, KLocale::DefaultWeekNumber); 01589 } 01590 01591 int KCalendarSystem::weeksInYear(int year) const 01592 { 01593 return weeksInYear(year, KLocale::DefaultWeekNumber); 01594 } 01595 01596 // NOT VIRTUAL - Uses shared-d instead 01597 int KCalendarSystem::weeksInYear(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem) const 01598 { 01599 Q_D(const KCalendarSystem); 01600 01601 if (isValid(date)) { 01602 return d->weeksInYear(year(date), weekNumberSystem); 01603 } 01604 01605 return -1; 01606 } 01607 01608 // NOT VIRTUAL - Uses shared-d instead 01609 int KCalendarSystem::weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem) const 01610 { 01611 Q_D(const KCalendarSystem); 01612 01613 if (isValid(year, 1, 1)) { 01614 return d->weeksInYear(year, weekNumberSystem); 01615 } 01616 01617 return -1; 01618 } 01619 01620 int KCalendarSystem::daysInYear(const QDate &date) const 01621 { 01622 Q_D(const KCalendarSystem); 01623 01624 if (isValid(date)) { 01625 return d->daysInYear(year(date)); 01626 } 01627 01628 return -1; 01629 } 01630 01631 // NOT VIRTUAL - Uses shared-d instead 01632 int KCalendarSystem::daysInYear(int year) const 01633 { 01634 Q_D(const KCalendarSystem); 01635 01636 if (isValid(year, 1, 1)) { 01637 return d->daysInYear(year); 01638 } 01639 01640 return -1; 01641 } 01642 01643 int KCalendarSystem::daysInMonth(const QDate &date) const 01644 { 01645 Q_D(const KCalendarSystem); 01646 01647 if (isValid(date)) { 01648 int year, month; 01649 getDate(date, &year, &month, 0); 01650 return d->daysInMonth(year, month); 01651 } 01652 01653 return -1; 01654 } 01655 01656 // NOT VIRTUAL - Uses shared-d instead 01657 int KCalendarSystem::daysInMonth(int year, int month) const 01658 { 01659 Q_D(const KCalendarSystem); 01660 01661 if (isValid(year, 1, 1)) { 01662 return d->daysInMonth(year, month); 01663 } 01664 01665 return -1; 01666 } 01667 01668 int KCalendarSystem::daysInWeek(const QDate &date) const 01669 { 01670 Q_UNUSED(date) 01671 Q_D(const KCalendarSystem); 01672 return d->daysInWeek(); 01673 } 01674 01675 int KCalendarSystem::dayOfYear(const QDate &date) const 01676 { 01677 Q_D(const KCalendarSystem); 01678 01679 if (isValid(date)) { 01680 return d->dayOfYear(date); 01681 } 01682 01683 return -1; 01684 } 01685 01686 int KCalendarSystem::dayOfWeek(const QDate &date) const 01687 { 01688 Q_D(const KCalendarSystem); 01689 01690 if (isValid(date)) { 01691 return d->dayOfWeek(date); 01692 } 01693 01694 return -1; 01695 } 01696 01697 int KCalendarSystem::weekNumber(const QDate &date, int *yearNum) const 01698 { 01699 return week(date, KLocale::IsoWeekNumber, yearNum); 01700 } 01701 01702 // NOT VIRTUAL - Uses shared-d instead 01703 int KCalendarSystem::week(const QDate &date, int *yearNum) const 01704 { 01705 return week(date, KLocale::DefaultWeekNumber, yearNum); 01706 } 01707 01708 // NOT VIRTUAL - Uses shared-d instead 01709 int KCalendarSystem::week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const 01710 { 01711 Q_D(const KCalendarSystem); 01712 01713 if (isValid(date)) { 01714 return d->week(date, weekNumberSystem, yearNum); 01715 } 01716 01717 return -1; 01718 } 01719 01720 bool KCalendarSystem::isLeapYear(int year) const 01721 { 01722 Q_D(const KCalendarSystem); 01723 01724 if (isValid(year, 1, 1)) { 01725 return d->isLeapYear(year); 01726 } 01727 01728 return false; 01729 } 01730 01731 bool KCalendarSystem::isLeapYear(const QDate &date) const 01732 { 01733 Q_D(const KCalendarSystem); 01734 01735 if (isValid(date)) { 01736 return d->isLeapYear(year(date)); 01737 } 01738 01739 return false; 01740 } 01741 01742 // NOT VIRTUAL - If override needed use shared-d 01743 QDate KCalendarSystem::firstDayOfYear(int year) const 01744 { 01745 Q_D(const KCalendarSystem); 01746 01747 if (isValid(year, 1, 1)) { 01748 return d->firstDayOfYear(year); 01749 } 01750 01751 return QDate(); 01752 } 01753 01754 // NOT VIRTUAL - If override needed use shared-d 01755 QDate KCalendarSystem::lastDayOfYear(int year) const 01756 { 01757 Q_D(const KCalendarSystem); 01758 01759 if (isValid(year, 1, 1)) { 01760 return d->lastDayOfYear(year); 01761 } 01762 01763 return QDate(); 01764 } 01765 01766 // NOT VIRTUAL - If override needed use shared-d 01767 QDate KCalendarSystem::firstDayOfYear(const QDate &date) const 01768 { 01769 Q_D(const KCalendarSystem); 01770 01771 if (isValid(date)) { 01772 return d->firstDayOfYear(year(date)); 01773 } 01774 01775 return QDate(); 01776 } 01777 01778 // NOT VIRTUAL - If override needed use shared-d 01779 QDate KCalendarSystem::lastDayOfYear(const QDate &date) const 01780 { 01781 Q_D(const KCalendarSystem); 01782 01783 if (isValid(date)) { 01784 return d->lastDayOfYear(year(date)); 01785 } 01786 01787 return QDate(); 01788 } 01789 01790 // NOT VIRTUAL - If override needed use shared-d 01791 QDate KCalendarSystem::firstDayOfMonth(int year, int month) const 01792 { 01793 Q_D(const KCalendarSystem); 01794 01795 if (isValid(year, month, 1)) { 01796 return d->firstDayOfMonth(year, month); 01797 } 01798 01799 return QDate(); 01800 } 01801 01802 // NOT VIRTUAL - If override needed use shared-d 01803 QDate KCalendarSystem::lastDayOfMonth(int year, int month) const 01804 { 01805 Q_D(const KCalendarSystem); 01806 01807 if (isValid(year, month, 1)) { 01808 return d->lastDayOfMonth(year, month); 01809 } 01810 01811 return QDate(); 01812 } 01813 01814 // NOT VIRTUAL - If override needed use shared-d 01815 QDate KCalendarSystem::firstDayOfMonth(const QDate &date) const 01816 { 01817 Q_D(const KCalendarSystem); 01818 01819 if (isValid(date)) { 01820 int year, month; 01821 getDate(date, &year, &month, 0); 01822 return d->firstDayOfMonth(year, month); 01823 } 01824 01825 return QDate(); 01826 } 01827 01828 // NOT VIRTUAL - If override needed use shared-d 01829 QDate KCalendarSystem::lastDayOfMonth(const QDate &date) const 01830 { 01831 Q_D(const KCalendarSystem); 01832 01833 if (isValid(date)) { 01834 int year, month; 01835 getDate(date, &year, &month, 0); 01836 return d->lastDayOfMonth(year, month); 01837 } 01838 01839 return QDate(); 01840 } 01841 01842 QString KCalendarSystem::monthName(int month, int year, KCalendarSystem::MonthNameFormat format) const 01843 { 01844 Q_D(const KCalendarSystem); 01845 01846 if (!isValid(year, month, 1)) { 01847 return QString(); 01848 } 01849 01850 if (format == KCalendarSystem::NarrowName) { 01851 return d->monthName(month, year, KLocale::NarrowName, false); 01852 } 01853 01854 if (format == KCalendarSystem::ShortNamePossessive) { 01855 return d->monthName(month, year, KLocale::ShortName, true); 01856 } 01857 01858 if (format == KCalendarSystem::ShortName) { 01859 return d->monthName(month, year, KLocale::ShortName, false); 01860 } 01861 01862 if (format == KCalendarSystem::LongNamePossessive) { 01863 return d->monthName(month, year, KLocale::LongName, true); 01864 } 01865 01866 // KCalendarSystem::LongName or any other 01867 return d->monthName(month, year, KLocale::LongName, false); 01868 } 01869 01870 QString KCalendarSystem::monthName(const QDate &date, MonthNameFormat format) const 01871 { 01872 if (isValid(date)) { 01873 int year, month; 01874 getDate(date, &year, &month, 0); 01875 return monthName(month, year, format); 01876 } 01877 01878 return QString(); 01879 } 01880 01881 QString KCalendarSystem::weekDayName(int weekDay, KCalendarSystem::WeekDayNameFormat format) const 01882 { 01883 Q_D(const KCalendarSystem); 01884 01885 if (weekDay < 1 || weekDay > d->daysInWeek()) { 01886 return QString(); 01887 } 01888 01889 if (format == KCalendarSystem::NarrowDayName) { 01890 return d->weekDayName(weekDay, KLocale::NarrowName); 01891 } 01892 01893 if (format == KCalendarSystem::ShortDayName) { 01894 return d->weekDayName(weekDay, KLocale::ShortName); 01895 } 01896 01897 if (format == KCalendarSystem::ShortDayName) { 01898 return d->weekDayName(weekDay, KLocale::ShortName); 01899 } 01900 01901 return d->weekDayName(weekDay, KLocale::LongName); 01902 } 01903 01904 QString KCalendarSystem::weekDayName(const QDate &date, WeekDayNameFormat format) const 01905 { 01906 if (isValid(date)) { 01907 return weekDayName(dayOfWeek(date), format); 01908 } 01909 01910 return QString(); 01911 } 01912 01913 QString KCalendarSystem::yearString(const QDate &date, StringFormat format) const 01914 { 01915 if (format == ShortFormat) { 01916 return formatDate(date, KLocale::Year, KLocale::ShortNumber); 01917 } else { 01918 return formatDate(date, KLocale::Year, KLocale::LongNumber); 01919 } 01920 } 01921 01922 QString KCalendarSystem::monthString(const QDate &date, StringFormat format) const 01923 { 01924 if (format == ShortFormat) { 01925 return formatDate(date, KLocale::Month, KLocale::ShortNumber); 01926 } else { 01927 return formatDate(date, KLocale::Month, KLocale::LongNumber); 01928 } 01929 } 01930 01931 QString KCalendarSystem::dayString(const QDate &date, StringFormat format) const 01932 { 01933 if (format == ShortFormat) { 01934 return formatDate(date, KLocale::Day, KLocale::ShortNumber); 01935 } else { 01936 return formatDate(date, KLocale::Day, KLocale::LongNumber); 01937 } 01938 } 01939 01940 // NOT VIRTUAL - If override needed use shared-d 01941 QString KCalendarSystem::yearInEraString(const QDate &date, StringFormat format) const 01942 { 01943 if (format == ShortFormat) { 01944 return formatDate(date, KLocale::YearInEra, KLocale::ShortNumber); 01945 } else { 01946 return formatDate(date, KLocale::YearInEra, KLocale::LongNumber); 01947 } 01948 } 01949 01950 // NOT VIRTUAL - If override needed use shared-d 01951 QString KCalendarSystem::dayOfYearString(const QDate &date, StringFormat format) const 01952 { 01953 if (format == ShortFormat) { 01954 return formatDate(date, KLocale::DayOfYear, KLocale::ShortNumber); 01955 } else { 01956 return formatDate(date, KLocale::DayOfYear, KLocale::LongNumber); 01957 } 01958 } 01959 01960 // NOT VIRTUAL - If override needed use shared-d 01961 QString KCalendarSystem::dayOfWeekString(const QDate &date) const 01962 { 01963 return formatDate(date, KLocale::DayOfWeek, KLocale::ShortNumber); 01964 } 01965 01966 // NOT VIRTUAL - If override needed use shared-d 01967 QString KCalendarSystem::weekNumberString(const QDate &date, StringFormat format) const 01968 { 01969 if (format == ShortFormat) { 01970 return formatDate(date, KLocale::Week, KLocale::ShortNumber); 01971 } else { 01972 return formatDate(date, KLocale::Week, KLocale::LongNumber); 01973 } 01974 } 01975 01976 // NOT VIRTUAL - If override needed use shared-d 01977 QString KCalendarSystem::monthsInYearString(const QDate &date, StringFormat format) const 01978 { 01979 if (format == ShortFormat) { 01980 return formatDate(date, KLocale::MonthsInYear, KLocale::ShortNumber); 01981 } else { 01982 return formatDate(date, KLocale::MonthsInYear, KLocale::LongNumber); 01983 } 01984 } 01985 01986 // NOT VIRTUAL - If override needed use shared-d 01987 QString KCalendarSystem::weeksInYearString(const QDate &date, StringFormat format) const 01988 { 01989 if (format == ShortFormat) { 01990 return formatDate(date, KLocale::WeeksInYear, KLocale::ShortNumber); 01991 } else { 01992 return formatDate(date, KLocale::WeeksInYear, KLocale::LongNumber); 01993 } 01994 } 01995 01996 // NOT VIRTUAL - If override needed use shared-d 01997 QString KCalendarSystem::daysInYearString(const QDate &date, StringFormat format) const 01998 { 01999 if (format == ShortFormat) { 02000 return formatDate(date, KLocale::DaysInYear, KLocale::ShortNumber); 02001 } else { 02002 return formatDate(date, KLocale::DaysInYear, KLocale::LongNumber); 02003 } 02004 } 02005 02006 // NOT VIRTUAL - If override needed use shared-d 02007 QString KCalendarSystem::daysInMonthString(const QDate &date, StringFormat format) const 02008 { 02009 if (format == ShortFormat) { 02010 return formatDate(date, KLocale::DaysInMonth, KLocale::ShortNumber); 02011 } else { 02012 return formatDate(date, KLocale::DaysInMonth, KLocale::LongNumber); 02013 } 02014 } 02015 02016 // NOT VIRTUAL - If override needed use shared-d 02017 QString KCalendarSystem::daysInWeekString(const QDate &date) const 02018 { 02019 return formatDate(date, KLocale::DaysInWeek, KLocale::ShortNumber); 02020 } 02021 02022 int KCalendarSystem::yearStringToInteger(const QString &yearString, int &readLength) const 02023 { 02024 Q_D(const KCalendarSystem); 02025 02026 QString minus = i18nc("Negative symbol as used for year numbers, e.g. -5 = 5 BC", "-"); 02027 if (yearString.startsWith(minus)) { 02028 int value = d->integerFromString(yearString.mid(minus.length()), 4, readLength); 02029 if (readLength > 0 && value >= 0) { 02030 readLength = readLength + minus.length(); 02031 return value * -1; 02032 } else { 02033 return value; 02034 } 02035 } 02036 02037 return d->integerFromString(yearString, 4, readLength); 02038 } 02039 02040 int KCalendarSystem::monthStringToInteger(const QString &monthString, int &readLength) const 02041 { 02042 Q_D(const KCalendarSystem); 02043 return d->integerFromString(monthString, 2, readLength); 02044 } 02045 02046 int KCalendarSystem::dayStringToInteger(const QString &dayString, int &readLength) const 02047 { 02048 Q_D(const KCalendarSystem); 02049 return d->integerFromString(dayString, 2, readLength); 02050 } 02051 02052 QString KCalendarSystem::formatDate(const QDate &fromDate, KLocale::DateFormat toFormat) const 02053 { 02054 if (!fromDate.isValid()) { 02055 return QString(); 02056 } 02057 02058 if (toFormat == KLocale::FancyShortDate || toFormat == KLocale::FancyLongDate) { 02059 QDate now = KDateTime::currentLocalDate(); 02060 int daysToNow = fromDate.daysTo(now); 02061 switch (daysToNow) { 02062 case 0: 02063 return i18n("Today"); 02064 case 1: 02065 return i18n("Yesterday"); 02066 case 2: 02067 case 3: 02068 case 4: 02069 case 5: 02070 case 6: 02071 return weekDayName(fromDate); 02072 default: 02073 break; 02074 } 02075 } 02076 02077 switch (toFormat) { 02078 case KLocale::LongDate: 02079 case KLocale::FancyLongDate: 02080 return formatDate(fromDate, locale()->dateFormat()); 02081 case KLocale::IsoDate: 02082 return formatDate(fromDate, QLatin1String("%Y-%m-%d")); 02083 case KLocale::IsoWeekDate: 02084 return formatDate(fromDate, QLatin1String("%Y-W%V-%u")); 02085 case KLocale::IsoOrdinalDate: 02086 return formatDate(fromDate, QLatin1String("%Y-%j")); 02087 case KLocale::ShortDate: 02088 case KLocale::FancyShortDate: 02089 default: 02090 return formatDate(fromDate, locale()->dateFormatShort()); 02091 } 02092 02093 } 02094 02095 // NOT VIRTUAL - If override needed use shared-d 02096 QString KCalendarSystem::formatDate(const QDate &fromDate, const QString &toFormat, 02097 KLocale::DateTimeFormatStandard standard) const 02098 { 02099 return formatDate(fromDate, toFormat, locale()->dateTimeDigitSet(), standard); 02100 } 02101 02102 // NOT VIRTUAL - If override needed use shared-d 02103 QString KCalendarSystem::formatDate(const QDate &fromDate, const QString &toFormat, KLocale::DigitSet digitSet, 02104 KLocale::DateTimeFormatStandard formatStandard) const 02105 { 02106 if (!isValid(fromDate) || toFormat.isEmpty()) { 02107 return QString(); 02108 } 02109 02110 KDateTimeFormatter formatter; 02111 return formatter.formatDate(fromDate, toFormat, this, locale(), digitSet, formatStandard); 02112 } 02113 02114 // NOT VIRTUAL - If override needed use shared-d 02115 QString KCalendarSystem::formatDate(const QDate &date, KLocale::DateTimeComponent component, 02116 KLocale::DateTimeComponentFormat format, 02117 KLocale::WeekNumberSystem weekNumberSystem) const 02118 { 02119 Q_D(const KCalendarSystem); 02120 02121 switch (component) { 02122 case KLocale::Year: 02123 case KLocale::YearName: 02124 switch (format) { 02125 case KLocale::ShortName: 02126 case KLocale::NarrowName: 02127 case KLocale::ShortNumber: 02128 return formatDate(date, QLatin1String("%y")); 02129 case KLocale::LongNumber: 02130 case KLocale::LongName: 02131 case KLocale::DefaultComponentFormat: 02132 default: 02133 return formatDate(date, QLatin1String("%Y")); 02134 } 02135 case KLocale::Month: 02136 switch (format) { 02137 case KLocale::LongName: 02138 return monthName(date, KCalendarSystem::LongName); 02139 case KLocale::ShortName: 02140 return monthName(date, KCalendarSystem::ShortName); 02141 case KLocale::NarrowName: 02142 return monthName(date, KCalendarSystem::NarrowName); 02143 case KLocale::LongNumber: 02144 return formatDate(date, QLatin1String("%m")); 02145 case KLocale::ShortNumber: 02146 case KLocale::DefaultComponentFormat: 02147 default: 02148 return formatDate(date, QLatin1String("%n")); 02149 } 02150 case KLocale::MonthName: 02151 switch (format) { 02152 case KLocale::NarrowName: 02153 return monthName(date, KCalendarSystem::NarrowName); 02154 case KLocale::ShortName: 02155 case KLocale::ShortNumber: 02156 return monthName(date, KCalendarSystem::ShortName); 02157 case KLocale::LongName: 02158 case KLocale::LongNumber: 02159 case KLocale::DefaultComponentFormat: 02160 default: 02161 return monthName(date, KCalendarSystem::LongName); 02162 } 02163 case KLocale::Day: 02164 case KLocale::DayName: 02165 switch (format) { 02166 case KLocale::LongNumber: 02167 case KLocale::LongName: 02168 return formatDate(date, QLatin1String("%d")); 02169 case KLocale::ShortName: 02170 case KLocale::NarrowName: 02171 case KLocale::ShortNumber: 02172 case KLocale::DefaultComponentFormat: 02173 default: 02174 return formatDate(date, QLatin1String("%e")); 02175 } 02176 case KLocale::JulianDay: 02177 return d->stringFromInteger(date.toJulianDay(), 0); 02178 case KLocale::EraName: 02179 switch (format) { 02180 case KLocale::LongNumber: 02181 case KLocale::LongName: 02182 return eraName(date, KCalendarSystem::LongFormat); 02183 case KLocale::ShortName: 02184 case KLocale::NarrowName: 02185 case KLocale::ShortNumber: 02186 case KLocale::DefaultComponentFormat: 02187 default: 02188 return eraName(date, KCalendarSystem::ShortFormat); 02189 } 02190 case KLocale::EraYear: 02191 switch (format) { 02192 case KLocale::LongNumber: 02193 case KLocale::LongName: 02194 return eraYear(date, KCalendarSystem::LongFormat); 02195 case KLocale::ShortName: 02196 case KLocale::NarrowName: 02197 case KLocale::ShortNumber: 02198 case KLocale::DefaultComponentFormat: 02199 default: 02200 return eraYear(date, KCalendarSystem::ShortFormat); 02201 } 02202 case KLocale::YearInEra: 02203 switch (format) { 02204 case KLocale::LongNumber: 02205 case KLocale::LongName: 02206 return formatDate(date, QLatin1String("%4Ey")); 02207 case KLocale::ShortName: 02208 case KLocale::NarrowName: 02209 case KLocale::ShortNumber: 02210 case KLocale::DefaultComponentFormat: 02211 default: 02212 return formatDate(date, QLatin1String("%Ey")); 02213 } 02214 case KLocale::DayOfYear: 02215 case KLocale::DayOfYearName: 02216 switch (format) { 02217 case KLocale::LongNumber: 02218 case KLocale::LongName: 02219 return formatDate(date, QLatin1String("%j")); 02220 case KLocale::ShortName: 02221 case KLocale::NarrowName: 02222 case KLocale::ShortNumber: 02223 case KLocale::DefaultComponentFormat: 02224 default: 02225 return formatDate(date, QLatin1String("%-j")); 02226 } 02227 case KLocale::DayOfWeek: 02228 switch (format) { 02229 case KLocale::LongName: 02230 return weekDayName(date, KCalendarSystem::LongDayName); 02231 case KLocale::ShortName: 02232 return weekDayName(date, KCalendarSystem::ShortDayName); 02233 case KLocale::NarrowName: 02234 return weekDayName(date, KCalendarSystem::NarrowDayName); 02235 case KLocale::LongNumber: 02236 case KLocale::ShortNumber: 02237 case KLocale::DefaultComponentFormat: 02238 default: 02239 return formatDate(date, QLatin1String("%-u")); 02240 } 02241 case KLocale::DayOfWeekName: 02242 switch (format) { 02243 case KLocale::NarrowName: 02244 return weekDayName(date, KCalendarSystem::NarrowDayName); 02245 case KLocale::ShortName: 02246 case KLocale::ShortNumber: 02247 return weekDayName(date, KCalendarSystem::ShortDayName); 02248 case KLocale::LongName: 02249 case KLocale::LongNumber: 02250 case KLocale::DefaultComponentFormat: 02251 default: 02252 return weekDayName(date, KCalendarSystem::LongDayName); 02253 } 02254 case KLocale::Week: 02255 switch (format) { 02256 case KLocale::LongNumber: 02257 case KLocale::LongName: 02258 return d->stringFromInteger(week(date, weekNumberSystem, 0), 2, QLatin1Char('0')); 02259 case KLocale::ShortName: 02260 case KLocale::NarrowName: 02261 case KLocale::ShortNumber: 02262 case KLocale::DefaultComponentFormat: 02263 default: 02264 return d->stringFromInteger(week(date, weekNumberSystem, 0), 0, QLatin1Char('0')); 02265 } 02266 case KLocale::WeekYear: { 02267 int weekYear; 02268 QDate yearDate; 02269 week(date, weekNumberSystem, &weekYear); 02270 setDate(yearDate, weekYear, 1, 1); 02271 return formatDate(yearDate, KLocale::Year, format); 02272 } 02273 case KLocale::MonthsInYear: 02274 switch (format) { 02275 case KLocale::LongNumber: 02276 case KLocale::LongName: 02277 return d->stringFromInteger(monthsInYear(date), 2, QLatin1Char('0')); 02278 case KLocale::ShortName: 02279 case KLocale::NarrowName: 02280 case KLocale::ShortNumber: 02281 case KLocale::DefaultComponentFormat: 02282 default: 02283 return d->stringFromInteger(monthsInYear(date), 0, QLatin1Char('0')); 02284 } 02285 case KLocale::WeeksInYear: 02286 switch (format) { 02287 case KLocale::LongNumber: 02288 case KLocale::LongName: 02289 return d->stringFromInteger(weeksInYear(date), 2, QLatin1Char('0')); 02290 case KLocale::ShortName: 02291 case KLocale::NarrowName: 02292 case KLocale::ShortNumber: 02293 case KLocale::DefaultComponentFormat: 02294 default: 02295 return d->stringFromInteger(weeksInYear(date), 0, QLatin1Char('0')); 02296 } 02297 case KLocale::DaysInYear: 02298 switch (format) { 02299 case KLocale::LongNumber: 02300 case KLocale::LongName: 02301 return d->stringFromInteger(daysInYear(date), 3, QLatin1Char('0')); 02302 case KLocale::ShortName: 02303 case KLocale::NarrowName: 02304 case KLocale::ShortNumber: 02305 case KLocale::DefaultComponentFormat: 02306 default: 02307 return d->stringFromInteger(daysInYear(date), 0, QLatin1Char('0')); 02308 } 02309 case KLocale::DaysInMonth: 02310 switch (format) { 02311 case KLocale::LongNumber: 02312 case KLocale::LongName: 02313 return d->stringFromInteger(daysInMonth(date), 2, QLatin1Char('0')); 02314 case KLocale::ShortName: 02315 case KLocale::NarrowName: 02316 case KLocale::ShortNumber: 02317 case KLocale::DefaultComponentFormat: 02318 default: 02319 return d->stringFromInteger(daysInMonth(date), 0, QLatin1Char('0')); 02320 } 02321 case KLocale::DaysInWeek: 02322 switch (format) { 02323 case KLocale::LongNumber: 02324 case KLocale::LongName: 02325 case KLocale::ShortName: 02326 case KLocale::NarrowName: 02327 case KLocale::ShortNumber: 02328 case KLocale::DefaultComponentFormat: 02329 default: 02330 return d->stringFromInteger(d->daysInWeek(), 0); 02331 } 02332 default: 02333 return QString(); 02334 } 02335 } 02336 02337 QDate KCalendarSystem::readDate(const QString &str, bool *ok) const 02338 { 02339 //Try each standard format in turn, start with the locale ones, 02340 //then the well defined standards 02341 QDate date = readDate(str, KLocale::ShortFormat, ok); 02342 if (!isValid(date)) { 02343 date = readDate(str, KLocale::NormalFormat, ok); 02344 if (!isValid(date)) { 02345 date = readDate(str, KLocale::IsoFormat, ok); 02346 if (!isValid(date)) { 02347 date = readDate(str, KLocale::IsoWeekFormat, ok); 02348 if (!isValid(date)) { 02349 date = readDate(str, KLocale::IsoOrdinalFormat, ok); 02350 } 02351 } 02352 } 02353 } 02354 02355 return date; 02356 } 02357 02358 QDate KCalendarSystem::readDate(const QString &str, KLocale::ReadDateFlags flags, bool *ok) const 02359 { 02360 Q_D(const KCalendarSystem); 02361 02362 if (flags & KLocale::ShortFormat) { 02363 return readDate(str, locale()->dateFormatShort(), ok); 02364 } else if (flags & KLocale::NormalFormat) { 02365 return readDate(str, locale()->dateFormat(), ok); 02366 } else if (flags & KLocale::IsoFormat) { 02367 return readDate(str, QLatin1String("%Y-%m-%d"), ok); 02368 } else if (flags & KLocale::IsoWeekFormat) { 02369 return readDate(str, QLatin1String("%Y-W%V-%u"), ok); 02370 } else if (flags & KLocale::IsoOrdinalFormat) { 02371 return readDate(str, QLatin1String("%Y-%j"), ok); 02372 } 02373 return d->invalidDate(); 02374 } 02375 02376 QDate KCalendarSystem::readDate(const QString &inputString, const QString &formatString, bool *ok) const 02377 { 02378 return readDate(inputString, formatString, ok, KLocale::KdeFormat); 02379 } 02380 02381 // NOT VIRTUAL - If override needed use shared-d 02382 QDate KCalendarSystem::readDate(const QString &inputString, const QString &formatString, bool *ok, 02383 KLocale::DateTimeFormatStandard formatStandard) const 02384 { 02385 KDateTimeParser parser; 02386 QDate resultDate = parser.parseDate(inputString, formatString, this, locale(), locale()->dateTimeDigitSet(), formatStandard); 02387 if (ok) { 02388 *ok = resultDate.isValid(); 02389 } 02390 return resultDate; 02391 } 02392 02393 // NOT VIRTUAL - If override needed use shared-d 02394 int KCalendarSystem::shortYearWindowStartYear() const 02395 { 02396 Q_D(const KCalendarSystem); 02397 02398 return d->shortYearWindowStartYear(); 02399 } 02400 02401 // NOT VIRTUAL - If override needed use shared-d 02402 int KCalendarSystem::applyShortYearWindow(int inputYear) const 02403 { 02404 Q_D(const KCalendarSystem); 02405 02406 return d->applyShortYearWindow(inputYear); 02407 } 02408 02409 int KCalendarSystem::weekStartDay() const 02410 { 02411 return locale()->weekStartDay(); 02412 } 02413 02414 // Dummy version using Gregorian as an example 02415 // This method MUST be re-implemented in any new Calendar System 02416 // The implementation MUST NOT do validity checking on date ranges, all calls to this function MUST 02417 // instead be wrapped in validity checks, as sometimes we want this to work outside the public valid 02418 // range, i.e. to allow us to internally set dates of 1/1/10000 which are not publically valid but 02419 // are required for internal maths 02420 bool KCalendarSystem::julianDayToDate(int jd, int &year, int &month, int &day) const 02421 { 02422 // Formula from The Calendar FAQ by Claus Tondering 02423 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 02424 // NOTE: Coded from scratch from mathematical formulas, not copied from 02425 // the Boost licensed source code 02426 02427 int a = jd + 32044; 02428 int b = ((4 * a) + 3) / 146097; 02429 int c = a - ((146097 * b) / 4); 02430 int d = ((4 * c) + 3) / 1461; 02431 int e = c - ((1461 * d) / 4); 02432 int m = ((5 * e) + 2) / 153; 02433 day = e - (((153 * m) + 2) / 5) + 1; 02434 month = m + 3 - (12 * (m / 10)); 02435 year = (100 * b) + d - 4800 + (m / 10); 02436 02437 // If year is -ve then is BC. In Gregorian there is no year 0, but the maths 02438 // is easier if we pretend there is, so internally year of 0 = 1BC = -1 outside 02439 if (year < 1) { 02440 year = year - 1; 02441 } 02442 02443 return true; 02444 } 02445 02446 // Dummy version using Gregorian as an example 02447 // This method MUST be re-implemented in any new Calendar System 02448 // The implementation MUST NOT do validity checking on date ranges, all calls to this function MUST 02449 // instead be wrapped in validity checks, as sometimes we want this to work outside the public valid 02450 // range, i.e. to allow us to internally set dates of 1/1/10000 which are not publically valid but 02451 // are required for internal maths 02452 bool KCalendarSystem::dateToJulianDay(int year, int month, int day, int &jd) const 02453 { 02454 // Formula from The Calendar FAQ by Claus Tondering 02455 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 02456 // NOTE: Coded from scratch from mathematical formulas, not copied from 02457 // the Boost licensed source code 02458 02459 // If year is -ve then is BC. In Gregorian there is no year 0, but the maths 02460 // is easier if we pretend there is, so internally year of -1 = 1BC = 0 internally 02461 int y; 02462 if (year < 1) { 02463 y = year + 1; 02464 } else { 02465 y = year; 02466 } 02467 02468 int a = (14 - month) / 12; 02469 y = y + 4800 - a; 02470 int m = month + (12 * a) - 3; 02471 02472 jd = day 02473 + (((153 * m) + 2) / 5) 02474 + (365 * y) 02475 + (y / 4) 02476 - (y / 100) 02477 + (y / 400) 02478 - 32045; 02479 02480 return true; 02481 } 02482 02483 const KLocale * KCalendarSystem::locale() const 02484 { 02485 Q_D(const KCalendarSystem); 02486 02487 return d->locale(); 02488 } 02489 02490 // Deprecated 02491 void KCalendarSystem::setMaxMonthsInYear(int maxMonths) 02492 { 02493 Q_UNUSED(maxMonths) 02494 } 02495 02496 // Deprecated 02497 void KCalendarSystem::setMaxDaysInWeek(int maxDays) 02498 { 02499 Q_UNUSED(maxDays) 02500 } 02501 02502 // Deprecated 02503 void KCalendarSystem::setHasYear0(bool hasYear0) 02504 { 02505 Q_UNUSED(hasYear0) 02506 }
KDE 4.7 API Reference