KDECore
kcalendarsystemgregorian.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright 2009, 2010 John Layt <john@layt.net> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 // Derived gregorian kde calendar class 00021 00022 #include "kcalendarsystemgregorian_p.h" 00023 #include "kcalendarsystemgregorianprivate_p.h" 00024 #include "kcalendarera_p.h" 00025 00026 #include "kdebug.h" 00027 #include "klocale.h" 00028 #include "kglobal.h" 00029 #include "kconfiggroup.h" 00030 00031 #include <QtCore/QDate> 00032 #include <QtCore/QCharRef> 00033 00034 // Shared d pointer base class definitions 00035 00036 KCalendarSystemGregorianPrivate::KCalendarSystemGregorianPrivate(KCalendarSystemGregorian *q) 00037 : KCalendarSystemPrivate(q) 00038 { 00039 } 00040 00041 KCalendarSystemGregorianPrivate::~KCalendarSystemGregorianPrivate() 00042 { 00043 } 00044 00045 KLocale::CalendarSystem KCalendarSystemGregorianPrivate::calendarSystem() const 00046 { 00047 return KLocale::GregorianCalendar; 00048 } 00049 00050 // Dummy version using Gregorian as an example 00051 // This method MUST be re-implemented in any new Calendar System 00052 void KCalendarSystemGregorianPrivate::loadDefaultEraList() 00053 { 00054 QString name, shortName, format; 00055 00056 KConfigGroup cg(config(), QString::fromLatin1("KCalendarSystem %1").arg(q->calendarType(q->calendarSystem()))); 00057 m_useCommonEra = cg.readEntry("UseCommonEra", false); 00058 00059 if (m_useCommonEra) { 00060 name = i18nc("Calendar Era: Gregorian Common Era, years < 0, LongFormat", "Before Common Era"); 00061 shortName = i18nc("Calendar Era: Gregorian Common Era, years < 0, ShortFormat", "BCE"); 00062 } else { 00063 name = i18nc("Calendar Era: Gregorian Christian Era, years < 0, LongFormat", "Before Christ"); 00064 shortName = i18nc("Calendar Era: Gregorian Christian Era, years < 0, ShortFormat", "BC"); 00065 } 00066 format = i18nc("(kdedt-format) Gregorian, BC, full era year format used for %EY, e.g. 2000 BC", "%Ey %EC"); 00067 addEra('-', 1, q->epoch().addDays(-1), -1, q->earliestValidDate(), name, shortName, format); 00068 00069 if (m_useCommonEra) { 00070 name = i18nc("Calendar Era: Gregorian Common Era, years > 0, LongFormat", "Common Era"); 00071 shortName = i18nc("Calendar Era: Gregorian Common Era, years > 0, ShortFormat", "CE"); 00072 } else { 00073 name = i18nc("Calendar Era: Gregorian Christian Era, years > 0, LongFormat", "Anno Domini"); 00074 shortName = i18nc("Calendar Era: Gregorian Christian Era, years > 0, ShortFormat", "AD"); 00075 } 00076 format = i18nc("(kdedt-format) Gregorian, AD, full era year format used for %EY, e.g. 2000 AD", "%Ey %EC"); 00077 addEra('+', 1, q->epoch(), 1, q->latestValidDate(), name, shortName, format); 00078 } 00079 00080 int KCalendarSystemGregorianPrivate::monthsInYear(int year) const 00081 { 00082 Q_UNUSED(year) 00083 return 12; 00084 } 00085 00086 int KCalendarSystemGregorianPrivate::daysInMonth(int year, int month) const 00087 { 00088 if (month == 2) { 00089 if (isLeapYear(year)) { 00090 return 29; 00091 } else { 00092 return 28; 00093 } 00094 } 00095 00096 if (month == 4 || month == 6 || month == 9 || month == 11) { 00097 return 30; 00098 } 00099 00100 return 31; 00101 } 00102 00103 int KCalendarSystemGregorianPrivate::daysInYear(int year) const 00104 { 00105 if (isLeapYear(year)) { 00106 return 366; 00107 } else { 00108 return 365; 00109 } 00110 } 00111 00112 int KCalendarSystemGregorianPrivate::daysInWeek() const 00113 { 00114 return 7; 00115 } 00116 00117 bool KCalendarSystemGregorianPrivate::isLeapYear(int year) const 00118 { 00119 if (!hasYearZero() && year < 1) { 00120 year = year + 1; 00121 } 00122 00123 if (year % 4 == 0) { 00124 if (year % 100 != 0) { 00125 return true; 00126 } else if (year % 400 == 0) { 00127 return true; 00128 } 00129 } 00130 00131 return false; 00132 } 00133 00134 bool KCalendarSystemGregorianPrivate::hasLeapMonths() const 00135 { 00136 return false; 00137 } 00138 00139 bool KCalendarSystemGregorianPrivate::hasYearZero() const 00140 { 00141 return false; 00142 } 00143 00144 int KCalendarSystemGregorianPrivate::maxDaysInWeek() const 00145 { 00146 return 7; 00147 } 00148 00149 int KCalendarSystemGregorianPrivate::maxMonthsInYear() const 00150 { 00151 return 12; 00152 } 00153 00154 int KCalendarSystemGregorianPrivate::earliestValidYear() const 00155 { 00156 return -4713; 00157 } 00158 00159 int KCalendarSystemGregorianPrivate::latestValidYear() const 00160 { 00161 return 9999; 00162 } 00163 00164 QString KCalendarSystemGregorianPrivate::monthName(int month, int year, KLocale::DateTimeComponentFormat format, bool possessive) const 00165 { 00166 Q_UNUSED(year); 00167 00168 if (format == KLocale::NarrowName) { 00169 switch (month) { 00170 case 1: 00171 return ki18nc("Gregorian month 1 - KLocale::NarrowName", "J").toString(locale()); 00172 case 2: 00173 return ki18nc("Gregorian month 2 - KLocale::NarrowName", "F").toString(locale()); 00174 case 3: 00175 return ki18nc("Gregorian month 3 - KLocale::NarrowName", "M").toString(locale()); 00176 case 4: 00177 return ki18nc("Gregorian month 4 - KLocale::NarrowName", "A").toString(locale()); 00178 case 5: 00179 return ki18nc("Gregorian month 5 - KLocale::NarrowName", "M").toString(locale()); 00180 case 6: 00181 return ki18nc("Gregorian month 6 - KLocale::NarrowName", "J").toString(locale()); 00182 case 7: 00183 return ki18nc("Gregorian month 7 - KLocale::NarrowName", "J").toString(locale()); 00184 case 8: 00185 return ki18nc("Gregorian month 8 - KLocale::NarrowName", "A").toString(locale()); 00186 case 9: 00187 return ki18nc("Gregorian month 9 - KLocale::NarrowName", "S").toString(locale()); 00188 case 10: 00189 return ki18nc("Gregorian month 10 - KLocale::NarrowName", "O").toString(locale()); 00190 case 11: 00191 return ki18nc("Gregorian month 11 - KLocale::NarrowName", "N").toString(locale()); 00192 case 12: 00193 return ki18nc("Gregorian month 12 - KLocale::NarrowName", "D").toString(locale()); 00194 default: 00195 return QString(); 00196 } 00197 } 00198 00199 if (format == KLocale::ShortName && possessive) { 00200 switch (month) { 00201 case 1: 00202 return ki18nc("Gregorian month 1 - KLocale::ShortName Possessive", "of Jan").toString(locale()); 00203 case 2: 00204 return ki18nc("Gregorian month 2 - KLocale::ShortName Possessive", "of Feb").toString(locale()); 00205 case 3: 00206 return ki18nc("Gregorian month 3 - KLocale::ShortName Possessive", "of Mar").toString(locale()); 00207 case 4: 00208 return ki18nc("Gregorian month 4 - KLocale::ShortName Possessive", "of Apr").toString(locale()); 00209 case 5: 00210 return ki18nc("Gregorian month 5 - KLocale::ShortName Possessive", "of May").toString(locale()); 00211 case 6: 00212 return ki18nc("Gregorian month 6 - KLocale::ShortName Possessive", "of Jun").toString(locale()); 00213 case 7: 00214 return ki18nc("Gregorian month 7 - KLocale::ShortName Possessive", "of Jul").toString(locale()); 00215 case 8: 00216 return ki18nc("Gregorian month 8 - KLocale::ShortName Possessive", "of Aug").toString(locale()); 00217 case 9: 00218 return ki18nc("Gregorian month 9 - KLocale::ShortName Possessive", "of Sep").toString(locale()); 00219 case 10: 00220 return ki18nc("Gregorian month 10 - KLocale::ShortName Possessive", "of Oct").toString(locale()); 00221 case 11: 00222 return ki18nc("Gregorian month 11 - KLocale::ShortName Possessive", "of Nov").toString(locale()); 00223 case 12: 00224 return ki18nc("Gregorian month 12 - KLocale::ShortName Possessive", "of Dec").toString(locale()); 00225 default: 00226 return QString(); 00227 } 00228 } 00229 00230 if (format == KLocale::ShortName && !possessive) { 00231 switch (month) { 00232 case 1: 00233 return ki18nc("Gregorian month 1 - KLocale::ShortName", "Jan").toString(locale()); 00234 case 2: 00235 return ki18nc("Gregorian month 2 - KLocale::ShortName", "Feb").toString(locale()); 00236 case 3: 00237 return ki18nc("Gregorian month 3 - KLocale::ShortName", "Mar").toString(locale()); 00238 case 4: 00239 return ki18nc("Gregorian month 4 - KLocale::ShortName", "Apr").toString(locale()); 00240 case 5: 00241 return ki18nc("Gregorian month 5 - KLocale::ShortName", "May").toString(locale()); 00242 case 6: 00243 return ki18nc("Gregorian month 6 - KLocale::ShortName", "Jun").toString(locale()); 00244 case 7: 00245 return ki18nc("Gregorian month 7 - KLocale::ShortName", "Jul").toString(locale()); 00246 case 8: 00247 return ki18nc("Gregorian month 8 - KLocale::ShortName", "Aug").toString(locale()); 00248 case 9: 00249 return ki18nc("Gregorian month 9 - KLocale::ShortName", "Sep").toString(locale()); 00250 case 10: 00251 return ki18nc("Gregorian month 10 - KLocale::ShortName", "Oct").toString(locale()); 00252 case 11: 00253 return ki18nc("Gregorian month 11 - KLocale::ShortName", "Nov").toString(locale()); 00254 case 12: 00255 return ki18nc("Gregorian month 12 - KLocale::ShortName", "Dec").toString(locale()); 00256 default: 00257 return QString(); 00258 } 00259 } 00260 00261 if (format == KLocale::LongName && possessive) { 00262 switch (month) { 00263 case 1: 00264 return ki18nc("Gregorian month 1 - KLocale::LongName Possessive", "of January").toString(locale()); 00265 case 2: 00266 return ki18nc("Gregorian month 2 - KLocale::LongName Possessive", "of February").toString(locale()); 00267 case 3: 00268 return ki18nc("Gregorian month 3 - KLocale::LongName Possessive", "of March").toString(locale()); 00269 case 4: 00270 return ki18nc("Gregorian month 4 - KLocale::LongName Possessive", "of April").toString(locale()); 00271 case 5: 00272 return ki18nc("Gregorian month 5 - KLocale::LongName Possessive", "of May").toString(locale()); 00273 case 6: 00274 return ki18nc("Gregorian month 6 - KLocale::LongName Possessive", "of June").toString(locale()); 00275 case 7: 00276 return ki18nc("Gregorian month 7 - KLocale::LongName Possessive", "of July").toString(locale()); 00277 case 8: 00278 return ki18nc("Gregorian month 8 - KLocale::LongName Possessive", "of August").toString(locale()); 00279 case 9: 00280 return ki18nc("Gregorian month 9 - KLocale::LongName Possessive", "of September").toString(locale()); 00281 case 10: 00282 return ki18nc("Gregorian month 10 - KLocale::LongName Possessive", "of October").toString(locale()); 00283 case 11: 00284 return ki18nc("Gregorian month 11 - KLocale::LongName Possessive", "of November").toString(locale()); 00285 case 12: 00286 return ki18nc("Gregorian month 12 - KLocale::LongName Possessive", "of December").toString(locale()); 00287 default: 00288 return QString(); 00289 } 00290 } 00291 00292 // Default to LongName 00293 switch (month) { 00294 case 1: 00295 return ki18nc("Gregorian month 1 - KLocale::LongName", "January").toString(locale()); 00296 case 2: 00297 return ki18nc("Gregorian month 2 - KLocale::LongName", "February").toString(locale()); 00298 case 3: 00299 return ki18nc("Gregorian month 3 - KLocale::LongName", "March").toString(locale()); 00300 case 4: 00301 return ki18nc("Gregorian month 4 - KLocale::LongName", "April").toString(locale()); 00302 case 5: 00303 return ki18nc("Gregorian month 5 - KLocale::LongName", "May").toString(locale()); 00304 case 6: 00305 return ki18nc("Gregorian month 6 - KLocale::LongName", "June").toString(locale()); 00306 case 7: 00307 return ki18nc("Gregorian month 7 - KLocale::LongName", "July").toString(locale()); 00308 case 8: 00309 return ki18nc("Gregorian month 8 - KLocale::LongName", "August").toString(locale()); 00310 case 9: 00311 return ki18nc("Gregorian month 9 - KLocale::LongName", "September").toString(locale()); 00312 case 10: 00313 return ki18nc("Gregorian month 10 - KLocale::LongName", "October").toString(locale()); 00314 case 11: 00315 return ki18nc("Gregorian month 11 - KLocale::LongName", "November").toString(locale()); 00316 case 12: 00317 return ki18nc("Gregorian month 12 - KLocale::LongName", "December").toString(locale()); 00318 default: 00319 return QString(); 00320 } 00321 } 00322 00323 QString KCalendarSystemGregorianPrivate::weekDayName(int weekDay, KLocale::DateTimeComponentFormat format) const 00324 { 00325 if (format == KLocale::NarrowName) { 00326 switch (weekDay) { 00327 case 1: 00328 return ki18nc("Gregorian weekday 1 - KLocale::NarrowName ", "M").toString(locale()); 00329 case 2: 00330 return ki18nc("Gregorian weekday 2 - KLocale::NarrowName ", "T").toString(locale()); 00331 case 3: 00332 return ki18nc("Gregorian weekday 3 - KLocale::NarrowName ", "W").toString(locale()); 00333 case 4: 00334 return ki18nc("Gregorian weekday 4 - KLocale::NarrowName ", "T").toString(locale()); 00335 case 5: 00336 return ki18nc("Gregorian weekday 5 - KLocale::NarrowName ", "F").toString(locale()); 00337 case 6: 00338 return ki18nc("Gregorian weekday 6 - KLocale::NarrowName ", "S").toString(locale()); 00339 case 7: 00340 return ki18nc("Gregorian weekday 7 - KLocale::NarrowName ", "S").toString(locale()); 00341 default: 00342 return QString(); 00343 } 00344 } 00345 00346 if (format == KLocale::ShortName || format == KLocale:: ShortNumber) { 00347 switch (weekDay) { 00348 case 1: 00349 return ki18nc("Gregorian weekday 1 - KLocale::ShortName", "Mon").toString(locale()); 00350 case 2: 00351 return ki18nc("Gregorian weekday 2 - KLocale::ShortName", "Tue").toString(locale()); 00352 case 3: 00353 return ki18nc("Gregorian weekday 3 - KLocale::ShortName", "Wed").toString(locale()); 00354 case 4: 00355 return ki18nc("Gregorian weekday 4 - KLocale::ShortName", "Thu").toString(locale()); 00356 case 5: 00357 return ki18nc("Gregorian weekday 5 - KLocale::ShortName", "Fri").toString(locale()); 00358 case 6: 00359 return ki18nc("Gregorian weekday 6 - KLocale::ShortName", "Sat").toString(locale()); 00360 case 7: 00361 return ki18nc("Gregorian weekday 7 - KLocale::ShortName", "Sun").toString(locale()); 00362 default: return QString(); 00363 } 00364 } 00365 00366 switch (weekDay) { 00367 case 1: 00368 return ki18nc("Gregorian weekday 1 - KLocale::LongName", "Monday").toString(locale()); 00369 case 2: 00370 return ki18nc("Gregorian weekday 2 - KLocale::LongName", "Tuesday").toString(locale()); 00371 case 3: 00372 return ki18nc("Gregorian weekday 3 - KLocale::LongName", "Wednesday").toString(locale()); 00373 case 4: 00374 return ki18nc("Gregorian weekday 4 - KLocale::LongName", "Thursday").toString(locale()); 00375 case 5: 00376 return ki18nc("Gregorian weekday 5 - KLocale::LongName", "Friday").toString(locale()); 00377 case 6: 00378 return ki18nc("Gregorian weekday 6 - KLocale::LongName", "Saturday").toString(locale()); 00379 case 7: 00380 return ki18nc("Gregorian weekday 7 - KLocale::LongName", "Sunday").toString(locale()); 00381 default: 00382 return QString(); 00383 } 00384 } 00385 00386 00387 KCalendarSystemGregorian::KCalendarSystemGregorian(const KLocale *locale) 00388 : KCalendarSystem(*new KCalendarSystemGregorianPrivate(this), KSharedConfig::Ptr(), locale) 00389 { 00390 d_ptr->loadConfig(calendarType()); 00391 } 00392 00393 KCalendarSystemGregorian::KCalendarSystemGregorian(const KSharedConfig::Ptr config, 00394 const KLocale *locale) 00395 : KCalendarSystem(*new KCalendarSystemGregorianPrivate(this), config, locale) 00396 { 00397 d_ptr->loadConfig(calendarType()); 00398 } 00399 00400 KCalendarSystemGregorian::KCalendarSystemGregorian(KCalendarSystemGregorianPrivate &dd, 00401 const KSharedConfig::Ptr config, 00402 const KLocale *locale) 00403 : KCalendarSystem(dd, config, locale) 00404 { 00405 d_ptr->loadConfig(calendarType()); 00406 } 00407 00408 KCalendarSystemGregorian::~KCalendarSystemGregorian() 00409 { 00410 } 00411 00412 QString KCalendarSystemGregorian::calendarType() const 00413 { 00414 return QLatin1String("gregorian-proleptic"); 00415 } 00416 00417 QDate KCalendarSystemGregorian::epoch() const 00418 { 00419 return QDate::fromJulianDay(1721426); 00420 } 00421 00422 QDate KCalendarSystemGregorian::earliestValidDate() const 00423 { 00424 // Gregorian 1 Jan 4713 BC, no year zero 00425 return QDate::fromJulianDay(38); 00426 } 00427 00428 QDate KCalendarSystemGregorian::latestValidDate() const 00429 { 00430 // Set to last day of year 9999 until confirm date formats & widgets support > 9999 00431 // In Gregorian this is 9999-12-31, which is is jd 5373484 00432 // Can't call setDate( 9999, 12, 31 ) as it creates circular reference! 00433 return QDate::fromJulianDay(5373484); 00434 } 00435 00436 bool KCalendarSystemGregorian::isValid(int year, int month, int day) const 00437 { 00438 return KCalendarSystem::isValid(year, month, day); 00439 } 00440 00441 bool KCalendarSystemGregorian::isValid(const QDate &date) const 00442 { 00443 return KCalendarSystem::isValid(date); 00444 } 00445 00446 bool KCalendarSystemGregorian::isLeapYear(int year) const 00447 { 00448 return KCalendarSystem::isLeapYear(year); 00449 } 00450 00451 bool KCalendarSystemGregorian::isLeapYear(const QDate &date) const 00452 { 00453 return KCalendarSystem::isLeapYear(date); 00454 } 00455 00456 QString KCalendarSystemGregorian::monthName(int month, int year, MonthNameFormat format) const 00457 { 00458 return KCalendarSystem::monthName(month, year, format); 00459 } 00460 00461 QString KCalendarSystemGregorian::monthName(const QDate &date, MonthNameFormat format) const 00462 { 00463 return KCalendarSystem::monthName(date, format); 00464 } 00465 00466 QString KCalendarSystemGregorian::weekDayName(int weekDay, WeekDayNameFormat format) const 00467 { 00468 return KCalendarSystem::weekDayName(weekDay, format); 00469 } 00470 00471 QString KCalendarSystemGregorian::weekDayName(const QDate &date, WeekDayNameFormat format) const 00472 { 00473 return KCalendarSystem::weekDayName(date, format); 00474 } 00475 00476 int KCalendarSystemGregorian::yearStringToInteger(const QString &sNum, int &iLength) const 00477 { 00478 return KCalendarSystem::yearStringToInteger(sNum, iLength); 00479 } 00480 00481 int KCalendarSystemGregorian::weekDayOfPray() const 00482 { 00483 return 7; // sunday 00484 } 00485 00486 bool KCalendarSystemGregorian::isLunar() const 00487 { 00488 return false; 00489 } 00490 00491 bool KCalendarSystemGregorian::isLunisolar() const 00492 { 00493 return false; 00494 } 00495 00496 bool KCalendarSystemGregorian::isSolar() const 00497 { 00498 return true; 00499 } 00500 00501 bool KCalendarSystemGregorian::isProleptic() const 00502 { 00503 return true; 00504 } 00505 00506 bool KCalendarSystemGregorian::julianDayToDate(int jd, int &year, int &month, int &day) const 00507 { 00508 Q_D(const KCalendarSystemGregorian); 00509 00510 // Formula from The Calendar FAQ by Claus Tondering 00511 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 00512 // NOTE: Coded from scratch from mathematical formulas, not copied from 00513 // the Boost licensed source code 00514 00515 int a = jd + 32044; 00516 int b = ((4 * a) + 3) / 146097; 00517 int c = a - ((146097 * b) / 4); 00518 int dd = ((4 * c) + 3) / 1461; 00519 int e = c - ((1461 * dd) / 4); 00520 int m = ((5 * e) + 2) / 153; 00521 day = e - (((153 * m) + 2) / 5) + 1; 00522 month = m + 3 - (12 * (m / 10)); 00523 year = (100 * b) + dd - 4800 + (m / 10); 00524 00525 // If year is -ve then is BC. In Gregorian there is no year 0, but the maths 00526 // is easier if we pretend there is, so internally year of 0 = 1BC = -1 outside 00527 // Check for Year 0 support as some Gregorian based calendars do have it, e.g. Thai and ISO 00528 if (!d->hasYearZero() && year < 1) { 00529 year = year - 1; 00530 } 00531 return true; 00532 } 00533 00534 bool KCalendarSystemGregorian::dateToJulianDay(int year, int month, int day, int &jd) const 00535 { 00536 Q_D(const KCalendarSystemGregorian); 00537 00538 // Formula from The Calendar FAQ by Claus Tondering 00539 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 00540 // NOTE: Coded from scratch from mathematical formulas, not copied from 00541 // the Boost licensed source code 00542 00543 // If year is -ve then is BC. In Gregorian there is no year 0, but the maths 00544 // is easier if we pretend there is, so internally year of -1 = 1BC = 0 internally 00545 // Check for Year 0 support as some Gregorian based calendars do have it, e.g. Thai and ISO 00546 int y; 00547 if (!d->hasYearZero() && year < 1) { 00548 y = year + 1; 00549 } else { 00550 y = year; 00551 } 00552 00553 int a = (14 - month) / 12; 00554 y = y + 4800 - a; 00555 int m = month + (12 * a) - 3; 00556 00557 jd = day 00558 + (((153 * m) + 2) / 5) 00559 + (365 * y) 00560 + (y / 4) 00561 - (y / 100) 00562 + (y / 400) 00563 - 32045; 00564 00565 return true; 00566 }
KDE 4.7 API Reference