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