File indexing completed on 2023-10-03 03:16:18
0001 /* 0002 Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es> 0003 Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org> 0004 Copyright 2007, 2008, 2009, 2010 John Layt <john@layt.net> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "kcalendarsystem.h" 0023 #include "kcalendarsystemprivate_p.h" 0024 0025 #include "kconfiggroup.h" 0026 0027 #include <QDateTime> 0028 0029 #include "klocalizedstring.h" 0030 #include "kdatetime.h" 0031 #include "kdatetimeformatter_p.h" 0032 #include "kdatetimeparser_p.h" 0033 #include "kcalendarera_p.h" 0034 #include "kcalendarsystemcoptic_p.h" 0035 #include "kcalendarsystemethiopian_p.h" 0036 #include "kcalendarsystemgregorian_p.h" 0037 #include "kcalendarsystemhebrew_p.h" 0038 #include "kcalendarsystemindiannational_p.h" 0039 #include "kcalendarsystemislamiccivil_p.h" 0040 #include "kcalendarsystemjalali_p.h" 0041 #include "kcalendarsystemjapanese_p.h" 0042 #include "kcalendarsystemjulian_p.h" 0043 #include "kcalendarsystemminguo_p.h" 0044 #include "kcalendarsystemthai_p.h" 0045 0046 KCalendarSystem *KCalendarSystem::create(KLocale::CalendarSystem calendarSystem, const KLocale *locale) 0047 { 0048 return create(calendarSystem, KSharedConfig::Ptr(), locale); 0049 } 0050 0051 KCalendarSystem *KCalendarSystem::create(KLocale::CalendarSystem calendarSystem, 0052 KSharedConfig::Ptr config, 0053 const KLocale *locale) 0054 { 0055 switch (calendarSystem) { 0056 case KLocale::GregorianCalendar: 0057 return new KCalendarSystemGregorian(config, locale); 0058 case KLocale::CopticCalendar: 0059 return new KCalendarSystemCoptic(config, locale); 0060 case KLocale::EthiopianCalendar: 0061 return new KCalendarSystemEthiopian(config, locale); 0062 case KLocale::HebrewCalendar: 0063 return new KCalendarSystemHebrew(config, locale); 0064 case KLocale::IndianNationalCalendar: 0065 return new KCalendarSystemIndianNational(config, locale); 0066 case KLocale::IslamicCivilCalendar: 0067 return new KCalendarSystemIslamicCivil(config, locale); 0068 case KLocale::JalaliCalendar: 0069 return new KCalendarSystemJalali(config, locale); 0070 case KLocale::JapaneseCalendar: 0071 return new KCalendarSystemJapanese(config, locale); 0072 case KLocale::JulianCalendar: 0073 return new KCalendarSystemJulian(config, locale); 0074 case KLocale::MinguoCalendar: 0075 return new KCalendarSystemMinguo(config, locale); 0076 case KLocale::ThaiCalendar: 0077 return new KCalendarSystemThai(config, locale); 0078 default: 0079 return new KCalendarSystemGregorian(config, locale); 0080 } 0081 } 0082 0083 QList<KLocale::CalendarSystem> KCalendarSystem::calendarSystemsList() 0084 { 0085 QList<KLocale::CalendarSystem> list; 0086 0087 list.append(KLocale::GregorianCalendar); 0088 list.append(KLocale::CopticCalendar); 0089 list.append(KLocale::EthiopianCalendar); 0090 list.append(KLocale::HebrewCalendar); 0091 list.append(KLocale::IslamicCivilCalendar); 0092 list.append(KLocale::IndianNationalCalendar); 0093 list.append(KLocale::JalaliCalendar); 0094 list.append(KLocale::JapaneseCalendar); 0095 list.append(KLocale::JulianCalendar); 0096 list.append(KLocale::MinguoCalendar); 0097 list.append(KLocale::ThaiCalendar); 0098 0099 return list; 0100 } 0101 0102 QString KCalendarSystem::calendarLabel(KLocale::CalendarSystem calendarSystem, const KLocale *locale) 0103 { 0104 QStringList languages = locale->languageList(); 0105 0106 switch (calendarSystem) { 0107 case KLocale::GregorianCalendar: 0108 return ki18nc("@item Calendar system", "Gregorian").toString(languages); 0109 case KLocale::CopticCalendar: 0110 return ki18nc("@item Calendar system", "Coptic").toString(languages); 0111 case KLocale::EthiopianCalendar: 0112 return ki18nc("@item Calendar system", "Ethiopian").toString(languages); 0113 case KLocale::HebrewCalendar: 0114 return ki18nc("@item Calendar system", "Hebrew").toString(languages); 0115 case KLocale::IslamicCivilCalendar: 0116 return ki18nc("@item Calendar system", "Islamic / Hijri (Civil)").toString(languages); 0117 case KLocale::IndianNationalCalendar: 0118 return ki18nc("@item Calendar system", "Indian National").toString(languages); 0119 case KLocale::JalaliCalendar: 0120 return ki18nc("@item Calendar system", "Jalali").toString(languages); 0121 case KLocale::JapaneseCalendar: 0122 return ki18nc("@item Calendar system", "Japanese").toString(languages); 0123 case KLocale::JulianCalendar: 0124 return ki18nc("@item Calendar system", "Julian").toString(languages); 0125 case KLocale::MinguoCalendar: 0126 return ki18nc("@item Calendar system", "Taiwanese").toString(languages); 0127 case KLocale::ThaiCalendar: 0128 return ki18nc("@item Calendar system", "Thai").toString(languages); 0129 } 0130 0131 return ki18nc("@item Calendar system", "Invalid Calendar Type").toString(languages); 0132 } 0133 0134 // Shared d pointer base class definitions 0135 0136 KCalendarSystemPrivate::KCalendarSystemPrivate(KCalendarSystem *q_ptr) 0137 : q(q_ptr), 0138 m_eraList(nullptr), 0139 m_shortYearWindowStartYear(2000) 0140 { 0141 } 0142 0143 KCalendarSystemPrivate::~KCalendarSystemPrivate() 0144 { 0145 delete m_eraList; 0146 } 0147 0148 int KCalendarSystemPrivate::isoWeekNumber(const QDate &date, int *yearNum) const 0149 { 0150 int y, m, d; 0151 q->julianDayToDate(date.toJulianDay(), y, m, d); 0152 0153 QDate firstDayWeek1, lastDay; 0154 int week; 0155 int weekDay1, dayOfWeek1InYear; 0156 0157 // let's guess 1st day of 1st week 0158 firstDayWeek1 = firstDayOfYear(y); 0159 weekDay1 = dayOfWeek(firstDayWeek1); 0160 0161 // iso 8601: week 1 is the first containing thursday and week starts on monday 0162 if (weekDay1 > 4 /*Thursday*/) { 0163 firstDayWeek1 = q->addDays(firstDayWeek1, daysInWeek() - weekDay1 + 1); // next monday 0164 } 0165 0166 dayOfWeek1InYear = dayOfYear(firstDayWeek1); 0167 0168 // our date in prev year's week 0169 if (dayOfYear(date) < dayOfWeek1InYear) { 0170 if (yearNum) { 0171 *yearNum = addYears(y, - 1); 0172 } 0173 return isoWeeksInYear(addYears(y, - 1)); 0174 } 0175 0176 // let's check if its last week belongs to next year 0177 lastDay = lastDayOfYear(y); 0178 0179 // if our date is in last week && 1st week in next year has thursday 0180 if ((dayOfYear(date) >= daysInYear(y) - dayOfWeek(lastDay) + 1) 0181 && dayOfWeek(lastDay) < 4) { 0182 if (yearNum) { 0183 * yearNum = addYears(y, 1); 0184 } 0185 week = 1; 0186 } else { 0187 // To calculate properly the number of weeks from day a to x let's make a day 1 of week 0188 if (weekDay1 < 5) { 0189 firstDayWeek1 = q->addDays(firstDayWeek1, -(weekDay1 - 1)); 0190 } 0191 0192 if (yearNum) { 0193 * yearNum = y; 0194 } 0195 0196 week = firstDayWeek1.daysTo(date) / daysInWeek() + 1; 0197 } 0198 0199 return week; 0200 } 0201 0202 int KCalendarSystemPrivate::regularWeekNumber(const QDate &date, int weekStartDay, int firstWeekNumber, int *weekYear) const 0203 { 0204 int y, m, d; 0205 q->julianDayToDate(date.toJulianDay(), y, m, d); 0206 0207 int firstWeekDayOffset = (dayOfWeek(date) - weekStartDay + daysInWeek()) % daysInWeek(); 0208 int dayInYear = date.toJulianDay() - firstDayOfYear(y).toJulianDay(); // 0 indexed 0209 int week = ((dayInYear - firstWeekDayOffset + daysInWeek()) / daysInWeek()); 0210 0211 if (dayOfWeek(firstDayOfYear(y)) != weekStartDay) { 0212 week = week + firstWeekNumber; 0213 } 0214 0215 if (week < 1) { 0216 y = y - 1; 0217 week = regularWeeksInYear(y, weekStartDay, firstWeekNumber); 0218 } 0219 0220 if (weekYear) { 0221 *weekYear = y; 0222 } 0223 0224 return week; 0225 } 0226 0227 int KCalendarSystemPrivate::simpleWeekNumber(const QDate &date, int *yearNum) const 0228 { 0229 int y, m, d; 0230 q->julianDayToDate(date.toJulianDay(), y, m, d); 0231 if (yearNum) { 0232 *yearNum = y; 0233 } 0234 return ((date.toJulianDay() - firstDayOfYear(y).toJulianDay()) / daysInWeek()) + 1; 0235 } 0236 0237 int KCalendarSystemPrivate::isoWeeksInYear(int year) const 0238 { 0239 QDate lastDayOfThisYear = lastDayOfYear(year); 0240 0241 int weekYear = year; 0242 int lastWeekInThisYear = isoWeekNumber(lastDayOfThisYear, &weekYear); 0243 0244 // If error, or the last day of the year is in the first week of next year use the week before 0245 if (lastWeekInThisYear < 1 || weekYear != year) { 0246 lastWeekInThisYear = isoWeekNumber(q->addDays(lastDayOfThisYear, -7), &weekYear); 0247 } 0248 0249 return lastWeekInThisYear; 0250 } 0251 0252 int KCalendarSystemPrivate::regularWeeksInYear(int year, int weekStartDay, int firstWeekNumber) const 0253 { 0254 return regularWeekNumber(lastDayOfYear(year), weekStartDay, firstWeekNumber, nullptr); 0255 } 0256 0257 int KCalendarSystemPrivate::simpleWeeksInYear(int year) const 0258 { 0259 return simpleWeekNumber(lastDayOfYear(year), nullptr); 0260 } 0261 0262 // Reimplement if special maths handling required, e.g. Hebrew. 0263 // Works for calendars with constant number of months, or where leap month is last month of year 0264 // Will not work for Hebrew or others where leap month is inserted in middle of year 0265 void KCalendarSystemPrivate::dateDifference(const QDate &fromDate, const QDate &toDate, 0266 int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const 0267 { 0268 // This could be optimised a little but is left in full as it's easier to understand 0269 int dy = 0; 0270 int dm = 0; 0271 int dd = 0; 0272 int dir = 1; 0273 0274 if (toDate < fromDate) { 0275 dateDifference(toDate, fromDate, &dy, &dm, &dd, nullptr); 0276 dir = -1; 0277 } else if (toDate > fromDate) { 0278 0279 int fromYear = q->year(fromDate); 0280 int toYear = q->year(toDate); 0281 int fromMonth = q->month(fromDate); 0282 int toMonth = q->month(toDate); 0283 int fromDay = q->day(fromDate); 0284 int toDay = q->day(toDate); 0285 0286 int monthsInPrevYear = monthsInYear(addYears(toYear, -1)); 0287 int daysInPrevMonth = q->daysInMonth(q->addMonths(toDate, -1)); 0288 int daysInFromMonth = daysInMonth(fromYear, fromMonth); 0289 int daysInToMonth = daysInMonth(toYear, toMonth); 0290 0291 // Calculate years difference 0292 if (toYear == fromYear) { 0293 dy = 0; 0294 } else if (toMonth > fromMonth) { 0295 dy = differenceYearNumbers(fromYear, toYear); 0296 } else if (toMonth < fromMonth) { 0297 dy = differenceYearNumbers(fromYear, toYear) - 1; 0298 } else { // toMonth == fromMonth 0299 // Allow for last day of month to last day of month and leap days 0300 // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years 0301 if ((toDay >= fromDay) || (fromDay == daysInFromMonth && toDay == daysInToMonth)) { 0302 dy = differenceYearNumbers(fromYear, toYear); 0303 } else { 0304 dy = differenceYearNumbers(fromYear, toYear) - 1; 0305 } 0306 } 0307 0308 // Calculate months and days difference 0309 if (toDay >= fromDay) { 0310 dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear; 0311 dd = toDay - fromDay; 0312 } else { // toDay < fromDay 0313 // Allow for last day of month to last day of month and leap days 0314 // e.g. 2010-03-31 to 2010-04-30 is 1 month 0315 // 2000-02-29 to 2001-02-28 is 1 year 0316 // 2000-02-29 to 2001-03-01 is 1 year 1 day 0317 int prevMonth = q->month(q->addMonths(toDate, -1)); 0318 if (fromDay == daysInFromMonth && toDay == daysInToMonth) { 0319 dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear; 0320 dd = 0; 0321 } else if (prevMonth == fromMonth && daysInPrevMonth < daysInFromMonth) { 0322 // Special case where fromDate = leap day and toDate in month following but non-leap year 0323 // e.g. 2000-02-29 to 2001-03-01 needs to use 29 to calculate day number not 28 0324 dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear; 0325 dd = (daysInFromMonth + toDay - fromDay) % daysInFromMonth; 0326 } else { 0327 dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear; 0328 dd = (daysInPrevMonth + toDay - fromDay) % daysInPrevMonth; 0329 } 0330 } 0331 0332 } 0333 0334 // Only return values if we have a valid pointer 0335 if (yearsDiff) { 0336 *yearsDiff = dy; 0337 } 0338 if (monthsDiff) { 0339 *monthsDiff = dm; 0340 } 0341 if (daysDiff) { 0342 *daysDiff = dd; 0343 } 0344 if (direction) { 0345 *direction = dir; 0346 } 0347 } 0348 0349 // Reimplement if special maths handling required, e.g. Hebrew 0350 // Allows for calendars with leap months at end of year but not during year 0351 int KCalendarSystemPrivate::yearsDifference(const QDate &fromDate, const QDate &toDate) const 0352 { 0353 // This could be optimised a little but is left in full as it's easier to understand 0354 // Alternatively could just call dateDifference(), but this is slightly more efficient 0355 0356 if (toDate < fromDate) { 0357 return 0 - yearsDifference(toDate, fromDate); 0358 } 0359 0360 if (toDate == fromDate) { 0361 return 0; 0362 } 0363 0364 int fromYear = q->year(fromDate); 0365 int toYear = q->year(toDate); 0366 0367 if (toYear == fromYear) { 0368 return 0; 0369 } 0370 0371 int fromMonth = q->month(fromDate); 0372 int toMonth = q->month(toDate); 0373 0374 if (toMonth > fromMonth) { 0375 return differenceYearNumbers(fromYear, toYear); 0376 } 0377 0378 if (toMonth < fromMonth) { 0379 return differenceYearNumbers(fromYear, toYear) - 1; 0380 } 0381 0382 // toMonth == fromMonth 0383 int fromDay = q->day(fromDate); 0384 int toDay = q->day(toDate); 0385 0386 // Adjust for month numbers in from and to year 0387 // Allow for last day of month to last day of month and leap days 0388 // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years 0389 if ((toDay >= fromDay) || 0390 (fromDay == daysInMonth(fromYear, fromMonth) && 0391 toDay == daysInMonth(toYear, toMonth))) { 0392 return differenceYearNumbers(fromYear, toYear); 0393 } else { 0394 return differenceYearNumbers(fromYear, toYear) - 1; 0395 } 0396 0397 } 0398 0399 // Reimplement if special maths handling required, e.g. maybe Hebrew? 0400 // Allows for calendars with leap months 0401 int KCalendarSystemPrivate::monthsDifference(const QDate &fromDate, const QDate &toDate) const 0402 { 0403 if (toDate < fromDate) { 0404 return 0 - monthsDifference(toDate, fromDate); 0405 } 0406 0407 if (toDate == fromDate) { 0408 return 0; 0409 } 0410 0411 int fromYear = q->year(fromDate); 0412 int toYear = q->year(toDate); 0413 int fromMonth = q->month(fromDate); 0414 int toMonth = q->month(toDate); 0415 int fromDay = q->day(fromDate); 0416 int toDay = q->day(toDate); 0417 0418 int monthsInPreceedingYears; 0419 0420 // Calculate number of months in full years preceding toYear 0421 if (toYear == fromYear) { 0422 monthsInPreceedingYears = 0; 0423 } else if (hasLeapMonths()) { 0424 monthsInPreceedingYears = 0; 0425 for (int y = fromYear; y < toYear; y = addYears(y, 1)) { 0426 monthsInPreceedingYears = monthsInPreceedingYears + monthsInYear(y); 0427 } 0428 } else { 0429 monthsInPreceedingYears = differenceYearNumbers(fromYear, toYear) * monthsInYear(toYear); 0430 } 0431 0432 // Adjust for months in from and to year 0433 // Allow for last day of month to last day of month and leap days 0434 // e.g. 2010-03-31 to 2010-04-30 is 1 month not 0 months 0435 // also 2000-02-29 to 2001-02-28 is 12 months not 11 months 0436 if ((toDay >= fromDay) || 0437 (fromDay == daysInMonth(fromYear, fromMonth) && 0438 toDay == daysInMonth(toYear, toMonth))) { 0439 return monthsInPreceedingYears + toMonth - fromMonth; 0440 } else { 0441 return monthsInPreceedingYears + toMonth - fromMonth - 1; 0442 } 0443 } 0444 0445 // Reimplement if special string to integer handling required, e.g. Hebrew. 0446 // Peel a number off the front of a string which may have other trailing chars after the number 0447 // Stop either at either maxLength, eos, or first non-digit char 0448 int KCalendarSystemPrivate::integerFromString(const QString &string, int maxLength, int &readLength) const 0449 { 0450 int value = -1; 0451 int position = 0; 0452 readLength = 0; 0453 bool ok = false; 0454 0455 if (maxLength < 0) { 0456 maxLength = string.length(); 0457 } 0458 0459 while (position < string.length() && 0460 position < maxLength && 0461 string.at(position).isDigit()) { 0462 position++; 0463 } 0464 0465 if (position > 0) { 0466 value = string.left(position).toInt(&ok); 0467 if (ok) { 0468 readLength = position; 0469 } else { 0470 value = -1; 0471 } 0472 } 0473 0474 return value; 0475 } 0476 0477 // Reimplement if special integer to string handling required, e.g. Hebrew. 0478 // Utility to convert an integer into the correct display string form 0479 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar) const 0480 { 0481 return stringFromInteger(number, padWidth, padChar, q->locale()->dateTimeDigitSet()); 0482 } 0483 0484 // Reimplement if special integer to string handling required, e.g. Hebrew. 0485 // Utility to convert an integer into the correct display string form 0486 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar, KLocale::DigitSet digitSet) const 0487 { 0488 if (padChar == QLatin1Char('\0') || padWidth == 0) { 0489 return q->locale()->convertDigits(QString::number(number), digitSet); 0490 } else { 0491 return q->locale()->convertDigits(QString::number(number).rightJustified(padWidth, padChar), digitSet); 0492 } 0493 } 0494 0495 // Utility to correctly add years to a year number because some systems such as 0496 // Julian and Gregorian calendars don't have a year 0 0497 int KCalendarSystemPrivate::addYears(int originalYear, int addYears) const 0498 { 0499 int newYear = originalYear + addYears; 0500 0501 if (!hasYearZero()) { 0502 if (originalYear > 0 && newYear <= 0) { 0503 newYear = newYear - 1; 0504 } else if (originalYear < 0 && newYear >= 0) { 0505 newYear = newYear + 1; 0506 } 0507 } 0508 0509 return newYear; 0510 } 0511 0512 // Utility to correctly return number of years between two year numbers because some systems such as 0513 // Julian and Gregorian calendars don't have a year 0 0514 int KCalendarSystemPrivate::differenceYearNumbers(int fromYear, int toYear) const 0515 { 0516 int dy = toYear - fromYear; 0517 0518 if (!hasYearZero()) { 0519 if (toYear > 0 && fromYear < 0) { 0520 dy = dy - 1; 0521 } else if (toYear < 0 && fromYear > 0) { 0522 dy = dy + 1; 0523 } 0524 } 0525 0526 return dy; 0527 } 0528 0529 QString KCalendarSystemPrivate::simpleDateString(const QString &str) const 0530 { 0531 QString newStr; 0532 newStr.reserve(str.length()); 0533 for (int i = 0; i < str.length(); i++) { 0534 if (str.at(i).isLetterOrNumber()) { 0535 newStr.append(str.at(i)); 0536 } else { 0537 newStr.append(QLatin1Char(' ')); 0538 } 0539 } 0540 0541 return newStr.simplified(); 0542 } 0543 0544 // If we ever want to support a calendar system with another week length,this 0545 // method can be changed to virtual. Doing so will, however, likely break some 0546 // code, so don't do that without testing and fixing at least all of KDE SC. 0547 int KCalendarSystemPrivate::daysInWeek() const 0548 { 0549 return 7; 0550 } 0551 0552 int KCalendarSystemPrivate::dayOfYear(const QDate &date) const 0553 { 0554 qint64 jdFirstDayOfYear; 0555 int y, m, d; 0556 q->julianDayToDate(date.toJulianDay(), y, m, d); 0557 q->dateToJulianDay(y, 1, 1, jdFirstDayOfYear); 0558 //Take the jd of the given date, and subtract the jd of the first day of that year 0559 return (date.toJulianDay() - jdFirstDayOfYear + 1); 0560 } 0561 0562 // This assumes all calendar systems agree on the day of week for a given 0563 // julian day number. That is true of all current calendar systems. If we 0564 // ever want to support one for which it isn't this implementation can be 0565 // changed. Doing so will, however, likely break some code, so don't do that 0566 // without testing and fixing at least all of KDE SC. 0567 int KCalendarSystemPrivate::dayOfWeek(const QDate &date) const 0568 { 0569 return date.dayOfWeek(); 0570 } 0571 0572 QDate KCalendarSystemPrivate::firstDayOfYear(int year) const 0573 { 0574 qint64 jd; 0575 q->dateToJulianDay(year, 1, 1, jd); 0576 return QDate::fromJulianDay(jd); 0577 } 0578 0579 QDate KCalendarSystemPrivate::lastDayOfYear(int year) const 0580 { 0581 qint64 jd; 0582 q->dateToJulianDay(year, 1, 1, jd); 0583 jd = jd + daysInYear(year) - 1; 0584 return QDate::fromJulianDay(jd); 0585 } 0586 0587 QDate KCalendarSystemPrivate::firstDayOfMonth(int year, int month) const 0588 { 0589 qint64 jd; 0590 q->dateToJulianDay(year, month, 1, jd); 0591 return QDate::fromJulianDay(jd); 0592 } 0593 0594 QDate KCalendarSystemPrivate::lastDayOfMonth(int year, int month) const 0595 { 0596 qint64 jd; 0597 q->dateToJulianDay(year, month, 1, jd); 0598 jd = jd + daysInMonth(year, month) - 1; 0599 return QDate::fromJulianDay(jd); 0600 } 0601 0602 const KLocale *KCalendarSystemPrivate::locale() const 0603 { 0604 if (m_locale) { 0605 return m_locale; 0606 } else { 0607 return KLocale::global(); 0608 } 0609 } 0610 0611 QList<KCalendarEra> *KCalendarSystemPrivate::eraList() const 0612 { 0613 return m_eraList; 0614 } 0615 0616 KCalendarEra KCalendarSystemPrivate::era(const QDate &eraDate) const 0617 { 0618 for (int i = m_eraList->count() - 1; i >= 0; --i) { 0619 if (m_eraList->at(i).isInEra(eraDate)) { 0620 return m_eraList->at(i); 0621 } 0622 } 0623 return KCalendarEra(); 0624 } 0625 0626 KCalendarEra KCalendarSystemPrivate::era(const QString &eraName, int yearInEra) const 0627 { 0628 Q_UNUSED(yearInEra) 0629 0630 for (int i = m_eraList->count() - 1; i >= 0; --i) { 0631 KCalendarEra era = m_eraList->at(i); 0632 if (era.name(KLocale::LongName).toLower() == eraName.toLower() || 0633 era.name(KLocale::ShortName).toLower() == eraName.toLower()) { 0634 return era; 0635 } 0636 } 0637 return KCalendarEra(); 0638 } 0639 0640 void KCalendarSystemPrivate::loadEraList(const KConfigGroup &cg) 0641 { 0642 delete m_eraList; 0643 m_eraList = new QList<KCalendarEra>; 0644 QString eraKey = QString::fromLatin1("Era1"); 0645 int i = 1; 0646 while (cg.hasKey(eraKey)) { 0647 QString eraEntry = cg.readEntry(eraKey, QString()); 0648 if (!eraEntry.isEmpty()) { 0649 // Based on LC_TIME, but different! 0650 // Includes long and short names, uses ISO fomat dates 0651 // e.g. +:1:0001-01-01:9999-12-31:Anno Domini:AD:%EC %Ey 0652 QChar direction = eraEntry.section(QLatin1Char(':'), 0, 0).at(0); 0653 QDate startDate, endDate; 0654 int startYear; 0655 QString buffer = eraEntry.section(QLatin1Char(':'), 2, 2); 0656 if (buffer.isEmpty()) { 0657 if (direction == QLatin1Char('-')) { 0658 startDate = q->latestValidDate(); 0659 } else { 0660 startDate = q->earliestValidDate(); 0661 } 0662 } else { 0663 startDate = q->readDate(buffer, KLocale::IsoFormat); 0664 } 0665 if (q->isValid(startDate)) { 0666 startYear = q->year(startDate); 0667 } else { 0668 startYear = eraEntry.section(QLatin1Char(':'), 1, 1).toInt(); //Use offset 0669 } 0670 0671 buffer = eraEntry.section(QLatin1Char(':'), 3, 3); 0672 if (buffer.isEmpty()) { 0673 if (direction == QLatin1Char('-')) { 0674 endDate = q->earliestValidDate(); 0675 } else { 0676 endDate = q->latestValidDate(); 0677 } 0678 } else { 0679 endDate = q->readDate(buffer, KLocale::IsoFormat); 0680 } 0681 addEra(direction.toLatin1(), eraEntry.section(QLatin1Char(':'), 1, 1).toInt(), 0682 startDate, startYear, endDate, eraEntry.section(QLatin1Char(':'), 4, 4), 0683 eraEntry.section(QLatin1Char(':'), 5, 5), eraEntry.section(QLatin1Char(':'), 6)); 0684 } 0685 ++i; 0686 eraKey = QString::fromLatin1("Era%1").arg(i); 0687 } 0688 0689 if (m_eraList->isEmpty()) { 0690 loadDefaultEraList(); 0691 } 0692 } 0693 0694 void KCalendarSystemPrivate::addEra(char direction, int offset, 0695 const QDate &startDate, int startYear, const QDate &endDate, 0696 const QString &name, const QString &shortName, 0697 const QString &format) 0698 { 0699 KCalendarEra newEra; 0700 0701 newEra.m_sequence = m_eraList->count() + 1; 0702 if (direction == '-') { 0703 newEra.m_direction = -1; 0704 } else { 0705 newEra.m_direction = 1; 0706 } 0707 newEra.m_offset = offset; 0708 newEra.m_startDate = startDate; 0709 newEra.m_startYear = startYear; 0710 newEra.m_endDate = endDate; 0711 newEra.m_longName = name; 0712 newEra.m_shortName = shortName; 0713 newEra.m_format = format; 0714 0715 m_eraList->append(newEra); 0716 } 0717 0718 int KCalendarSystemPrivate::shortYearWindowStartYear() const 0719 { 0720 return m_shortYearWindowStartYear; 0721 } 0722 0723 int KCalendarSystemPrivate::applyShortYearWindow(int inputYear) const 0724 { 0725 if (inputYear >= 0 && inputYear <= 99) { 0726 int shortStartYear = m_shortYearWindowStartYear % 100; 0727 int yearOffset = m_shortYearWindowStartYear - shortStartYear; 0728 if (inputYear >= shortStartYear) { 0729 return inputYear + yearOffset; 0730 } else { 0731 return inputYear + yearOffset + 100; 0732 } 0733 } else { 0734 return inputYear; 0735 } 0736 } 0737 0738 void KCalendarSystemPrivate::loadShortYearWindowStartYear(const KConfigGroup &cg) 0739 { 0740 // Default to 2000 for backwards compatibility 0741 // as that's the old readDate() default value 0742 int startYear = 2000; 0743 if (cg.exists()) { 0744 startYear = cg.readEntry("ShortYearWindowStartYear", 2000); 0745 } 0746 m_shortYearWindowStartYear = startYear; 0747 } 0748 0749 KSharedConfig::Ptr KCalendarSystemPrivate::config() 0750 { 0751 if (m_config == KSharedConfig::Ptr()) { 0752 return KSharedConfig::openConfig(); 0753 } else { 0754 return m_config; 0755 } 0756 } 0757 0758 void KCalendarSystemPrivate::loadConfig(const QString &calendarType) 0759 { 0760 KConfigGroup localeGroup(config(), QString::fromLatin1("Locale")); 0761 KConfigGroup calendarGroup = localeGroup.group(QString::fromLatin1("KCalendarSystem %1").arg(calendarType)); 0762 loadEraList(calendarGroup); 0763 loadShortYearWindowStartYear(calendarGroup); 0764 } 0765 0766 KCalendarSystem::KCalendarSystem(KCalendarSystemPrivate &dd, const KSharedConfig::Ptr config, const KLocale *locale) 0767 : d_ptr(&dd) 0768 { 0769 d_ptr->m_config = config; 0770 d_ptr->m_locale = locale; 0771 } 0772 0773 KCalendarSystem::~KCalendarSystem() 0774 { 0775 delete d_ptr; 0776 } 0777 0778 // NOT VIRTUAL - If override needed use shared-d 0779 QString KCalendarSystem::calendarLabel() const 0780 { 0781 return KCalendarSystem::calendarLabel(calendarSystem()); 0782 } 0783 0784 bool KCalendarSystem::isValid(int year, int month, int day) const 0785 { 0786 Q_D(const KCalendarSystem); 0787 0788 return year >= d->earliestValidYear() && year <= d->latestValidYear() && (d->hasYearZero() || year != 0) && 0789 month >= 1 && month <= d->monthsInYear(year) && 0790 day >= 1 && day <= d->daysInMonth(year, month); 0791 } 0792 0793 bool KCalendarSystem::isValid(int year, int dayOfYear) const 0794 { 0795 Q_D(const KCalendarSystem); 0796 0797 return (isValid(year, 1, 1) && dayOfYear > 0 && dayOfYear <= d->daysInYear(year)); 0798 } 0799 0800 bool KCalendarSystem::isValid(const QString &eraName, int yearInEra, int month, int day) const 0801 { 0802 Q_D(const KCalendarSystem); 0803 0804 KCalendarEra era = d->era(eraName, yearInEra); 0805 return (era.isValid() && isValid(era.year(yearInEra), month, day)); 0806 } 0807 0808 // NOT VIRTUAL - If override needed use shared-d 0809 bool KCalendarSystem::isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const 0810 { 0811 Q_D(const KCalendarSystem); 0812 0813 //Tests Year value in standard YMD isValid() 0814 if (!isValid(year, 1, 1)) { 0815 return false; 0816 } 0817 0818 //Test Week Number falls in valid range for this year 0819 int weeksInThisYear = weeksInYear(year); 0820 if (isoWeekNumber < 1 || isoWeekNumber > weeksInThisYear) { 0821 return false; 0822 } 0823 0824 //Test Day of Week Number falls in valid range 0825 if (dayOfIsoWeek < 1 || dayOfIsoWeek > d->daysInWeek()) { 0826 return false; 0827 } 0828 0829 //If not in earliest or latest years then all OK 0830 //Otherwise need to check don't fall into previous or next year that would be invalid 0831 if (year == d->earliestValidYear() && isoWeekNumber == 1) { 0832 //If firstDayOfYear falls on or before Thursday then firstDayOfYear falls in week 1 this 0833 //year and if wanted dayOfIsoWeek falls before firstDayOfYear then falls in previous year 0834 //and so in invalid year 0835 int dowFirstDay = dayOfWeek(d->firstDayOfYear(year)); 0836 if (dowFirstDay <= 4 && dayOfIsoWeek < dowFirstDay) { 0837 return false; 0838 } 0839 } else if (year == d->latestValidYear() && isoWeekNumber == weeksInThisYear) { 0840 //If lastDayOfYear falls on or after Thursday then lastDayOfYear falls in last week this 0841 //year and if wanted dayOfIsoWeek falls after lastDayOfYear then falls in next year 0842 //and so in invalid year 0843 int dowLastDay = dayOfWeek(d->lastDayOfYear(year)); 0844 if (dowLastDay >= 4 && dayOfIsoWeek > dowLastDay) { 0845 return false; 0846 } 0847 } 0848 0849 return true; 0850 } 0851 0852 bool KCalendarSystem::setDate(QDate &date, int year, int month, int day) const 0853 { 0854 date = QDate(); 0855 0856 if (isValid(year, month, day)) { 0857 qint64 jd; 0858 dateToJulianDay(year, month, day, jd); 0859 QDate calcDate = QDate::fromJulianDay(jd); 0860 0861 if (isValid(calcDate)) { 0862 date = calcDate; 0863 return true; 0864 } 0865 } 0866 0867 return false; 0868 } 0869 0870 // NOT VIRTUAL - If override needed use shared-d 0871 bool KCalendarSystem::setDate(QDate &date, int year, int dayOfYear) const 0872 { 0873 date = QDate(); 0874 0875 if (isValid(year, dayOfYear)) { 0876 qint64 jd; 0877 dateToJulianDay(year, 1, 1, jd); 0878 QDate calcDate = QDate::fromJulianDay(jd + dayOfYear - 1); 0879 if (isValid(calcDate)) { 0880 date = calcDate; 0881 return true; 0882 } 0883 } 0884 0885 return false; 0886 } 0887 0888 // NOT VIRTUAL - If override needed use shared-d 0889 bool KCalendarSystem::setDate(QDate &date, QString eraName, int yearInEra, int month, int day) const 0890 { 0891 Q_D(const KCalendarSystem); 0892 0893 KCalendarEra era = d->era(eraName, yearInEra); 0894 return (era.isValid() && setDate(date, era.year(yearInEra), month, day)); 0895 } 0896 0897 // NOT VIRTUAL - If override needed use shared-d 0898 bool KCalendarSystem::setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const 0899 { 0900 Q_D(const KCalendarSystem); 0901 0902 date = QDate(); 0903 0904 if (isValidIsoWeekDate(year, isoWeekNumber, dayOfIsoWeek)) { 0905 0906 QDate calcDate = d->firstDayOfYear(year); 0907 int dowFirstDayOfYear = dayOfWeek(calcDate); 0908 0909 int daysToAdd = (d->daysInWeek() * (isoWeekNumber - 1)) + dayOfIsoWeek; 0910 0911 if (dowFirstDayOfYear <= 4) { 0912 calcDate = calcDate.addDays(daysToAdd - dowFirstDayOfYear); 0913 } else { 0914 calcDate = calcDate.addDays(daysInWeek(calcDate) + daysToAdd - dowFirstDayOfYear); 0915 } 0916 0917 if (isValid(calcDate)) { 0918 date = calcDate; 0919 return true; 0920 } 0921 } 0922 0923 return false; 0924 } 0925 0926 // NOT VIRTUAL - If override needed use shared-d 0927 void KCalendarSystem::getDate(const QDate date, int *year, int *month, int *day) const 0928 { 0929 int y, m, d; 0930 0931 if (isValid(date)) { 0932 julianDayToDate(date.toJulianDay(), y, m, d); 0933 } else { 0934 y = 0; // How do you denote invalid year when we support -ve years? 0935 m = 0; 0936 d = 0; 0937 } 0938 0939 if (year) { 0940 *year = y; 0941 } 0942 if (month) { 0943 *month = m; 0944 } 0945 if (day) { 0946 *day = d; 0947 } 0948 0949 } 0950 0951 int KCalendarSystem::year(const QDate &date) const 0952 { 0953 if (isValid(date)) { 0954 int year, month, day; 0955 0956 julianDayToDate(date.toJulianDay(), year, month, day); 0957 0958 return year; 0959 } 0960 0961 return 0; // How do you denote invalid year when we support -ve years? 0962 } 0963 0964 int KCalendarSystem::month(const QDate &date) const 0965 { 0966 if (isValid(date)) { 0967 int year, month, day; 0968 0969 julianDayToDate(date.toJulianDay(), year, month, day); 0970 0971 return month; 0972 } 0973 0974 return 0; 0975 } 0976 0977 int KCalendarSystem::day(const QDate &date) const 0978 { 0979 if (isValid(date)) { 0980 int year, month, day; 0981 0982 julianDayToDate(date.toJulianDay(), year, month, day); 0983 0984 return day; 0985 } 0986 0987 return 0; 0988 } 0989 0990 // NOT VIRTUAL - If override needed use shared-d 0991 QString KCalendarSystem::eraName(const QDate &date, StringFormat format) const 0992 { 0993 Q_D(const KCalendarSystem); 0994 0995 if (isValid(date)) { 0996 if (format == LongFormat) { 0997 return d->era(date).name(KLocale::LongName); 0998 } else { 0999 return d->era(date).name(KLocale::ShortName); 1000 } 1001 } 1002 1003 return QString(); 1004 } 1005 1006 // NOT VIRTUAL - If override needed use shared-d 1007 QString KCalendarSystem::eraYear(const QDate &date, StringFormat format) const 1008 { 1009 Q_UNUSED(format) 1010 Q_D(const KCalendarSystem); 1011 1012 if (isValid(date)) { 1013 return formatDate(date, d->era(date).format()); 1014 } 1015 1016 return QString(); 1017 } 1018 1019 // NOT VIRTUAL - If override needed use shared-d 1020 int KCalendarSystem::yearInEra(const QDate &date) const 1021 { 1022 Q_D(const KCalendarSystem); 1023 1024 if (isValid(date)) { 1025 return d->era(date).yearInEra(year(date)); 1026 } 1027 1028 return -1; 1029 } 1030 1031 // NOT VIRTUAL - If override needed use shared-d 1032 QList<KCalendarEra> *KCalendarSystem::eraList() const 1033 { 1034 Q_D(const KCalendarSystem); 1035 1036 return d->eraList(); 1037 } 1038 1039 // NOT VIRTUAL - If override needed use shared-d 1040 KCalendarEra KCalendarSystem::era(const QDate &eraDate) const 1041 { 1042 Q_D(const KCalendarSystem); 1043 1044 return d->era(eraDate); 1045 } 1046 1047 // NOT VIRTUAL - If override needed use shared-d 1048 KCalendarEra KCalendarSystem::era(const QString &eraName, int yearInEra) const 1049 { 1050 Q_D(const KCalendarSystem); 1051 1052 return d->era(eraName, yearInEra); 1053 } 1054 1055 QDate KCalendarSystem::addYears(const QDate &date, int numYears) const 1056 { 1057 Q_D(const KCalendarSystem); 1058 1059 if (isValid(date)) { 1060 1061 int originalYear, originalMonth, originalDay; 1062 julianDayToDate(date.toJulianDay(), originalYear, originalMonth, originalDay); 1063 1064 int newYear = d->addYears(originalYear, numYears); 1065 int newMonth = originalMonth; 1066 int newDay = originalDay; 1067 1068 //Adjust day number if new month has fewer days than old month 1069 int daysInNewMonth = d->daysInMonth(newYear, newMonth); 1070 if (daysInNewMonth < originalDay) { 1071 newDay = daysInNewMonth; 1072 } 1073 1074 QDate newDate; 1075 setDate(newDate, newYear, newMonth, newDay); 1076 return newDate; 1077 1078 } 1079 1080 return QDate(); 1081 } 1082 1083 QDate KCalendarSystem::addMonths(const QDate &date, int numMonths) const 1084 { 1085 Q_D(const KCalendarSystem); 1086 1087 if (isValid(date)) { 1088 1089 int originalYear, originalMonth, originalDay; 1090 julianDayToDate(date.toJulianDay(), originalYear, originalMonth, originalDay); 1091 1092 int monthsInOriginalYear = d->monthsInYear(originalYear); 1093 1094 int newYear = d->addYears(originalYear, (originalMonth + numMonths) / monthsInOriginalYear); 1095 int newMonth = (originalMonth + numMonths) % monthsInOriginalYear; 1096 int newDay = originalDay; 1097 1098 if (newMonth == 0) { 1099 newYear = d->addYears(newYear, - 1); 1100 newMonth = monthsInOriginalYear; 1101 } 1102 if (newMonth < 0) { 1103 newYear = d->addYears(newYear, - 1); 1104 newMonth = newMonth + monthsInOriginalYear; 1105 } 1106 1107 //Adjust day number if new month has fewer days than old month 1108 int daysInNewMonth = d->daysInMonth(newYear, newMonth); 1109 if (daysInNewMonth < originalDay) { 1110 newDay = daysInNewMonth; 1111 } 1112 1113 QDate newDate; 1114 setDate(newDate, newYear, newMonth, newDay); 1115 return newDate; 1116 1117 } 1118 1119 return QDate(); 1120 } 1121 1122 // NOT VIRTUAL - Uses shared-d instead 1123 void KCalendarSystem::dateDifference(const QDate &fromDate, const QDate &toDate, 1124 int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const 1125 { 1126 Q_D(const KCalendarSystem); 1127 1128 if (isValid(fromDate) && isValid(toDate)) { 1129 d->dateDifference(fromDate, toDate, yearsDiff, monthsDiff, daysDiff, direction); 1130 } 1131 } 1132 1133 // NOT VIRTUAL - Uses shared-d instead 1134 int KCalendarSystem::yearsDifference(const QDate &fromDate, const QDate &toDate) const 1135 { 1136 Q_D(const KCalendarSystem); 1137 1138 if (isValid(fromDate) && isValid(toDate)) { 1139 return d->yearsDifference(fromDate, toDate); 1140 } 1141 1142 return 0; 1143 } 1144 1145 // NOT VIRTUAL - Uses shared-d instead 1146 int KCalendarSystem::monthsDifference(const QDate &fromDate, const QDate &toDate) const 1147 { 1148 Q_D(const KCalendarSystem); 1149 1150 if (isValid(fromDate) && isValid(toDate)) { 1151 return d->monthsDifference(fromDate, toDate); 1152 } 1153 1154 return 0; 1155 } 1156 1157 int KCalendarSystem::monthsInYear(const QDate &date) const 1158 { 1159 Q_D(const KCalendarSystem); 1160 1161 if (isValid(date)) { 1162 return d->monthsInYear(year(date)); 1163 } 1164 1165 return -1; 1166 } 1167 1168 int KCalendarSystem::monthsInYear(int year) const 1169 { 1170 Q_D(const KCalendarSystem); 1171 1172 if (isValid(year, 1, 1)) { 1173 return d->monthsInYear(year); 1174 } 1175 1176 return -1; 1177 } 1178 1179 int KCalendarSystem::weeksInYear(int year, KLocale::WeekNumberSystem weekNumberSystem) const 1180 { 1181 Q_D(const KCalendarSystem); 1182 1183 if (!isValid(year, 1, 1)) { 1184 return -1; 1185 } 1186 1187 switch (weekNumberSystem) { 1188 case KLocale::IsoWeekNumber: 1189 return d->isoWeeksInYear(year); 1190 case KLocale::FirstFullWeek: 1191 return d->regularWeeksInYear(year, locale()->weekStartDay(), 0); 1192 case KLocale::FirstPartialWeek: 1193 return d->regularWeeksInYear(year, locale()->weekStartDay(), 1); 1194 case KLocale::SimpleWeek: 1195 return d->simpleWeeksInYear(year); 1196 case KLocale::DefaultWeekNumber: 1197 default: 1198 return weeksInYear(year, locale()->weekNumberSystem()); 1199 } 1200 } 1201 1202 int KCalendarSystem::daysInYear(const QDate &date) const 1203 { 1204 Q_D(const KCalendarSystem); 1205 1206 if (isValid(date)) { 1207 return d->daysInYear(year(date)); 1208 } 1209 1210 return -1; 1211 } 1212 1213 int KCalendarSystem::daysInYear(int year) const 1214 { 1215 Q_D(const KCalendarSystem); 1216 1217 if (isValid(year, 1, 1)) { 1218 return d->daysInYear(year); 1219 } 1220 1221 return -1; 1222 } 1223 1224 int KCalendarSystem::daysInMonth(const QDate &date) const 1225 { 1226 Q_D(const KCalendarSystem); 1227 1228 if (isValid(date)) { 1229 int year, month, day; 1230 julianDayToDate(date.toJulianDay(), year, month, day); 1231 return d->daysInMonth(year, month); 1232 } 1233 1234 return -1; 1235 } 1236 1237 int KCalendarSystem::daysInMonth(int year, int month) const 1238 { 1239 Q_D(const KCalendarSystem); 1240 1241 if (isValid(year, month, 1)) { 1242 return d->daysInMonth(year, month); 1243 } 1244 1245 return -1; 1246 } 1247 1248 // If ever changed to depend on the date, a lot of code will break. 1249 // Don't do that without testing and fixing at least all of KDE SC. 1250 int KCalendarSystem::daysInWeek(const QDate &date) const 1251 { 1252 Q_UNUSED(date) 1253 Q_D(const KCalendarSystem); 1254 return d->daysInWeek(); 1255 } 1256 1257 int KCalendarSystem::dayOfYear(const QDate &date) const 1258 { 1259 Q_D(const KCalendarSystem); 1260 1261 if (isValid(date)) { 1262 return d->dayOfYear(date); 1263 } 1264 1265 return -1; 1266 } 1267 1268 int KCalendarSystem::dayOfWeek(const QDate &date) const 1269 { 1270 Q_D(const KCalendarSystem); 1271 1272 if (isValid(date)) { 1273 return d->dayOfWeek(date); 1274 } 1275 1276 return -1; 1277 } 1278 1279 int KCalendarSystem::week(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem, int *yearNum) const 1280 { 1281 Q_D(const KCalendarSystem); 1282 1283 if (!isValid(date)) { 1284 return -1; 1285 } 1286 1287 switch (weekNumberSystem) { 1288 case KLocale::IsoWeekNumber: 1289 return d->isoWeekNumber(date, yearNum); 1290 case KLocale::FirstFullWeek: 1291 return d->regularWeekNumber(date, locale()->weekStartDay(), 0, yearNum); 1292 case KLocale::FirstPartialWeek: 1293 return d->regularWeekNumber(date, locale()->weekStartDay(), 1, yearNum); 1294 case KLocale::SimpleWeek: 1295 return d->simpleWeekNumber(date, yearNum); 1296 case KLocale::DefaultWeekNumber: 1297 default: 1298 return week(date, locale()->weekNumberSystem(), yearNum); 1299 } 1300 } 1301 1302 bool KCalendarSystem::isLeapYear(int year) const 1303 { 1304 Q_D(const KCalendarSystem); 1305 1306 if (isValid(year, 1, 1)) { 1307 return d->isLeapYear(year); 1308 } 1309 1310 return false; 1311 } 1312 1313 bool KCalendarSystem::isLeapYear(const QDate &date) const 1314 { 1315 Q_D(const KCalendarSystem); 1316 1317 if (isValid(date)) { 1318 return d->isLeapYear(year(date)); 1319 } 1320 1321 return false; 1322 } 1323 1324 // NOT VIRTUAL - If override needed use shared-d 1325 QDate KCalendarSystem::firstDayOfYear(int year) const 1326 { 1327 Q_D(const KCalendarSystem); 1328 1329 if (isValid(year, 1, 1)) { 1330 return d->firstDayOfYear(year); 1331 } 1332 1333 return QDate(); 1334 } 1335 1336 // NOT VIRTUAL - If override needed use shared-d 1337 QDate KCalendarSystem::lastDayOfYear(int year) const 1338 { 1339 Q_D(const KCalendarSystem); 1340 1341 if (isValid(year, 1, 1)) { 1342 return d->lastDayOfYear(year); 1343 } 1344 1345 return QDate(); 1346 } 1347 1348 // NOT VIRTUAL - If override needed use shared-d 1349 QDate KCalendarSystem::firstDayOfYear(const QDate &date) const 1350 { 1351 Q_D(const KCalendarSystem); 1352 1353 if (isValid(date)) { 1354 return d->firstDayOfYear(year(date)); 1355 } 1356 1357 return QDate(); 1358 } 1359 1360 // NOT VIRTUAL - If override needed use shared-d 1361 QDate KCalendarSystem::lastDayOfYear(const QDate &date) const 1362 { 1363 Q_D(const KCalendarSystem); 1364 1365 if (isValid(date)) { 1366 return d->lastDayOfYear(year(date)); 1367 } 1368 1369 return QDate(); 1370 } 1371 1372 // NOT VIRTUAL - If override needed use shared-d 1373 QDate KCalendarSystem::firstDayOfMonth(int year, int month) const 1374 { 1375 Q_D(const KCalendarSystem); 1376 1377 if (isValid(year, month, 1)) { 1378 return d->firstDayOfMonth(year, month); 1379 } 1380 1381 return QDate(); 1382 } 1383 1384 // NOT VIRTUAL - If override needed use shared-d 1385 QDate KCalendarSystem::lastDayOfMonth(int year, int month) const 1386 { 1387 Q_D(const KCalendarSystem); 1388 1389 if (isValid(year, month, 1)) { 1390 return d->lastDayOfMonth(year, month); 1391 } 1392 1393 return QDate(); 1394 } 1395 1396 // NOT VIRTUAL - If override needed use shared-d 1397 QDate KCalendarSystem::firstDayOfMonth(const QDate &date) const 1398 { 1399 Q_D(const KCalendarSystem); 1400 1401 if (isValid(date)) { 1402 int year, month; 1403 getDate(date, &year, &month, nullptr); 1404 return d->firstDayOfMonth(year, month); 1405 } 1406 1407 return QDate(); 1408 } 1409 1410 // NOT VIRTUAL - If override needed use shared-d 1411 QDate KCalendarSystem::lastDayOfMonth(const QDate &date) const 1412 { 1413 Q_D(const KCalendarSystem); 1414 1415 if (isValid(date)) { 1416 int year, month; 1417 getDate(date, &year, &month, nullptr); 1418 return d->lastDayOfMonth(year, month); 1419 } 1420 1421 return QDate(); 1422 } 1423 1424 QString KCalendarSystem::monthName(int month, int year, KCalendarSystem::MonthNameFormat format) const 1425 { 1426 Q_D(const KCalendarSystem); 1427 1428 if (!isValid(year, month, 1)) { 1429 return QString(); 1430 } 1431 1432 if (format == KCalendarSystem::NarrowName) { 1433 return d->monthName(month, year, KLocale::NarrowName, false); 1434 } 1435 1436 if (format == KCalendarSystem::ShortNamePossessive) { 1437 return d->monthName(month, year, KLocale::ShortName, true); 1438 } 1439 1440 if (format == KCalendarSystem::ShortName) { 1441 return d->monthName(month, year, KLocale::ShortName, false); 1442 } 1443 1444 if (format == KCalendarSystem::LongNamePossessive) { 1445 return d->monthName(month, year, KLocale::LongName, true); 1446 } 1447 1448 // KCalendarSystem::LongName or any other 1449 return d->monthName(month, year, KLocale::LongName, false); 1450 } 1451 1452 QString KCalendarSystem::monthName(const QDate &date, MonthNameFormat format) const 1453 { 1454 if (isValid(date)) { 1455 int year, month; 1456 getDate(date, &year, &month, nullptr); 1457 return monthName(month, year, format); 1458 } 1459 1460 return QString(); 1461 } 1462 1463 QString KCalendarSystem::weekDayName(int weekDay, KCalendarSystem::WeekDayNameFormat format) const 1464 { 1465 Q_D(const KCalendarSystem); 1466 1467 if (weekDay < 1 || weekDay > d->daysInWeek()) { 1468 return QString(); 1469 } 1470 1471 if (format == KCalendarSystem::NarrowDayName) { 1472 return d->weekDayName(weekDay, KLocale::NarrowName); 1473 } 1474 1475 if (format == KCalendarSystem::ShortDayName) { 1476 return d->weekDayName(weekDay, KLocale::ShortName); 1477 } 1478 1479 return d->weekDayName(weekDay, KLocale::LongName); 1480 } 1481 1482 QString KCalendarSystem::weekDayName(const QDate &date, WeekDayNameFormat format) const 1483 { 1484 if (isValid(date)) { 1485 return weekDayName(dayOfWeek(date), format); 1486 } 1487 1488 return QString(); 1489 } 1490 1491 int KCalendarSystem::yearStringToInteger(const QString &yearString, int &readLength) const 1492 { 1493 Q_D(const KCalendarSystem); 1494 1495 QString minus = i18nc("Negative symbol as used for year numbers, e.g. -5 = 5 BC", "-"); 1496 if (yearString.startsWith(minus)) { 1497 int value = d->integerFromString(yearString.mid(minus.length()), 4, readLength); 1498 if (readLength > 0 && value >= 0) { 1499 readLength = readLength + minus.length(); 1500 return value * -1; 1501 } else { 1502 return value; 1503 } 1504 } 1505 1506 return d->integerFromString(yearString, 4, readLength); 1507 } 1508 1509 int KCalendarSystem::monthStringToInteger(const QString &monthString, int &readLength) const 1510 { 1511 Q_D(const KCalendarSystem); 1512 return d->integerFromString(monthString, 2, readLength); 1513 } 1514 1515 int KCalendarSystem::dayStringToInteger(const QString &dayString, int &readLength) const 1516 { 1517 Q_D(const KCalendarSystem); 1518 return d->integerFromString(dayString, 2, readLength); 1519 } 1520 1521 QString KCalendarSystem::formatDate(const QDate &fromDate, KLocale::DateFormat toFormat) const 1522 { 1523 if (!fromDate.isValid()) { 1524 return QString(); 1525 } 1526 1527 if (toFormat == KLocale::FancyShortDate || toFormat == KLocale::FancyLongDate) { 1528 QDate now = KDateTime::currentLocalDate(); 1529 int daysToNow = fromDate.daysTo(now); 1530 switch (daysToNow) { 1531 case 0: 1532 return i18n("Today"); 1533 case 1: 1534 return i18n("Yesterday"); 1535 case 2: 1536 case 3: 1537 case 4: 1538 case 5: 1539 case 6: 1540 return weekDayName(fromDate); 1541 default: 1542 break; 1543 } 1544 } 1545 1546 switch (toFormat) { 1547 case KLocale::LongDate: 1548 case KLocale::FancyLongDate: 1549 return formatDate(fromDate, locale()->dateFormat()); 1550 case KLocale::IsoDate: 1551 return formatDate(fromDate, QLatin1String("%Y-%m-%d")); 1552 case KLocale::IsoWeekDate: 1553 return formatDate(fromDate, QLatin1String("%Y-W%V-%u")); 1554 case KLocale::IsoOrdinalDate: 1555 return formatDate(fromDate, QLatin1String("%Y-%j")); 1556 case KLocale::ShortDate: 1557 case KLocale::FancyShortDate: 1558 default: 1559 return formatDate(fromDate, locale()->dateFormatShort()); 1560 } 1561 1562 } 1563 1564 // NOT VIRTUAL - If override needed use shared-d 1565 QString KCalendarSystem::formatDate(const QDate &fromDate, const QString &toFormat, 1566 KLocale::DateTimeFormatStandard standard) const 1567 { 1568 return formatDate(fromDate, toFormat, locale()->dateTimeDigitSet(), standard); 1569 } 1570 1571 // NOT VIRTUAL - If override needed use shared-d 1572 QString KCalendarSystem::formatDate(const QDate &fromDate, const QString &toFormat, KLocale::DigitSet digitSet, 1573 KLocale::DateTimeFormatStandard formatStandard) const 1574 { 1575 if (!isValid(fromDate) || toFormat.isEmpty()) { 1576 return QString(); 1577 } 1578 1579 KDateTimeFormatter formatter; 1580 return formatter.formatDate(fromDate, toFormat, this, locale(), digitSet, formatStandard); 1581 } 1582 1583 // NOT VIRTUAL - If override needed use shared-d 1584 QString KCalendarSystem::formatDate(const QDate &date, KLocale::DateTimeComponent component, 1585 KLocale::DateTimeComponentFormat format, 1586 KLocale::WeekNumberSystem weekNumberSystem) const 1587 { 1588 Q_D(const KCalendarSystem); 1589 1590 switch (component) { 1591 case KLocale::Year: 1592 case KLocale::YearName: 1593 switch (format) { 1594 case KLocale::ShortName: 1595 case KLocale::NarrowName: 1596 case KLocale::ShortNumber: 1597 return formatDate(date, QLatin1String("%y")); 1598 case KLocale::LongNumber: 1599 case KLocale::LongName: 1600 case KLocale::DefaultComponentFormat: 1601 default: 1602 return formatDate(date, QLatin1String("%Y")); 1603 } 1604 case KLocale::Month: 1605 switch (format) { 1606 case KLocale::LongName: 1607 return monthName(date, KCalendarSystem::LongName); 1608 case KLocale::ShortName: 1609 return monthName(date, KCalendarSystem::ShortName); 1610 case KLocale::NarrowName: 1611 return monthName(date, KCalendarSystem::NarrowName); 1612 case KLocale::LongNumber: 1613 return formatDate(date, QLatin1String("%m")); 1614 case KLocale::ShortNumber: 1615 case KLocale::DefaultComponentFormat: 1616 default: 1617 return formatDate(date, QLatin1String("%n")); 1618 } 1619 case KLocale::MonthName: 1620 switch (format) { 1621 case KLocale::NarrowName: 1622 return monthName(date, KCalendarSystem::NarrowName); 1623 case KLocale::ShortName: 1624 case KLocale::ShortNumber: 1625 return monthName(date, KCalendarSystem::ShortName); 1626 case KLocale::LongName: 1627 case KLocale::LongNumber: 1628 case KLocale::DefaultComponentFormat: 1629 default: 1630 return monthName(date, KCalendarSystem::LongName); 1631 } 1632 case KLocale::Day: 1633 case KLocale::DayName: 1634 switch (format) { 1635 case KLocale::LongNumber: 1636 case KLocale::LongName: 1637 return formatDate(date, QLatin1String("%d")); 1638 case KLocale::ShortName: 1639 case KLocale::NarrowName: 1640 case KLocale::ShortNumber: 1641 case KLocale::DefaultComponentFormat: 1642 default: 1643 return formatDate(date, QLatin1String("%e")); 1644 } 1645 case KLocale::JulianDay: 1646 return d->stringFromInteger(date.toJulianDay(), 0); 1647 case KLocale::EraName: 1648 switch (format) { 1649 case KLocale::LongNumber: 1650 case KLocale::LongName: 1651 return eraName(date, KCalendarSystem::LongFormat); 1652 case KLocale::ShortName: 1653 case KLocale::NarrowName: 1654 case KLocale::ShortNumber: 1655 case KLocale::DefaultComponentFormat: 1656 default: 1657 return eraName(date, KCalendarSystem::ShortFormat); 1658 } 1659 case KLocale::EraYear: 1660 switch (format) { 1661 case KLocale::LongNumber: 1662 case KLocale::LongName: 1663 return eraYear(date, KCalendarSystem::LongFormat); 1664 case KLocale::ShortName: 1665 case KLocale::NarrowName: 1666 case KLocale::ShortNumber: 1667 case KLocale::DefaultComponentFormat: 1668 default: 1669 return eraYear(date, KCalendarSystem::ShortFormat); 1670 } 1671 case KLocale::YearInEra: 1672 switch (format) { 1673 case KLocale::LongNumber: 1674 case KLocale::LongName: 1675 return formatDate(date, QLatin1String("%4Ey")); 1676 case KLocale::ShortName: 1677 case KLocale::NarrowName: 1678 case KLocale::ShortNumber: 1679 case KLocale::DefaultComponentFormat: 1680 default: 1681 return formatDate(date, QLatin1String("%Ey")); 1682 } 1683 case KLocale::DayOfYear: 1684 case KLocale::DayOfYearName: 1685 switch (format) { 1686 case KLocale::LongNumber: 1687 case KLocale::LongName: 1688 return formatDate(date, QLatin1String("%j")); 1689 case KLocale::ShortName: 1690 case KLocale::NarrowName: 1691 case KLocale::ShortNumber: 1692 case KLocale::DefaultComponentFormat: 1693 default: 1694 return formatDate(date, QLatin1String("%-j")); 1695 } 1696 case KLocale::DayOfWeek: 1697 switch (format) { 1698 case KLocale::LongName: 1699 return weekDayName(date, KCalendarSystem::LongDayName); 1700 case KLocale::ShortName: 1701 return weekDayName(date, KCalendarSystem::ShortDayName); 1702 case KLocale::NarrowName: 1703 return weekDayName(date, KCalendarSystem::NarrowDayName); 1704 case KLocale::LongNumber: 1705 case KLocale::ShortNumber: 1706 case KLocale::DefaultComponentFormat: 1707 default: 1708 return formatDate(date, QLatin1String("%-u")); 1709 } 1710 case KLocale::DayOfWeekName: 1711 switch (format) { 1712 case KLocale::NarrowName: 1713 return weekDayName(date, KCalendarSystem::NarrowDayName); 1714 case KLocale::ShortName: 1715 case KLocale::ShortNumber: 1716 return weekDayName(date, KCalendarSystem::ShortDayName); 1717 case KLocale::LongName: 1718 case KLocale::LongNumber: 1719 case KLocale::DefaultComponentFormat: 1720 default: 1721 return weekDayName(date, KCalendarSystem::LongDayName); 1722 } 1723 case KLocale::Week: 1724 switch (format) { 1725 case KLocale::LongNumber: 1726 case KLocale::LongName: 1727 return d->stringFromInteger(week(date, weekNumberSystem, nullptr), 2, QLatin1Char('0')); 1728 case KLocale::ShortName: 1729 case KLocale::NarrowName: 1730 case KLocale::ShortNumber: 1731 case KLocale::DefaultComponentFormat: 1732 default: 1733 return d->stringFromInteger(week(date, weekNumberSystem, nullptr), 0, QLatin1Char('0')); 1734 } 1735 case KLocale::WeekYear: { 1736 int weekYear; 1737 QDate yearDate; 1738 week(date, weekNumberSystem, &weekYear); 1739 setDate(yearDate, weekYear, 1, 1); 1740 return formatDate(yearDate, KLocale::Year, format); 1741 } 1742 case KLocale::MonthsInYear: 1743 switch (format) { 1744 case KLocale::LongNumber: 1745 case KLocale::LongName: 1746 return d->stringFromInteger(monthsInYear(date), 2, QLatin1Char('0')); 1747 case KLocale::ShortName: 1748 case KLocale::NarrowName: 1749 case KLocale::ShortNumber: 1750 case KLocale::DefaultComponentFormat: 1751 default: 1752 return d->stringFromInteger(monthsInYear(date), 0, QLatin1Char('0')); 1753 } 1754 case KLocale::WeeksInYear: 1755 switch (format) { 1756 case KLocale::LongNumber: 1757 case KLocale::LongName: 1758 return d->stringFromInteger(weeksInYear(date), 2, QLatin1Char('0')); 1759 case KLocale::ShortName: 1760 case KLocale::NarrowName: 1761 case KLocale::ShortNumber: 1762 case KLocale::DefaultComponentFormat: 1763 default: 1764 return d->stringFromInteger(weeksInYear(date), 0, QLatin1Char('0')); 1765 } 1766 case KLocale::DaysInYear: 1767 switch (format) { 1768 case KLocale::LongNumber: 1769 case KLocale::LongName: 1770 return d->stringFromInteger(daysInYear(date), 3, QLatin1Char('0')); 1771 case KLocale::ShortName: 1772 case KLocale::NarrowName: 1773 case KLocale::ShortNumber: 1774 case KLocale::DefaultComponentFormat: 1775 default: 1776 return d->stringFromInteger(daysInYear(date), 0, QLatin1Char('0')); 1777 } 1778 case KLocale::DaysInMonth: 1779 switch (format) { 1780 case KLocale::LongNumber: 1781 case KLocale::LongName: 1782 return d->stringFromInteger(daysInMonth(date), 2, QLatin1Char('0')); 1783 case KLocale::ShortName: 1784 case KLocale::NarrowName: 1785 case KLocale::ShortNumber: 1786 case KLocale::DefaultComponentFormat: 1787 default: 1788 return d->stringFromInteger(daysInMonth(date), 0, QLatin1Char('0')); 1789 } 1790 case KLocale::DaysInWeek: 1791 switch (format) { 1792 case KLocale::LongNumber: 1793 case KLocale::LongName: 1794 case KLocale::ShortName: 1795 case KLocale::NarrowName: 1796 case KLocale::ShortNumber: 1797 case KLocale::DefaultComponentFormat: 1798 default: 1799 return d->stringFromInteger(d->daysInWeek(), 0); 1800 } 1801 default: 1802 return QString(); 1803 } 1804 } 1805 1806 QDate KCalendarSystem::readDate(const QString &str, bool *ok) const 1807 { 1808 //Try each standard format in turn, start with the locale ones, 1809 //then the well defined standards 1810 QDate date = readDate(str, KLocale::ShortFormat, ok); 1811 if (!isValid(date)) { 1812 date = readDate(str, KLocale::NormalFormat, ok); 1813 if (!isValid(date)) { 1814 date = readDate(str, KLocale::IsoFormat, ok); 1815 if (!isValid(date)) { 1816 date = readDate(str, KLocale::IsoWeekFormat, ok); 1817 if (!isValid(date)) { 1818 date = readDate(str, KLocale::IsoOrdinalFormat, ok); 1819 } 1820 } 1821 } 1822 } 1823 1824 return date; 1825 } 1826 1827 QDate KCalendarSystem::readDate(const QString &str, KLocale::ReadDateFlags flags, bool *ok) const 1828 { 1829 if (flags & KLocale::ShortFormat) { 1830 return readDate(str, locale()->dateFormatShort(), ok); 1831 } else if (flags & KLocale::NormalFormat) { 1832 return readDate(str, locale()->dateFormat(), ok); 1833 } else if (flags & KLocale::IsoFormat) { 1834 return readDate(str, QLatin1String("%Y-%m-%d"), ok); 1835 } else if (flags & KLocale::IsoWeekFormat) { 1836 return readDate(str, QLatin1String("%Y-W%V-%u"), ok); 1837 } else if (flags & KLocale::IsoOrdinalFormat) { 1838 return readDate(str, QLatin1String("%Y-%j"), ok); 1839 } 1840 return QDate(); 1841 } 1842 1843 QDate KCalendarSystem::readDate(const QString &inputString, const QString &formatString, bool *ok) const 1844 { 1845 return readDate(inputString, formatString, ok, KLocale::KdeFormat); 1846 } 1847 1848 // NOT VIRTUAL - If override needed use shared-d 1849 QDate KCalendarSystem::readDate(const QString &inputString, const QString &formatString, bool *ok, 1850 KLocale::DateTimeFormatStandard formatStandard) const 1851 { 1852 KDateTimeParser parser; 1853 QDate resultDate = parser.parseDate(inputString, formatString, this, locale(), locale()->dateTimeDigitSet(), formatStandard); 1854 if (ok) { 1855 *ok = resultDate.isValid(); 1856 } 1857 return resultDate; 1858 } 1859 1860 // NOT VIRTUAL - If override needed use shared-d 1861 int KCalendarSystem::shortYearWindowStartYear() const 1862 { 1863 Q_D(const KCalendarSystem); 1864 1865 return d->shortYearWindowStartYear(); 1866 } 1867 1868 // NOT VIRTUAL - If override needed use shared-d 1869 int KCalendarSystem::applyShortYearWindow(int inputYear) const 1870 { 1871 Q_D(const KCalendarSystem); 1872 1873 return d->applyShortYearWindow(inputYear); 1874 } 1875 1876 const KLocale *KCalendarSystem::locale() const 1877 { 1878 Q_D(const KCalendarSystem); 1879 1880 return d->locale(); 1881 }