• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

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 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal