File indexing completed on 2023-09-24 04:04:45
0001 /* 0002 Copyright 2009, 2010 John Layt <john@layt.net> 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "kcalendarsystemjulian_p.h" 0021 #include "kcalendarsystemprivate_p.h" 0022 0023 #include "klocale.h" 0024 #include "klocalizedstring.h" 0025 #include "kconfiggroup.h" 0026 0027 #include <QDate> 0028 #include <QCharRef> 0029 0030 class KCalendarSystemJulianPrivate : public KCalendarSystemPrivate 0031 { 0032 public: 0033 KDELIBS4SUPPORT_DEPRECATED explicit KCalendarSystemJulianPrivate(KCalendarSystemJulian *q); 0034 0035 ~KCalendarSystemJulianPrivate() override; 0036 0037 // Virtual methods each calendar system must re-implement 0038 void loadDefaultEraList() override; 0039 int monthsInYear(int year) const override; 0040 int daysInMonth(int year, int month) const override; 0041 int daysInYear(int year) const override; 0042 bool isLeapYear(int year) const override; 0043 bool hasLeapMonths() const override; 0044 bool hasYearZero() const override; 0045 int maxMonthsInYear() const override; 0046 int earliestValidYear() const override; 0047 int latestValidYear() const override; 0048 QString monthName(int month, int year, KLocale::DateTimeComponentFormat format, bool possessive) const override; 0049 QString weekDayName(int weekDay, KLocale::DateTimeComponentFormat format) const override; 0050 0051 bool m_useCommonEra; 0052 }; 0053 0054 // Shared d pointer base class definitions 0055 0056 KCalendarSystemJulianPrivate::KCalendarSystemJulianPrivate(KCalendarSystemJulian *q) 0057 : KCalendarSystemPrivate(q) 0058 { 0059 } 0060 0061 KCalendarSystemJulianPrivate::~KCalendarSystemJulianPrivate() 0062 { 0063 } 0064 0065 void KCalendarSystemJulianPrivate::loadDefaultEraList() 0066 { 0067 QString name, shortName, format; 0068 0069 KConfigGroup cg(config(), QString::fromLatin1("KCalendarSystem %1").arg(q->calendarType())); 0070 m_useCommonEra = cg.readEntry("UseCommonEra", false); 0071 0072 if (m_useCommonEra) { 0073 name = i18nc("Calendar Era: Julian Common Era, years < 0, LongFormat", "Before Common Era"); 0074 shortName = i18nc("Calendar Era: Julian Common Era, years < 0, ShortFormat", "BCE"); 0075 } else { 0076 name = i18nc("Calendar Era: Julian Christian Era, years < 0, LongFormat", "Before Christ"); 0077 shortName = i18nc("Calendar Era: Julian Christian Era, years < 0, ShortFormat", "BC"); 0078 } 0079 format = i18nc("(kdedt-format) Julian, BC, full era year format used for %EY, e.g. 2000 BC", "%Ey %EC"); 0080 addEra('-', 1, q->epoch().addDays(-1), -1, q->earliestValidDate(), name, shortName, format); 0081 0082 if (m_useCommonEra) { 0083 name = i18nc("Calendar Era: Julian Common Era, years > 0, LongFormat", "Common Era"); 0084 shortName = i18nc("Calendar Era: Julian Common Era, years > 0, ShortFormat", "CE"); 0085 } else { 0086 name = i18nc("Calendar Era: Julian Christian Era, years > 0, LongFormat", "Anno Domini"); 0087 shortName = i18nc("Calendar Era: Julian Christian Era, years > 0, ShortFormat", "AD"); 0088 } 0089 format = i18nc("(kdedt-format) Julian, AD, full era year format used for %EY, e.g. 2000 AD", "%Ey %EC"); 0090 addEra('+', 1, q->epoch(), 1, q->latestValidDate(), name, shortName, format); 0091 } 0092 0093 int KCalendarSystemJulianPrivate::monthsInYear(int year) const 0094 { 0095 Q_UNUSED(year) 0096 return 12; 0097 } 0098 0099 int KCalendarSystemJulianPrivate::daysInMonth(int year, int month) const 0100 { 0101 if (month == 2) { 0102 if (isLeapYear(year)) { 0103 return 29; 0104 } else { 0105 return 28; 0106 } 0107 } 0108 0109 if (month == 4 || month == 6 || month == 9 || month == 11) { 0110 return 30; 0111 } 0112 0113 return 31; 0114 } 0115 0116 int KCalendarSystemJulianPrivate::daysInYear(int year) const 0117 { 0118 if (isLeapYear(year)) { 0119 return 366; 0120 } else { 0121 return 365; 0122 } 0123 } 0124 0125 bool KCalendarSystemJulianPrivate::isLeapYear(int year) const 0126 { 0127 if (year < 1) { 0128 year = year + 1; 0129 } 0130 0131 if (year % 4 == 0) { 0132 return true; 0133 } 0134 0135 return false; 0136 } 0137 0138 bool KCalendarSystemJulianPrivate::hasLeapMonths() const 0139 { 0140 return false; 0141 } 0142 0143 bool KCalendarSystemJulianPrivate::hasYearZero() const 0144 { 0145 return false; 0146 } 0147 0148 int KCalendarSystemJulianPrivate::maxMonthsInYear() const 0149 { 0150 return 12; 0151 } 0152 0153 int KCalendarSystemJulianPrivate::earliestValidYear() const 0154 { 0155 return -4712; 0156 } 0157 0158 int KCalendarSystemJulianPrivate::latestValidYear() const 0159 { 0160 return 9999; 0161 } 0162 0163 QString KCalendarSystemJulianPrivate::monthName(int month, int year, KLocale::DateTimeComponentFormat format, bool possessive) const 0164 { 0165 Q_UNUSED(year); 0166 0167 QStringList languages = locale()->languageList(); 0168 0169 if (format == KLocale::NarrowName) { 0170 switch (month) { 0171 case 1: 0172 return ki18nc("Julian month 1 - KLocale::NarrowName", "J").toString(languages); 0173 case 2: 0174 return ki18nc("Julian month 2 - KLocale::NarrowName", "F").toString(languages); 0175 case 3: 0176 return ki18nc("Julian month 3 - KLocale::NarrowName", "M").toString(languages); 0177 case 4: 0178 return ki18nc("Julian month 4 - KLocale::NarrowName", "A").toString(languages); 0179 case 5: 0180 return ki18nc("Julian month 5 - KLocale::NarrowName", "M").toString(languages); 0181 case 6: 0182 return ki18nc("Julian month 6 - KLocale::NarrowName", "J").toString(languages); 0183 case 7: 0184 return ki18nc("Julian month 7 - KLocale::NarrowName", "J").toString(languages); 0185 case 8: 0186 return ki18nc("Julian month 8 - KLocale::NarrowName", "A").toString(languages); 0187 case 9: 0188 return ki18nc("Julian month 9 - KLocale::NarrowName", "S").toString(languages); 0189 case 10: 0190 return ki18nc("Julian month 10 - KLocale::NarrowName", "O").toString(languages); 0191 case 11: 0192 return ki18nc("Julian month 11 - KLocale::NarrowName", "N").toString(languages); 0193 case 12: 0194 return ki18nc("Julian month 12 - KLocale::NarrowName", "D").toString(languages); 0195 default: 0196 return QString(); 0197 } 0198 } 0199 0200 if (format == KLocale::ShortName && possessive) { 0201 switch (month) { 0202 case 1: 0203 return ki18nc("Julian month 1 - KLocale::ShortName Possessive", "of Jan").toString(languages); 0204 case 2: 0205 return ki18nc("Julian month 2 - KLocale::ShortName Possessive", "of Feb").toString(languages); 0206 case 3: 0207 return ki18nc("Julian month 3 - KLocale::ShortName Possessive", "of Mar").toString(languages); 0208 case 4: 0209 return ki18nc("Julian month 4 - KLocale::ShortName Possessive", "of Apr").toString(languages); 0210 case 5: 0211 return ki18nc("Julian month 5 - KLocale::ShortName Possessive", "of May").toString(languages); 0212 case 6: 0213 return ki18nc("Julian month 6 - KLocale::ShortName Possessive", "of Jun").toString(languages); 0214 case 7: 0215 return ki18nc("Julian month 7 - KLocale::ShortName Possessive", "of Jul").toString(languages); 0216 case 8: 0217 return ki18nc("Julian month 8 - KLocale::ShortName Possessive", "of Aug").toString(languages); 0218 case 9: 0219 return ki18nc("Julian month 9 - KLocale::ShortName Possessive", "of Sep").toString(languages); 0220 case 10: 0221 return ki18nc("Julian month 10 - KLocale::ShortName Possessive", "of Oct").toString(languages); 0222 case 11: 0223 return ki18nc("Julian month 11 - KLocale::ShortName Possessive", "of Nov").toString(languages); 0224 case 12: 0225 return ki18nc("Julian month 12 - KLocale::ShortName Possessive", "of Dec").toString(languages); 0226 default: 0227 return QString(); 0228 } 0229 } 0230 0231 if (format == KLocale::ShortName && !possessive) { 0232 switch (month) { 0233 case 1: 0234 return ki18nc("Julian month 1 - KLocale::ShortName", "Jan").toString(languages); 0235 case 2: 0236 return ki18nc("Julian month 2 - KLocale::ShortName", "Feb").toString(languages); 0237 case 3: 0238 return ki18nc("Julian month 3 - KLocale::ShortName", "Mar").toString(languages); 0239 case 4: 0240 return ki18nc("Julian month 4 - KLocale::ShortName", "Apr").toString(languages); 0241 case 5: 0242 return ki18nc("Julian month 5 - KLocale::ShortName", "May").toString(languages); 0243 case 6: 0244 return ki18nc("Julian month 6 - KLocale::ShortName", "Jun").toString(languages); 0245 case 7: 0246 return ki18nc("Julian month 7 - KLocale::ShortName", "Jul").toString(languages); 0247 case 8: 0248 return ki18nc("Julian month 8 - KLocale::ShortName", "Aug").toString(languages); 0249 case 9: 0250 return ki18nc("Julian month 9 - KLocale::ShortName", "Sep").toString(languages); 0251 case 10: 0252 return ki18nc("Julian month 10 - KLocale::ShortName", "Oct").toString(languages); 0253 case 11: 0254 return ki18nc("Julian month 11 - KLocale::ShortName", "Nov").toString(languages); 0255 case 12: 0256 return ki18nc("Julian month 12 - KLocale::ShortName", "Dec").toString(languages); 0257 default: 0258 return QString(); 0259 } 0260 } 0261 0262 if (format == KLocale::LongName && possessive) { 0263 switch (month) { 0264 case 1: 0265 return ki18nc("Julian month 1 - KLocale::LongName Possessive", "of January").toString(languages); 0266 case 2: 0267 return ki18nc("Julian month 2 - KLocale::LongName Possessive", "of February").toString(languages); 0268 case 3: 0269 return ki18nc("Julian month 3 - KLocale::LongName Possessive", "of March").toString(languages); 0270 case 4: 0271 return ki18nc("Julian month 4 - KLocale::LongName Possessive", "of April").toString(languages); 0272 case 5: 0273 return ki18nc("Julian month 5 - KLocale::LongName Possessive", "of May").toString(languages); 0274 case 6: 0275 return ki18nc("Julian month 6 - KLocale::LongName Possessive", "of June").toString(languages); 0276 case 7: 0277 return ki18nc("Julian month 7 - KLocale::LongName Possessive", "of July").toString(languages); 0278 case 8: 0279 return ki18nc("Julian month 8 - KLocale::LongName Possessive", "of August").toString(languages); 0280 case 9: 0281 return ki18nc("Julian month 9 - KLocale::LongName Possessive", "of September").toString(languages); 0282 case 10: 0283 return ki18nc("Julian month 10 - KLocale::LongName Possessive", "of October").toString(languages); 0284 case 11: 0285 return ki18nc("Julian month 11 - KLocale::LongName Possessive", "of November").toString(languages); 0286 case 12: 0287 return ki18nc("Julian month 12 - KLocale::LongName Possessive", "of December").toString(languages); 0288 default: 0289 return QString(); 0290 } 0291 } 0292 0293 // Default to LongName 0294 switch (month) { 0295 case 1: 0296 return ki18nc("Julian month 1 - KLocale::LongName", "January").toString(languages); 0297 case 2: 0298 return ki18nc("Julian month 2 - KLocale::LongName", "February").toString(languages); 0299 case 3: 0300 return ki18nc("Julian month 3 - KLocale::LongName", "March").toString(languages); 0301 case 4: 0302 return ki18nc("Julian month 4 - KLocale::LongName", "April").toString(languages); 0303 case 5: 0304 return ki18nc("Julian month 5 - KLocale::LongName", "May").toString(languages); 0305 case 6: 0306 return ki18nc("Julian month 6 - KLocale::LongName", "June").toString(languages); 0307 case 7: 0308 return ki18nc("Julian month 7 - KLocale::LongName", "July").toString(languages); 0309 case 8: 0310 return ki18nc("Julian month 8 - KLocale::LongName", "August").toString(languages); 0311 case 9: 0312 return ki18nc("Julian month 9 - KLocale::LongName", "September").toString(languages); 0313 case 10: 0314 return ki18nc("Julian month 10 - KLocale::LongName", "October").toString(languages); 0315 case 11: 0316 return ki18nc("Julian month 11 - KLocale::LongName", "November").toString(languages); 0317 case 12: 0318 return ki18nc("Julian month 12 - KLocale::LongName", "December").toString(languages); 0319 default: 0320 return QString(); 0321 } 0322 } 0323 0324 QString KCalendarSystemJulianPrivate::weekDayName(int weekDay, KLocale::DateTimeComponentFormat format) const 0325 { 0326 QStringList languages = locale()->languageList(); 0327 0328 if (format == KLocale::NarrowName) { 0329 switch (weekDay) { 0330 case 1: 0331 return ki18nc("Julian weekday 1 - KLocale::NarrowName ", "M").toString(languages); 0332 case 2: 0333 return ki18nc("Julian weekday 2 - KLocale::NarrowName ", "T").toString(languages); 0334 case 3: 0335 return ki18nc("Julian weekday 3 - KLocale::NarrowName ", "W").toString(languages); 0336 case 4: 0337 return ki18nc("Julian weekday 4 - KLocale::NarrowName ", "T").toString(languages); 0338 case 5: 0339 return ki18nc("Julian weekday 5 - KLocale::NarrowName ", "F").toString(languages); 0340 case 6: 0341 return ki18nc("Julian weekday 6 - KLocale::NarrowName ", "S").toString(languages); 0342 case 7: 0343 return ki18nc("Julian weekday 7 - KLocale::NarrowName ", "S").toString(languages); 0344 default: 0345 return QString(); 0346 } 0347 } 0348 0349 if (format == KLocale::ShortName || format == KLocale:: ShortNumber) { 0350 switch (weekDay) { 0351 case 1: 0352 return ki18nc("Julian weekday 1 - KLocale::ShortName", "Mon").toString(languages); 0353 case 2: 0354 return ki18nc("Julian weekday 2 - KLocale::ShortName", "Tue").toString(languages); 0355 case 3: 0356 return ki18nc("Julian weekday 3 - KLocale::ShortName", "Wed").toString(languages); 0357 case 4: 0358 return ki18nc("Julian weekday 4 - KLocale::ShortName", "Thu").toString(languages); 0359 case 5: 0360 return ki18nc("Julian weekday 5 - KLocale::ShortName", "Fri").toString(languages); 0361 case 6: 0362 return ki18nc("Julian weekday 6 - KLocale::ShortName", "Sat").toString(languages); 0363 case 7: 0364 return ki18nc("Julian weekday 7 - KLocale::ShortName", "Sun").toString(languages); 0365 default: return QString(); 0366 } 0367 } 0368 0369 switch (weekDay) { 0370 case 1: 0371 return ki18nc("Julian weekday 1 - KLocale::LongName", "Monday").toString(languages); 0372 case 2: 0373 return ki18nc("Julian weekday 2 - KLocale::LongName", "Tuesday").toString(languages); 0374 case 3: 0375 return ki18nc("Julian weekday 3 - KLocale::LongName", "Wednesday").toString(languages); 0376 case 4: 0377 return ki18nc("Julian weekday 4 - KLocale::LongName", "Thursday").toString(languages); 0378 case 5: 0379 return ki18nc("Julian weekday 5 - KLocale::LongName", "Friday").toString(languages); 0380 case 6: 0381 return ki18nc("Julian weekday 6 - KLocale::LongName", "Saturday").toString(languages); 0382 case 7: 0383 return ki18nc("Julian weekday 7 - KLocale::LongName", "Sunday").toString(languages); 0384 default: 0385 return QString(); 0386 } 0387 } 0388 0389 KCalendarSystemJulian::KCalendarSystemJulian(const KSharedConfig::Ptr config, const KLocale *locale) 0390 : KCalendarSystem(*new KCalendarSystemJulianPrivate(this), config, locale) 0391 { 0392 d_ptr->loadConfig(calendarType()); 0393 } 0394 0395 KCalendarSystemJulian::KCalendarSystemJulian(KCalendarSystemJulianPrivate &dd, 0396 const KSharedConfig::Ptr config, const KLocale *locale) 0397 : KCalendarSystem(dd, config, locale) 0398 { 0399 d_ptr->loadConfig(calendarType()); 0400 } 0401 0402 KCalendarSystemJulian::~KCalendarSystemJulian() 0403 { 0404 } 0405 0406 QString KCalendarSystemJulian::calendarType() const 0407 { 0408 return QLatin1String("julian"); 0409 } 0410 0411 KLocale::CalendarSystem KCalendarSystemJulian::calendarSystem() const 0412 { 0413 return KLocale::JulianCalendar; 0414 } 0415 0416 QDate KCalendarSystemJulian::epoch() const 0417 { 0418 return QDate::fromJulianDay(1721426); 0419 } 0420 0421 QDate KCalendarSystemJulian::earliestValidDate() const 0422 { 0423 // 1 Jan 4712 BC, no year zero, cant be 4713BC due to error in QDate that day 0 is not valid 0424 // and we really need the first in each year to be valid for the date maths 0425 return QDate::fromJulianDay(366); 0426 } 0427 0428 QDate KCalendarSystemJulian::latestValidDate() const 0429 { 0430 // Set to last day of year 9999 until confirm date formats & widgets support > 9999 0431 // 31 Dec 9999 AD, no year zero 0432 return QDate::fromJulianDay(5373557); 0433 } 0434 0435 QString KCalendarSystemJulian::monthName(int month, int year, MonthNameFormat format) const 0436 { 0437 return KCalendarSystem::monthName(month, year, format); 0438 } 0439 0440 QString KCalendarSystemJulian::monthName(const QDate &date, MonthNameFormat format) const 0441 { 0442 return KCalendarSystem::monthName(date, format); 0443 } 0444 0445 QString KCalendarSystemJulian::weekDayName(int weekDay, WeekDayNameFormat format) const 0446 { 0447 return KCalendarSystem::weekDayName(weekDay, format); 0448 } 0449 0450 QString KCalendarSystemJulian::weekDayName(const QDate &date, WeekDayNameFormat format) const 0451 { 0452 return KCalendarSystem::weekDayName(date, format); 0453 } 0454 0455 bool KCalendarSystemJulian::isLunar() const 0456 { 0457 return false; 0458 } 0459 0460 bool KCalendarSystemJulian::isLunisolar() const 0461 { 0462 return false; 0463 } 0464 0465 bool KCalendarSystemJulian::isSolar() const 0466 { 0467 return true; 0468 } 0469 0470 bool KCalendarSystemJulian::isProleptic() const 0471 { 0472 return true; 0473 } 0474 0475 bool KCalendarSystemJulian::julianDayToDate(qint64 jd, int &year, int &month, int &day) const 0476 { 0477 // Formula from The Calendar FAQ by Claus Tondering 0478 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 0479 // NOTE: Coded from scratch from mathematical formulas, not copied from 0480 // the Boost licensed source code 0481 0482 int b = 0; 0483 int c = jd + 32082; 0484 int d = ((4 * c) + 3) / 1461; 0485 int e = c - ((1461 * d) / 4); 0486 int m = ((5 * e) + 2) / 153; 0487 day = e - (((153 * m) + 2) / 5) + 1; 0488 month = m + 3 - (12 * (m / 10)); 0489 year = (100 * b) + d - 4800 + (m / 10); 0490 0491 // If year is -ve then is BC. In Julian there is no year 0, but the maths 0492 // is easier if we pretend there is, so internally year of 0 = 1BC = -1 outside 0493 if (year < 1) { 0494 year = year - 1; 0495 } 0496 0497 return true; 0498 } 0499 0500 bool KCalendarSystemJulian::dateToJulianDay(int year, int month, int day, qint64 &jd) const 0501 { 0502 // Formula from The Calendar FAQ by Claus Tondering 0503 // http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000 0504 // NOTE: Coded from scratch from mathematical formulas, not copied from 0505 // the Boost licensed source code 0506 0507 // If year is -ve then is BC. In Julian there is no year 0, but the maths 0508 // is easier if we pretend there is, so internally year of -1 = 1BC = 0 internally 0509 int y; 0510 if (year < 1) { 0511 y = year + 1; 0512 } else { 0513 y = year; 0514 } 0515 0516 int a = (14 - month) / 12; 0517 y = y + 4800 - a; 0518 int m = month + (12 * a) - 3; 0519 0520 jd = day 0521 + (((153 * m) + 2) / 5) 0522 + (365 * y) 0523 + (y / 4) 0524 - 32083; 0525 0526 return true; 0527 }