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

KDECore

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • 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.3
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