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 }
KDE 4.6 API Reference