KDELibs4Support

kcalendarsystem.cpp
1 /*
2  Copyright (c) 2002 Carlos Moro <[email protected]>
3  Copyright (c) 2002 Hans Petter Bieker <[email protected]>
4  Copyright 2007, 2008, 2009, 2010 John Layt <[email protected]>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "kcalendarsystem.h"
23 #include "kcalendarsystemprivate_p.h"
24 
25 #include "kconfiggroup.h"
26 
27 #include <QDateTime>
28 
29 #include "klocalizedstring.h"
30 #include "kdatetime.h"
31 #include "kdatetimeformatter_p.h"
32 #include "kdatetimeparser_p.h"
33 #include "kcalendarera_p.h"
34 #include "kcalendarsystemcoptic_p.h"
35 #include "kcalendarsystemethiopian_p.h"
36 #include "kcalendarsystemgregorian_p.h"
37 #include "kcalendarsystemhebrew_p.h"
38 #include "kcalendarsystemindiannational_p.h"
39 #include "kcalendarsystemislamiccivil_p.h"
40 #include "kcalendarsystemjalali_p.h"
41 #include "kcalendarsystemjapanese_p.h"
42 #include "kcalendarsystemjulian_p.h"
43 #include "kcalendarsystemminguo_p.h"
44 #include "kcalendarsystemthai_p.h"
45 
47 {
48  return create(calendarSystem, KSharedConfig::Ptr(), locale);
49 }
50 
52  KSharedConfig::Ptr config,
53  const KLocale *locale)
54 {
55  switch (calendarSystem) {
57  return new KCalendarSystemGregorian(config, locale);
59  return new KCalendarSystemCoptic(config, locale);
61  return new KCalendarSystemEthiopian(config, locale);
63  return new KCalendarSystemHebrew(config, locale);
65  return new KCalendarSystemIndianNational(config, locale);
67  return new KCalendarSystemIslamicCivil(config, locale);
69  return new KCalendarSystemJalali(config, locale);
71  return new KCalendarSystemJapanese(config, locale);
73  return new KCalendarSystemJulian(config, locale);
75  return new KCalendarSystemMinguo(config, locale);
77  return new KCalendarSystemThai(config, locale);
78  default:
79  return new KCalendarSystemGregorian(config, locale);
80  }
81 }
82 
84 {
86 
98 
99  return list;
100 }
101 
103 {
104  QStringList languages = locale->languageList();
105 
106  switch (calendarSystem) {
108  return ki18nc("@item Calendar system", "Gregorian").toString(languages);
110  return ki18nc("@item Calendar system", "Coptic").toString(languages);
112  return ki18nc("@item Calendar system", "Ethiopian").toString(languages);
114  return ki18nc("@item Calendar system", "Hebrew").toString(languages);
116  return ki18nc("@item Calendar system", "Islamic / Hijri (Civil)").toString(languages);
118  return ki18nc("@item Calendar system", "Indian National").toString(languages);
120  return ki18nc("@item Calendar system", "Jalali").toString(languages);
122  return ki18nc("@item Calendar system", "Japanese").toString(languages);
124  return ki18nc("@item Calendar system", "Julian").toString(languages);
126  return ki18nc("@item Calendar system", "Taiwanese").toString(languages);
128  return ki18nc("@item Calendar system", "Thai").toString(languages);
129  }
130 
131  return ki18nc("@item Calendar system", "Invalid Calendar Type").toString(languages);
132 }
133 
134 // Shared d pointer base class definitions
135 
136 KCalendarSystemPrivate::KCalendarSystemPrivate(KCalendarSystem *q_ptr)
137  : q(q_ptr),
138  m_eraList(nullptr),
139  m_shortYearWindowStartYear(2000)
140 {
141 }
142 
143 KCalendarSystemPrivate::~KCalendarSystemPrivate()
144 {
145  delete m_eraList;
146 }
147 
148 int KCalendarSystemPrivate::isoWeekNumber(const QDate &date, int *yearNum) const
149 {
150  int y, m, d;
151  q->julianDayToDate(date.toJulianDay(), y, m, d);
152 
153  QDate firstDayWeek1, lastDay;
154  int week;
155  int weekDay1, dayOfWeek1InYear;
156 
157  // let's guess 1st day of 1st week
158  firstDayWeek1 = firstDayOfYear(y);
159  weekDay1 = dayOfWeek(firstDayWeek1);
160 
161  // iso 8601: week 1 is the first containing thursday and week starts on monday
162  if (weekDay1 > 4 /*Thursday*/) {
163  firstDayWeek1 = q->addDays(firstDayWeek1, daysInWeek() - weekDay1 + 1); // next monday
164  }
165 
166  dayOfWeek1InYear = dayOfYear(firstDayWeek1);
167 
168  // our date in prev year's week
169  if (dayOfYear(date) < dayOfWeek1InYear) {
170  if (yearNum) {
171  *yearNum = addYears(y, - 1);
172  }
173  return isoWeeksInYear(addYears(y, - 1));
174  }
175 
176  // let's check if its last week belongs to next year
177  lastDay = lastDayOfYear(y);
178 
179  // if our date is in last week && 1st week in next year has thursday
180  if ((dayOfYear(date) >= daysInYear(y) - dayOfWeek(lastDay) + 1)
181  && dayOfWeek(lastDay) < 4) {
182  if (yearNum) {
183  * yearNum = addYears(y, 1);
184  }
185  week = 1;
186  } else {
187  // To calculate properly the number of weeks from day a to x let's make a day 1 of week
188  if (weekDay1 < 5) {
189  firstDayWeek1 = q->addDays(firstDayWeek1, -(weekDay1 - 1));
190  }
191 
192  if (yearNum) {
193  * yearNum = y;
194  }
195 
196  week = firstDayWeek1.daysTo(date) / daysInWeek() + 1;
197  }
198 
199  return week;
200 }
201 
202 int KCalendarSystemPrivate::regularWeekNumber(const QDate &date, int weekStartDay, int firstWeekNumber, int *weekYear) const
203 {
204  int y, m, d;
205  q->julianDayToDate(date.toJulianDay(), y, m, d);
206 
207  int firstWeekDayOffset = (dayOfWeek(date) - weekStartDay + daysInWeek()) % daysInWeek();
208  int dayInYear = date.toJulianDay() - firstDayOfYear(y).toJulianDay(); // 0 indexed
209  int week = ((dayInYear - firstWeekDayOffset + daysInWeek()) / daysInWeek());
210 
212  week = week + firstWeekNumber;
213  }
214 
215  if (week < 1) {
216  y = y - 1;
217  week = regularWeeksInYear(y, weekStartDay, firstWeekNumber);
218  }
219 
220  if (weekYear) {
221  *weekYear = y;
222  }
223 
224  return week;
225 }
226 
227 int KCalendarSystemPrivate::simpleWeekNumber(const QDate &date, int *yearNum) const
228 {
229  int y, m, d;
230  q->julianDayToDate(date.toJulianDay(), y, m, d);
231  if (yearNum) {
232  *yearNum = y;
233  }
234  return ((date.toJulianDay() - firstDayOfYear(y).toJulianDay()) / daysInWeek()) + 1;
235 }
236 
237 int KCalendarSystemPrivate::isoWeeksInYear(int year) const
238 {
239  QDate lastDayOfThisYear = lastDayOfYear(year);
240 
241  int weekYear = year;
242  int lastWeekInThisYear = isoWeekNumber(lastDayOfThisYear, &weekYear);
243 
244  // If error, or the last day of the year is in the first week of next year use the week before
245  if (lastWeekInThisYear < 1 || weekYear != year) {
246  lastWeekInThisYear = isoWeekNumber(q->addDays(lastDayOfThisYear, -7), &weekYear);
247  }
248 
249  return lastWeekInThisYear;
250 }
251 
252 int KCalendarSystemPrivate::regularWeeksInYear(int year, int weekStartDay, int firstWeekNumber) const
253 {
254  return regularWeekNumber(lastDayOfYear(year), weekStartDay, firstWeekNumber, nullptr);
255 }
256 
257 int KCalendarSystemPrivate::simpleWeeksInYear(int year) const
258 {
259  return simpleWeekNumber(lastDayOfYear(year), nullptr);
260 }
261 
262 // Reimplement if special maths handling required, e.g. Hebrew.
263 // Works for calendars with constant number of months, or where leap month is last month of year
264 // Will not work for Hebrew or others where leap month is inserted in middle of year
265 void KCalendarSystemPrivate::dateDifference(const QDate &fromDate, const QDate &toDate,
266  int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const
267 {
268  // This could be optimised a little but is left in full as it's easier to understand
269  int dy = 0;
270  int dm = 0;
271  int dd = 0;
272  int dir = 1;
273 
274  if (toDate < fromDate) {
275  dateDifference(toDate, fromDate, &dy, &dm, &dd, nullptr);
276  dir = -1;
277  } else if (toDate > fromDate) {
278 
279  int fromYear = q->year(fromDate);
280  int toYear = q->year(toDate);
281  int fromMonth = q->month(fromDate);
282  int toMonth = q->month(toDate);
283  int fromDay = q->day(fromDate);
284  int toDay = q->day(toDate);
285 
286  int monthsInPrevYear = monthsInYear(addYears(toYear, -1));
287  int daysInPrevMonth = q->daysInMonth(q->addMonths(toDate, -1));
288  int daysInFromMonth = daysInMonth(fromYear, fromMonth);
289  int daysInToMonth = daysInMonth(toYear, toMonth);
290 
291  // Calculate years difference
292  if (toYear == fromYear) {
293  dy = 0;
294  } else if (toMonth > fromMonth) {
295  dy = differenceYearNumbers(fromYear, toYear);
296  } else if (toMonth < fromMonth) {
297  dy = differenceYearNumbers(fromYear, toYear) - 1;
298  } else { // toMonth == fromMonth
299  // Allow for last day of month to last day of month and leap days
300  // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years
301  if ((toDay >= fromDay) || (fromDay == daysInFromMonth && toDay == daysInToMonth)) {
302  dy = differenceYearNumbers(fromYear, toYear);
303  } else {
304  dy = differenceYearNumbers(fromYear, toYear) - 1;
305  }
306  }
307 
308  // Calculate months and days difference
309  if (toDay >= fromDay) {
310  dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear;
311  dd = toDay - fromDay;
312  } else { // toDay < fromDay
313  // Allow for last day of month to last day of month and leap days
314  // e.g. 2010-03-31 to 2010-04-30 is 1 month
315  // 2000-02-29 to 2001-02-28 is 1 year
316  // 2000-02-29 to 2001-03-01 is 1 year 1 day
317  int prevMonth = q->month(q->addMonths(toDate, -1));
318  if (fromDay == daysInFromMonth && toDay == daysInToMonth) {
319  dm = (monthsInPrevYear + toMonth - fromMonth) % monthsInPrevYear;
320  dd = 0;
321  } else if (prevMonth == fromMonth && daysInPrevMonth < daysInFromMonth) {
322  // Special case where fromDate = leap day and toDate in month following but non-leap year
323  // e.g. 2000-02-29 to 2001-03-01 needs to use 29 to calculate day number not 28
324  dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear;
325  dd = (daysInFromMonth + toDay - fromDay) % daysInFromMonth;
326  } else {
327  dm = (monthsInPrevYear + toMonth - fromMonth - 1) % monthsInPrevYear;
328  dd = (daysInPrevMonth + toDay - fromDay) % daysInPrevMonth;
329  }
330  }
331 
332  }
333 
334  // Only return values if we have a valid pointer
335  if (yearsDiff) {
336  *yearsDiff = dy;
337  }
338  if (monthsDiff) {
339  *monthsDiff = dm;
340  }
341  if (daysDiff) {
342  *daysDiff = dd;
343  }
344  if (direction) {
345  *direction = dir;
346  }
347 }
348 
349 // Reimplement if special maths handling required, e.g. Hebrew
350 // Allows for calendars with leap months at end of year but not during year
351 int KCalendarSystemPrivate::yearsDifference(const QDate &fromDate, const QDate &toDate) const
352 {
353  // This could be optimised a little but is left in full as it's easier to understand
354  // Alternatively could just call dateDifference(), but this is slightly more efficient
355 
356  if (toDate < fromDate) {
357  return 0 - yearsDifference(toDate, fromDate);
358  }
359 
360  if (toDate == fromDate) {
361  return 0;
362  }
363 
364  int fromYear = q->year(fromDate);
365  int toYear = q->year(toDate);
366 
367  if (toYear == fromYear) {
368  return 0;
369  }
370 
371  int fromMonth = q->month(fromDate);
372  int toMonth = q->month(toDate);
373 
374  if (toMonth > fromMonth) {
375  return differenceYearNumbers(fromYear, toYear);
376  }
377 
378  if (toMonth < fromMonth) {
379  return differenceYearNumbers(fromYear, toYear) - 1;
380  }
381 
382  // toMonth == fromMonth
383  int fromDay = q->day(fromDate);
384  int toDay = q->day(toDate);
385 
386  // Adjust for month numbers in from and to year
387  // Allow for last day of month to last day of month and leap days
388  // e.g. 2000-02-29 to 2001-02-28 is 1 year not 0 years
389  if ((toDay >= fromDay) ||
390  (fromDay == daysInMonth(fromYear, fromMonth) &&
391  toDay == daysInMonth(toYear, toMonth))) {
392  return differenceYearNumbers(fromYear, toYear);
393  } else {
394  return differenceYearNumbers(fromYear, toYear) - 1;
395  }
396 
397 }
398 
399 // Reimplement if special maths handling required, e.g. maybe Hebrew?
400 // Allows for calendars with leap months
401 int KCalendarSystemPrivate::monthsDifference(const QDate &fromDate, const QDate &toDate) const
402 {
403  if (toDate < fromDate) {
404  return 0 - monthsDifference(toDate, fromDate);
405  }
406 
407  if (toDate == fromDate) {
408  return 0;
409  }
410 
411  int fromYear = q->year(fromDate);
412  int toYear = q->year(toDate);
413  int fromMonth = q->month(fromDate);
414  int toMonth = q->month(toDate);
415  int fromDay = q->day(fromDate);
416  int toDay = q->day(toDate);
417 
418  int monthsInPreceedingYears;
419 
420  // Calculate number of months in full years preceding toYear
421  if (toYear == fromYear) {
422  monthsInPreceedingYears = 0;
423  } else if (hasLeapMonths()) {
424  monthsInPreceedingYears = 0;
425  for (int y = fromYear; y < toYear; y = addYears(y, 1)) {
426  monthsInPreceedingYears = monthsInPreceedingYears + monthsInYear(y);
427  }
428  } else {
429  monthsInPreceedingYears = differenceYearNumbers(fromYear, toYear) * monthsInYear(toYear);
430  }
431 
432  // Adjust for months in from and to year
433  // Allow for last day of month to last day of month and leap days
434  // e.g. 2010-03-31 to 2010-04-30 is 1 month not 0 months
435  // also 2000-02-29 to 2001-02-28 is 12 months not 11 months
436  if ((toDay >= fromDay) ||
437  (fromDay == daysInMonth(fromYear, fromMonth) &&
438  toDay == daysInMonth(toYear, toMonth))) {
439  return monthsInPreceedingYears + toMonth - fromMonth;
440  } else {
441  return monthsInPreceedingYears + toMonth - fromMonth - 1;
442  }
443 }
444 
445 // Reimplement if special string to integer handling required, e.g. Hebrew.
446 // Peel a number off the front of a string which may have other trailing chars after the number
447 // Stop either at either maxLength, eos, or first non-digit char
448 int KCalendarSystemPrivate::integerFromString(const QString &string, int maxLength, int &readLength) const
449 {
450  int value = -1;
451  int position = 0;
452  readLength = 0;
453  bool ok = false;
454 
455  if (maxLength < 0) {
456  maxLength = string.length();
457  }
458 
459  while (position < string.length() &&
460  position < maxLength &&
461  string.at(position).isDigit()) {
462  position++;
463  }
464 
465  if (position > 0) {
466  value = string.left(position).toInt(&ok);
467  if (ok) {
468  readLength = position;
469  } else {
470  value = -1;
471  }
472  }
473 
474  return value;
475 }
476 
477 // Reimplement if special integer to string handling required, e.g. Hebrew.
478 // Utility to convert an integer into the correct display string form
479 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar) const
480 {
481  return stringFromInteger(number, padWidth, padChar, q->locale()->dateTimeDigitSet());
482 }
483 
484 // Reimplement if special integer to string handling required, e.g. Hebrew.
485 // Utility to convert an integer into the correct display string form
486 QString KCalendarSystemPrivate::stringFromInteger(int number, int padWidth, QChar padChar, KLocale::DigitSet digitSet) const
487 {
488  if (padChar == QLatin1Char('\0') || padWidth == 0) {
489  return q->locale()->convertDigits(QString::number(number), digitSet);
490  } else {
491  return q->locale()->convertDigits(QString::number(number).rightJustified(padWidth, padChar), digitSet);
492  }
493 }
494 
495 // Utility to correctly add years to a year number because some systems such as
496 // Julian and Gregorian calendars don't have a year 0
497 int KCalendarSystemPrivate::addYears(int originalYear, int addYears) const
498 {
499  int newYear = originalYear + addYears;
500 
501  if (!hasYearZero()) {
502  if (originalYear > 0 && newYear <= 0) {
503  newYear = newYear - 1;
504  } else if (originalYear < 0 && newYear >= 0) {
505  newYear = newYear + 1;
506  }
507  }
508 
509  return newYear;
510 }
511 
512 // Utility to correctly return number of years between two year numbers because some systems such as
513 // Julian and Gregorian calendars don't have a year 0
514 int KCalendarSystemPrivate::differenceYearNumbers(int fromYear, int toYear) const
515 {
516  int dy = toYear - fromYear;
517 
518  if (!hasYearZero()) {
519  if (toYear > 0 && fromYear < 0) {
520  dy = dy - 1;
521  } else if (toYear < 0 && fromYear > 0) {
522  dy = dy + 1;
523  }
524  }
525 
526  return dy;
527 }
528 
529 QString KCalendarSystemPrivate::simpleDateString(const QString &str) const
530 {
531  QString newStr;
532  newStr.reserve(str.length());
533  for (int i = 0; i < str.length(); i++) {
534  if (str.at(i).isLetterOrNumber()) {
535  newStr.append(str.at(i));
536  } else {
537  newStr.append(QLatin1Char(' '));
538  }
539  }
540 
541  return newStr.simplified();
542 }
543 
544 // If we ever want to support a calendar system with another week length,this
545 // method can be changed to virtual. Doing so will, however, likely break some
546 // code, so don't do that without testing and fixing at least all of KDE SC.
547 int KCalendarSystemPrivate::daysInWeek() const
548 {
549  return 7;
550 }
551 
552 int KCalendarSystemPrivate::dayOfYear(const QDate &date) const
553 {
554  qint64 jdFirstDayOfYear;
555  int y, m, d;
556  q->julianDayToDate(date.toJulianDay(), y, m, d);
557  q->dateToJulianDay(y, 1, 1, jdFirstDayOfYear);
558  //Take the jd of the given date, and subtract the jd of the first day of that year
559  return (date.toJulianDay() - jdFirstDayOfYear + 1);
560 }
561 
562 // This assumes all calendar systems agree on the day of week for a given
563 // julian day number. That is true of all current calendar systems. If we
564 // ever want to support one for which it isn't this implementation can be
565 // changed. Doing so will, however, likely break some code, so don't do that
566 // without testing and fixing at least all of KDE SC.
567 int KCalendarSystemPrivate::dayOfWeek(const QDate &date) const
568 {
569  return date.dayOfWeek();
570 }
571 
572 QDate KCalendarSystemPrivate::firstDayOfYear(int year) const
573 {
574  qint64 jd;
575  q->dateToJulianDay(year, 1, 1, jd);
576  return QDate::fromJulianDay(jd);
577 }
578 
579 QDate KCalendarSystemPrivate::lastDayOfYear(int year) const
580 {
581  qint64 jd;
582  q->dateToJulianDay(year, 1, 1, jd);
583  jd = jd + daysInYear(year) - 1;
584  return QDate::fromJulianDay(jd);
585 }
586 
587 QDate KCalendarSystemPrivate::firstDayOfMonth(int year, int month) const
588 {
589  qint64 jd;
590  q->dateToJulianDay(year, month, 1, jd);
591  return QDate::fromJulianDay(jd);
592 }
593 
594 QDate KCalendarSystemPrivate::lastDayOfMonth(int year, int month) const
595 {
596  qint64 jd;
597  q->dateToJulianDay(year, month, 1, jd);
598  jd = jd + daysInMonth(year, month) - 1;
599  return QDate::fromJulianDay(jd);
600 }
601 
602 const KLocale *KCalendarSystemPrivate::locale() const
603 {
604  if (m_locale) {
605  return m_locale;
606  } else {
607  return KLocale::global();
608  }
609 }
610 
611 QList<KCalendarEra> *KCalendarSystemPrivate::eraList() const
612 {
613  return m_eraList;
614 }
615 
616 KCalendarEra KCalendarSystemPrivate::era(const QDate &eraDate) const
617 {
618  for (int i = m_eraList->count() - 1; i >= 0; --i) {
619  if (m_eraList->at(i).isInEra(eraDate)) {
620  return m_eraList->at(i);
621  }
622  }
623  return KCalendarEra();
624 }
625 
626 KCalendarEra KCalendarSystemPrivate::era(const QString &eraName, int yearInEra) const
627 {
628  Q_UNUSED(yearInEra)
629 
630  for (int i = m_eraList->count() - 1; i >= 0; --i) {
631  KCalendarEra era = m_eraList->at(i);
632  if (era.name(KLocale::LongName).toLower() == eraName.toLower() ||
633  era.name(KLocale::ShortName).toLower() == eraName.toLower()) {
634  return era;
635  }
636  }
637  return KCalendarEra();
638 }
639 
640 void KCalendarSystemPrivate::loadEraList(const KConfigGroup &cg)
641 {
642  delete m_eraList;
643  m_eraList = new QList<KCalendarEra>;
644  QString eraKey = QString::fromLatin1("Era1");
645  int i = 1;
646  while (cg.hasKey(eraKey)) {
647  QString eraEntry = cg.readEntry(eraKey, QString());
648  if (!eraEntry.isEmpty()) {
649  // Based on LC_TIME, but different!
650  // Includes long and short names, uses ISO fomat dates
651  // e.g. +:1:0001-01-01:9999-12-31:Anno Domini:AD:%EC %Ey
652  QChar direction = eraEntry.section(QLatin1Char(':'), 0, 0).at(0);
653  QDate startDate, endDate;
654  int startYear;
655  QString buffer = eraEntry.section(QLatin1Char(':'), 2, 2);
656  if (buffer.isEmpty()) {
657  if (direction == QLatin1Char('-')) {
658  startDate = q->latestValidDate();
659  } else {
660  startDate = q->earliestValidDate();
661  }
662  } else {
663  startDate = q->readDate(buffer, KLocale::IsoFormat);
664  }
665  if (q->isValid(startDate)) {
666  startYear = q->year(startDate);
667  } else {
668  startYear = eraEntry.section(QLatin1Char(':'), 1, 1).toInt(); //Use offset
669  }
670 
671  buffer = eraEntry.section(QLatin1Char(':'), 3, 3);
672  if (buffer.isEmpty()) {
673  if (direction == QLatin1Char('-')) {
674  endDate = q->earliestValidDate();
675  } else {
676  endDate = q->latestValidDate();
677  }
678  } else {
679  endDate = q->readDate(buffer, KLocale::IsoFormat);
680  }
681  addEra(direction.toLatin1(), eraEntry.section(QLatin1Char(':'), 1, 1).toInt(),
682  startDate, startYear, endDate, eraEntry.section(QLatin1Char(':'), 4, 4),
683  eraEntry.section(QLatin1Char(':'), 5, 5), eraEntry.section(QLatin1Char(':'), 6));
684  }
685  ++i;
686  eraKey = QString::fromLatin1("Era%1").arg(i);
687  }
688 
689  if (m_eraList->isEmpty()) {
690  loadDefaultEraList();
691  }
692 }
693 
694 void KCalendarSystemPrivate::addEra(char direction, int offset,
695  const QDate &startDate, int startYear, const QDate &endDate,
696  const QString &name, const QString &shortName,
697  const QString &format)
698 {
699  KCalendarEra newEra;
700 
701  newEra.m_sequence = m_eraList->count() + 1;
702  if (direction == '-') {
703  newEra.m_direction = -1;
704  } else {
705  newEra.m_direction = 1;
706  }
707  newEra.m_offset = offset;
708  newEra.m_startDate = startDate;
709  newEra.m_startYear = startYear;
710  newEra.m_endDate = endDate;
711  newEra.m_longName = name;
712  newEra.m_shortName = shortName;
713  newEra.m_format = format;
714 
715  m_eraList->append(newEra);
716 }
717 
718 int KCalendarSystemPrivate::shortYearWindowStartYear() const
719 {
720  return m_shortYearWindowStartYear;
721 }
722 
723 int KCalendarSystemPrivate::applyShortYearWindow(int inputYear) const
724 {
725  if (inputYear >= 0 && inputYear <= 99) {
726  int shortStartYear = m_shortYearWindowStartYear % 100;
727  int yearOffset = m_shortYearWindowStartYear - shortStartYear;
728  if (inputYear >= shortStartYear) {
729  return inputYear + yearOffset;
730  } else {
731  return inputYear + yearOffset + 100;
732  }
733  } else {
734  return inputYear;
735  }
736 }
737 
738 void KCalendarSystemPrivate::loadShortYearWindowStartYear(const KConfigGroup &cg)
739 {
740  // Default to 2000 for backwards compatibility
741  // as that's the old readDate() default value
742  int startYear = 2000;
743  if (cg.exists()) {
744  startYear = cg.readEntry("ShortYearWindowStartYear", 2000);
745  }
746  m_shortYearWindowStartYear = startYear;
747 }
748 
749 KSharedConfig::Ptr KCalendarSystemPrivate::config()
750 {
751  if (m_config == KSharedConfig::Ptr()) {
752  return KSharedConfig::openConfig();
753  } else {
754  return m_config;
755  }
756 }
757 
758 void KCalendarSystemPrivate::loadConfig(const QString &calendarType)
759 {
760  KConfigGroup localeGroup(config(), QString::fromLatin1("Locale"));
761  KConfigGroup calendarGroup = localeGroup.group(QString::fromLatin1("KCalendarSystem %1").arg(calendarType));
762  loadEraList(calendarGroup);
763  loadShortYearWindowStartYear(calendarGroup);
764 }
765 
766 KCalendarSystem::KCalendarSystem(KCalendarSystemPrivate &dd, const KSharedConfig::Ptr config, const KLocale *locale)
767  : d_ptr(&dd)
768 {
769  d_ptr->m_config = config;
770  d_ptr->m_locale = locale;
771 }
772 
774 {
775  delete d_ptr;
776 }
777 
778 // NOT VIRTUAL - If override needed use shared-d
780 {
782 }
783 
784 bool KCalendarSystem::isValid(int year, int month, int day) const
785 {
786  Q_D(const KCalendarSystem);
787 
788  return year >= d->earliestValidYear() && year <= d->latestValidYear() && (d->hasYearZero() || year != 0) &&
789  month >= 1 && month <= d->monthsInYear(year) &&
790  day >= 1 && day <= d->daysInMonth(year, month);
791 }
792 
794 {
795  Q_D(const KCalendarSystem);
796 
797  return (isValid(year, 1, 1) && dayOfYear > 0 && dayOfYear <= d->daysInYear(year));
798 }
799 
800 bool KCalendarSystem::isValid(const QString &eraName, int yearInEra, int month, int day) const
801 {
802  Q_D(const KCalendarSystem);
803 
804  KCalendarEra era = d->era(eraName, yearInEra);
805  return (era.isValid() && isValid(era.year(yearInEra), month, day));
806 }
807 
808 // NOT VIRTUAL - If override needed use shared-d
809 bool KCalendarSystem::isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const
810 {
811  Q_D(const KCalendarSystem);
812 
813  //Tests Year value in standard YMD isValid()
814  if (!isValid(year, 1, 1)) {
815  return false;
816  }
817 
818  //Test Week Number falls in valid range for this year
819  int weeksInThisYear = weeksInYear(year);
820  if (isoWeekNumber < 1 || isoWeekNumber > weeksInThisYear) {
821  return false;
822  }
823 
824  //Test Day of Week Number falls in valid range
825  if (dayOfIsoWeek < 1 || dayOfIsoWeek > d->daysInWeek()) {
826  return false;
827  }
828 
829  //If not in earliest or latest years then all OK
830  //Otherwise need to check don't fall into previous or next year that would be invalid
831  if (year == d->earliestValidYear() && isoWeekNumber == 1) {
832  //If firstDayOfYear falls on or before Thursday then firstDayOfYear falls in week 1 this
833  //year and if wanted dayOfIsoWeek falls before firstDayOfYear then falls in previous year
834  //and so in invalid year
835  int dowFirstDay = dayOfWeek(d->firstDayOfYear(year));
836  if (dowFirstDay <= 4 && dayOfIsoWeek < dowFirstDay) {
837  return false;
838  }
839  } else if (year == d->latestValidYear() && isoWeekNumber == weeksInThisYear) {
840  //If lastDayOfYear falls on or after Thursday then lastDayOfYear falls in last week this
841  //year and if wanted dayOfIsoWeek falls after lastDayOfYear then falls in next year
842  //and so in invalid year
843  int dowLastDay = dayOfWeek(d->lastDayOfYear(year));
844  if (dowLastDay >= 4 && dayOfIsoWeek > dowLastDay) {
845  return false;
846  }
847  }
848 
849  return true;
850 }
851 
852 bool KCalendarSystem::setDate(QDate &date, int year, int month, int day) const
853 {
854  date = QDate();
855 
856  if (isValid(year, month, day)) {
857  qint64 jd;
858  dateToJulianDay(year, month, day, jd);
859  QDate calcDate = QDate::fromJulianDay(jd);
860 
861  if (isValid(calcDate)) {
862  date = calcDate;
863  return true;
864  }
865  }
866 
867  return false;
868 }
869 
870 // NOT VIRTUAL - If override needed use shared-d
871 bool KCalendarSystem::setDate(QDate &date, int year, int dayOfYear) const
872 {
873  date = QDate();
874 
875  if (isValid(year, dayOfYear)) {
876  qint64 jd;
877  dateToJulianDay(year, 1, 1, jd);
878  QDate calcDate = QDate::fromJulianDay(jd + dayOfYear - 1);
879  if (isValid(calcDate)) {
880  date = calcDate;
881  return true;
882  }
883  }
884 
885  return false;
886 }
887 
888 // NOT VIRTUAL - If override needed use shared-d
889 bool KCalendarSystem::setDate(QDate &date, QString eraName, int yearInEra, int month, int day) const
890 {
891  Q_D(const KCalendarSystem);
892 
893  KCalendarEra era = d->era(eraName, yearInEra);
894  return (era.isValid() && setDate(date, era.year(yearInEra), month, day));
895 }
896 
897 // NOT VIRTUAL - If override needed use shared-d
898 bool KCalendarSystem::setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
899 {
900  Q_D(const KCalendarSystem);
901 
902  date = QDate();
903 
904  if (isValidIsoWeekDate(year, isoWeekNumber, dayOfIsoWeek)) {
905 
906  QDate calcDate = d->firstDayOfYear(year);
907  int dowFirstDayOfYear = dayOfWeek(calcDate);
908 
909  int daysToAdd = (d->daysInWeek() * (isoWeekNumber - 1)) + dayOfIsoWeek;
910 
911  if (dowFirstDayOfYear <= 4) {
912  calcDate = calcDate.addDays(daysToAdd - dowFirstDayOfYear);
913  } else {
914  calcDate = calcDate.addDays(daysInWeek(calcDate) + daysToAdd - dowFirstDayOfYear);
915  }
916 
917  if (isValid(calcDate)) {
918  date = calcDate;
919  return true;
920  }
921  }
922 
923  return false;
924 }
925 
926 // NOT VIRTUAL - If override needed use shared-d
927 void KCalendarSystem::getDate(const QDate date, int *year, int *month, int *day) const
928 {
929  int y, m, d;
930 
931  if (isValid(date)) {
932  julianDayToDate(date.toJulianDay(), y, m, d);
933  } else {
934  y = 0; // How do you denote invalid year when we support -ve years?
935  m = 0;
936  d = 0;
937  }
938 
939  if (year) {
940  *year = y;
941  }
942  if (month) {
943  *month = m;
944  }
945  if (day) {
946  *day = d;
947  }
948 
949 }
950 
951 int KCalendarSystem::year(const QDate &date) const
952 {
953  if (isValid(date)) {
954  int year, month, day;
955 
957 
958  return year;
959  }
960 
961  return 0; // How do you denote invalid year when we support -ve years?
962 }
963 
964 int KCalendarSystem::month(const QDate &date) const
965 {
966  if (isValid(date)) {
967  int year, month, day;
968 
970 
971  return month;
972  }
973 
974  return 0;
975 }
976 
977 int KCalendarSystem::day(const QDate &date) const
978 {
979  if (isValid(date)) {
980  int year, month, day;
981 
983 
984  return day;
985  }
986 
987  return 0;
988 }
989 
990 // NOT VIRTUAL - If override needed use shared-d
992 {
993  Q_D(const KCalendarSystem);
994 
995  if (isValid(date)) {
996  if (format == LongFormat) {
997  return d->era(date).name(KLocale::LongName);
998  } else {
999  return d->era(date).name(KLocale::ShortName);
1000  }
1001  }
1002 
1003  return QString();
1004 }
1005 
1006 // NOT VIRTUAL - If override needed use shared-d
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 
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 
1180 {
1181  Q_D(const KCalendarSystem);
1182 
1183  if (!isValid(year, 1, 1)) {
1184  return -1;
1185  }
1186 
1187  switch (weekNumberSystem) {
1189  return d->isoWeeksInYear(year);
1191  return d->regularWeeksInYear(year, locale()->weekStartDay(), 0);
1193  return d->regularWeeksInYear(year, locale()->weekStartDay(), 1);
1194  case KLocale::SimpleWeek:
1195  return d->simpleWeeksInYear(year);
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 
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;
1231  return d->daysInMonth(year, month);
1232  }
1233 
1234  return -1;
1235 }
1236 
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) {
1289  return d->isoWeekNumber(date, yearNum);
1291  return d->regularWeekNumber(date, locale()->weekStartDay(), 0, yearNum);
1293  return d->regularWeekNumber(date, locale()->weekStartDay(), 1, yearNum);
1294  case KLocale::SimpleWeek:
1295  return d->simpleWeekNumber(date, yearNum);
1297  default:
1298  return week(date, locale()->weekNumberSystem(), yearNum);
1299  }
1300 }
1301 
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
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
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
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
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
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
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
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
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 
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 
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 
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 
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 
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 
1522 {
1523  if (!fromDate.isValid()) {
1524  return QString();
1525  }
1526 
1527  if (toFormat == KLocale::FancyShortDate || toFormat == KLocale::FancyLongDate) {
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:
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"));
1555  return formatDate(fromDate, QLatin1String("%Y-%j"));
1556  case KLocale::ShortDate:
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
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:
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:
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:
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:
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:
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:
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:
1680  default:
1681  return formatDate(date, QLatin1String("%Ey"));
1682  }
1683  case KLocale::DayOfYear:
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:
1693  default:
1694  return formatDate(date, QLatin1String("%-j"));
1695  }
1696  case KLocale::DayOfWeek:
1697  switch (format) {
1698  case KLocale::LongName:
1700  case KLocale::ShortName:
1702  case KLocale::NarrowName:
1704  case KLocale::LongNumber:
1705  case KLocale::ShortNumber:
1707  default:
1708  return formatDate(date, QLatin1String("%-u"));
1709  }
1711  switch (format) {
1712  case KLocale::NarrowName:
1714  case KLocale::ShortName:
1715  case KLocale::ShortNumber:
1717  case KLocale::LongName:
1718  case KLocale::LongNumber:
1720  default:
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:
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:
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:
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:
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:
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:
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 
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
1862 {
1863  Q_D(const KCalendarSystem);
1864 
1865  return d->shortYearWindowStartYear();
1866 }
1867 
1868 // NOT VIRTUAL - If override needed use shared-d
1870 {
1871  Q_D(const KCalendarSystem);
1872 
1873  return d->applyShortYearWindow(inputYear);
1874 }
1875 
1877 {
1878  Q_D(const KCalendarSystem);
1879 
1880  return d->locale();
1881 }
The Year In Era portion of a date.
Definition: klocale.h:738
Only accept a date string in ISO date format (YYYY-MM-DD)
Definition: klocale.h:1113
The Day Of Week / Weekday portion of a date, may be number or name.
Definition: klocale.h:741
virtual bool dateToJulianDay(int year, int month, int day, qint64 &jd) const =0
Internal method to convert YMD values for this calendar system into a Julian Day number.
qint64 daysTo(const QDate &d) const const
The Days In Year portion of a date.
Definition: klocale.h:747
Narrow text format, may not be unique, e.g.
Definition: klocale.h:775
Long name possessive format, e.g.
QString eraName(const QDate &date, StringFormat format=ShortFormat) const
Ethiopian Calendar, aka Ethiopic Calendar.
Definition: klocale.h:652
The Day portion of a date, may be number or name.
Definition: klocale.h:733
The Era Name portion of a date.
Definition: klocale.h:736
QString & append(QChar ch)
KCalendarSystem(KCalendarSystemPrivate &dd, const KSharedConfig::Ptr config, const KLocale *locale)
Constructor of abstract calendar class.
QString toString() const
virtual QDate readDate(const QString &str, bool *ok=nullptr) const
Converts a localized date string to a QDate.
bool setDateIsoWeek(QDate &date, int year, int isoWeekNumber, int dayOfIsoWeek) const
Date/times with associated time zone.
Japanese Calendar, Gregorian calculation using Japanese Era (NengĂ´)
Definition: klocale.h:664
virtual int monthStringToInteger(const QString &sNum, int &iLength) const
Short string format, e.g.
The Year Name portion of a date.
Definition: klocale.h:730
virtual QString yearString(const QDate &date, StringFormat format=LongFormat) const
The Day Of Year Name portion of a date.
Definition: klocale.h:740
Week 1 starts on the first Week Start Day in year ends after 7 days.
Definition: klocale.h:684
The Days In Week portion of a date.
Definition: klocale.h:749
int weekStartDay() const
Use this to determine which day is the first day of the week.
const T & at(int i) const const
Locale Short date format, e.g.
Definition: klocale.h:784
QDate lastDayOfYear(int year) const
QString simplified() const const
DateFormat
Format for date string.
Definition: klocale.h:783
QDate lastDayOfMonth(int year, int month) const
The Months In Year portion of a date.
Definition: klocale.h:745
The Week Year portion of a date.
Definition: klocale.h:744
virtual int day(const QDate &date) const
Returns the day portion of a given date in the current calendar system.
virtual QString weekDayName(int weekDay, WeekDayNameFormat format=LongDayName) const =0
Gets specific calendar type week day name.
The Day Of Week Name / Weekday Name portion of a date.
Definition: klocale.h:742
The system locale default for the componant.
Definition: klocale.h:771
Coptic Calendar as used Coptic Church and some parts of Egypt.
Definition: klocale.h:651
The Year portion of a date, may be number or name.
Definition: klocale.h:729
int daysInWeek(const QDate &date) const
Returns the number of days in the given week.
ISO-8601 Week Date format YYYY-Www-D, e.g.
Definition: klocale.h:793
MonthNameFormat
Format for returned month / day name.
Hebrew Calendar, aka Jewish Calendar.
Definition: klocale.h:654
StringFormat
Format for returned year number / month number / day number as string.
int applyShortYearWindow(int inputYear) const
Number at its natural width, e.g.
Definition: klocale.h:772
KCalendarSystem abstract base class, provides support for local Calendar Systems in KDE...
DateTimeComponentFormat
Definition: klocale.h:770
int weeksInYear(const QDate &date, KLocale::WeekNumberSystem weekNumberSystem=KLocale::DefaultWeekNumber) const
virtual KLocale::CalendarSystem calendarSystem() const =0
Indian National Calendar, not the Lunar Calendar.
Definition: klocale.h:659
int dayOfWeek() const const
QString number(int n, int base)
void append(const T &value)
The Weeks In Year portion of a date.
Definition: klocale.h:746
virtual int dayOfYear(const QDate &date) const
Returns the day number of year for the given date.
CalendarSystem
Definition: klocale.h:646
bool isLeapYear(int year) const
Returns whether a given year is a leap year.
Number padded to a required width, e.g.
Definition: klocale.h:773
Minguo Calendar, aka ROC, Republic of China or Taiwanese.
Definition: klocale.h:667
ISO Week Number.
Definition: klocale.h:683
virtual QString formatDate(const QDate &fromDate, KLocale::DateFormat toFormat=KLocale::LongDate) const
Returns a string formatted to the current locale&#39;s conventions regarding dates.
int monthsInYear(const QDate &date) const
Returns number of months in the given year.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool exists() const
Week 1 starts Jan 1st ends day before first Week Start Day in year.
Definition: klocale.h:685
Jalali Calendar, aka Persian or Iranian, also used in Afghanistan.
Definition: klocale.h:661
qint64 toJulianDay() const const
int toInt(bool *ok, int base) const const
bool isEmpty() const const
The Day Of Year portion of a date, may be number or name.
Definition: klocale.h:739
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
Long text format, e.g.
Definition: klocale.h:777
WeekNumberSystem
Definition: klocale.h:681
bool isValid() const const
virtual int month(const QDate &date) const
Returns the month portion of a given date in the current calendar system.
int week(const QDate &date, int *yearNum) const
Returns the localized Week Number for the date.
int yearsDifference(const QDate &fromDate, const QDate &toDate) const
Returns the difference between two dates in completed calendar years.
ISO-8601 Ordinal Date format YYYY-DDD, e.g.
Definition: klocale.h:794
void dateDifference(const QDate &fromDate, const QDate &toDate, int *yearsDiff, int *monthsDiff, int *daysDiff, int *direction) const
Returns the difference between two dates in years, months and days.
ReadDateFlags
Flags for readDate()
Definition: klocale.h:1108
const KLocale * locale() const
Returns the locale used for translations and formats for this calendar system instance.
WeekDayNameFormat
Format for returned month / day name.
Short name possessive format, e.g.
DateTimeComponent
Definition: klocale.h:728
KDE Standard.
Definition: klocale.h:695
Only accept a date string in ISO Week date format (YYYY-Www-D)
Definition: klocale.h:1115
static KLocale * global()
Return the global KLocale instance.
Definition: klocale.cpp:309
KDE Default, proleptic Gregorian Calendar as used by QDate.
Definition: klocale.h:647
The Month Name portion of a date.
Definition: klocale.h:732
Narrow name format, e.g.
virtual QString monthString(const QDate &date, StringFormat format=LongFormat) const
QString calendarLabel() const
QString toLower() const const
int monthsDifference(const QDate &fromDate, const QDate &toDate) const
Returns the difference between two dates in completed calendar months The returned value will be nega...
The system locale default.
Definition: klocale.h:682
QString eraYear(const QDate &date, StringFormat format=ShortFormat) const
bool isValid(int year, int month, int day) const
Returns whether a given date is valid in this calendar system.
char toLatin1() const const
int shortYearWindowStartYear() const
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
virtual int yearStringToInteger(const QString &sNum, int &iLength) const
bool hasKey(const QString &key) const
Short text format, e.g.
Definition: klocale.h:776
virtual int year(const QDate &date) const
Returns the year portion of a given date in the current calendar system.
The Era and Year portion of a date.
Definition: klocale.h:737
Narrow name format, e.g.
QString i18n(const char *text, const TYPE &arg...)
KConfigGroup group(const QString &group)
static KCalendarSystem * create(KLocale::CalendarSystem calendarSystem, const KLocale *locale)
static QDate currentLocalDate()
Returns the current date in the local time zone, as reported by the system clock. ...
Definition: kdatetime.cpp:1330
int yearInEra(const QDate &date) const
KLocalizedString KI18N_EXPORT ki18nc(const char *context, const char *text)
QStringList languageList() const
Returns the language codes selected by user, ordered by decreasing priority.
Definition: klocale.cpp:376
Short name format, e.g.
Same as ShortDate for dates a week or more ago.
Definition: klocale.h:786
virtual QDate addMonths(const QDate &date, int nmonths) const
Returns a QDate containing a date nmonths months later.
Long string format, e.g.
QString mid(int position, int n) const const
virtual QString monthName(int month, int year, MonthNameFormat format=LongName) const =0
Gets specific calendar type month name for a given month number If an invalid month is specified...
int daysInYear(const QDate &date) const
Returns the number of days in the given year.
KLocale provides support for language and country specific stuff.
Definition: klocale.h:75
Only accept a date string in the locale LongDate format.
Definition: klocale.h:1109
DateTimeFormatStandard
Definition: klocale.h:694
The Day Name portion of a date.
Definition: klocale.h:734
QDate firstDayOfMonth(int year, int month) const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
const QChar at(int position) const const
virtual bool julianDayToDate(qint64 jd, int &year, int &month, int &day) const =0
Internal method to convert a Julian Day number into the YMD values for this calendar system...
int length() const const
void reserve(int size)
Short name format, e.g.
QString section(QChar sep, int start, int end, QString::SectionFlags flags) const const
ISO-8601 Date format YYYY-MM-DD, e.g.
Definition: klocale.h:792
QString fromLatin1(const char *str, int size)
Only accept a date string in ISO Week date format (YYYY-DDD)
Definition: klocale.h:1117
Week 1 starts Jan 1st ends after 7 days.
Definition: klocale.h:686
Locale Long date format, e.g.
Definition: klocale.h:785
The Days In Month portion of a date.
Definition: klocale.h:748
virtual QDate addYears(const QDate &date, int nyears) const
Returns a QDate containing a date nyears years later.
The Month portion of a date, may be number or name.
Definition: klocale.h:731
QDate addDays(qint64 ndays) const const
virtual int dayStringToInteger(const QString &sNum, int &iLength) const
DigitSet
Definition: klocale.h:176
QDate fromJulianDay(qint64 jd)
virtual QString calendarType() const =0
Same as LongDate for dates a week or more ago.
Definition: klocale.h:789
The Week Number portion of a date.
Definition: klocale.h:743
Long name format, e.g.
QDate firstDayOfYear(int year) const
int year() const const
virtual ~KCalendarSystem()
Destructor.
bool isValidIsoWeekDate(int year, int isoWeekNumber, int dayOfIsoWeek) const
virtual QString dayString(const QDate &date, StringFormat format=LongFormat) const
void getDate(const QDate date, int *year, int *month, int *day) const
The Julian Day of a date.
Definition: klocale.h:735
Thai Calendar, aka Buddhist or Thai Buddhist.
Definition: klocale.h:668
virtual bool setDate(QDate &date, int year, int month, int day) const
Changes the date&#39;s year, month and day.
T readEntry(const QString &key, const T &aDefault) const
Julian Calendar, as used in Orthodox Churches.
Definition: klocale.h:666
Long name format, e.g.
int dayOfWeek(const QDate &date) const
Returns the weekday number for the given date.
Only accept a date string in the locale ShortDate format.
Definition: klocale.h:1111
Islamic Civil Calendar, aka Hijri, not the Lunar Calendar.
Definition: klocale.h:657
static QList< KLocale::CalendarSystem > calendarSystemsList()
bool isLetterOrNumber() const const
int daysInMonth(const QDate &date) const
Returns the number of days in the given month.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Nov 26 2020 22:57:05 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.