1/****************************************************************************
2**
3** Copyright (C) 2020 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#include "qcalendar.h"
40#include "qcalendarbackend_p.h"
41#include "qgregoriancalendar_p.h"
42#ifndef QT_BOOTSTRAPPED
43#include "qjuliancalendar_p.h"
44#include "qmilankoviccalendar_p.h"
45#endif
46#if QT_CONFIG(jalalicalendar)
47#include "qjalalicalendar_p.h"
48#endif
49#if QT_CONFIG(islamiccivilcalendar)
50#include "qislamiccivilcalendar_p.h"
51#endif
52
53#include "qdatetime.h"
54#include "qcalendarmath_p.h"
55#include <qhash.h>
56#include <qdebug.h>
57
58#include <vector>
59
60QT_BEGIN_NAMESPACE
61
62static const QCalendarBackend *backendFromEnum(QCalendar::System system);
63
64namespace {
65
66struct CalendarName : public QString
67{
68 CalendarName(const QString &name) : QString(name) {}
69};
70
71inline bool operator==(const CalendarName &u, const CalendarName &v)
72{
73 return u.compare(v, Qt::CaseInsensitive) == 0;
74}
75
76inline size_t qHash(const CalendarName &key, size_t seed = 0) noexcept
77{
78 return qHash(key.toLower(), seed);
79}
80
81struct Registry {
82 std::vector<QCalendarBackend *> byId;
83 QHash<CalendarName, QCalendarBackend *> byName;
84 QCalendarBackend *gregorianCalendar = nullptr;
85 bool populated = false;
86
87 Registry()
88 {
89 byId.resize(int(QCalendar::System::Last) + 1);
90 }
91
92 ~Registry()
93 {
94 qDeleteAll(byId);
95 }
96
97 bool registerName(QCalendarBackend *calendar, const QString &name)
98 {
99 if (byName.find(name) != byName.end()) {
100 qWarning() << "Calendar name" << name
101 << "is already taken, new calendar will not be registered.";
102 return false;
103 }
104 byName.insert(name, calendar);
105 return true;
106 }
107 void addCalendar(QCalendarBackend *calendar, const QString &name, QCalendar::System id)
108 {
109 if (!registerName(calendar, name))
110 return;
111 Q_ASSERT(byId.size() >= size_t(id));
112 if (id == QCalendar::System::User) {
113 byId.push_back(calendar);
114 } else {
115 Q_ASSERT(byId[size_t(id)] == nullptr);
116 byId[size_t(id)] = calendar;
117 }
118 if (id == QCalendar::System::Gregorian) {
119 Q_ASSERT(!gregorianCalendar);
120 gregorianCalendar = calendar;
121 }
122 }
123 /*
124 \internal
125 Ensures each \c{enum}-available calendar has been instantiated.
126
127 This arranges for each to register itself by name; it only does anything on
128 its first call, which ensures that name-based lookups can always find all
129 the calendars available via the \c enum.
130 */
131 void populate()
132 {
133 if (populated)
134 return;
135
136 for (int i = 0; i <= int(QCalendar::System::Last); ++i) {
137 if (!byId[i])
138 (void)backendFromEnum(QCalendar::System(i));
139 }
140
141 populated = true;
142 }
143};
144
145}
146
147Q_GLOBAL_STATIC(Registry, calendarRegistry);
148
149static const QCalendarBackend *backendFromEnum(QCalendar::System system)
150{
151 switch (system) {
152 case QCalendar::System::Gregorian:
153 return new QGregorianCalendar;
154#ifndef QT_BOOTSTRAPPED
155 case QCalendar::System::Julian:
156 return new QJulianCalendar;
157 case QCalendar::System::Milankovic:
158 return new QMilankovicCalendar;
159#endif
160#if QT_CONFIG(jalalicalendar)
161 case QCalendar::System::Jalali:
162 return new QJalaliCalendar;
163#endif
164#if QT_CONFIG(islamiccivilcalendar)
165 case QCalendar::System::IslamicCivil:
166 return new QIslamicCivilCalendar;
167#else // When highest-numbered system isn't enabled, ensure we have a case for Last:
168 case QCalendar::System::Last:
169#endif
170 case QCalendar::System::User:
171 Q_UNREACHABLE();
172 }
173 return nullptr;
174}
175
176/*!
177 \since 5.14
178
179 \class QCalendarBackend
180 \inmodule QtCore
181 \internal
182 \reentrant
183 \brief The QCalendarBackend class provides basic calendaring functions.
184
185 QCalendarBackend provides the base class on which all calendar types are
186 implemented. On construction, the backend is registered with its primary
187 name.
188
189 A backend may also be registered with aliases, where the calendar is known
190 by several names. Registering with the name used by CLDR (the Unicode
191 consortium's Common Locale Data Repository) is recommended, particularly
192 when interacting with third-party software. Once a backend is registered for
193 a name, QCalendar can be constructed using that name to select the backend.
194
195 Each calendar backend must inherit from QCalendarBackend and implement its
196 pure virtual methods. It may also override some other virtual methods, as
197 needed.
198
199 Most backends are pure code, with no data elements. Such backends should
200 normally be implemented as singletons. For a backend to be added to the
201 QCalendar::System \c enum, it should be such a singleton, with a case in
202 backendFromEnum()'s switch statement (above) to instantiate it.
203
204 Non-singleton calendar backends should ensure that each instance is created
205 with a distinct primary name. Later instances attempting to register with a
206 name already in use shall fail to register and be unavailable to QCalendar,
207 hence unusable.
208
209 \sa registerAlias(), QDate, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
210*/
211
212/*!
213 Constructs the calendar and registers it under \a name using \a id.
214*/
215QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System id)
216{
217 calendarRegistry->addCalendar(this, name, id);
218}
219
220/*!
221 Destroys the calendar.
222
223 Never call this from user code. Each calendar backend, once instantiated,
224 shall exist for the lifetime of the program. Its destruction is taken care
225 of by destruction of the registry of calendar backends and their names.
226*/
227QCalendarBackend::~QCalendarBackend()
228{
229}
230
231/*!
232 The calendar system of this calendar.
233
234 Each calendar backend constructible from the QCalendar::System \c enum
235 should return the member of that \c enum that produces it. Other calendars
236 should return User.
237
238 \sa QCalendarBackend::fromEnum()
239*/
240QCalendar::System QCalendarBackend::calendarSystem() const
241{
242 return QCalendar::System::User;
243}
244
245/*!
246 \fn QString QCalendarBackend::name() const;
247
248 This pure virtual method should be overloaded by each backend implementation
249 to return the name that the backend passes to the base-class as its name.
250*/
251
252/*!
253 The primary name of this calendar.
254*/
255QString QCalendar::name() const
256{
257 return d ? d->name() : QString();
258}
259
260// date queries
261/*!
262 \fn int QCalendarBackend::daysInMonth(int month, int year) const
263
264 Returns number of days in the month number \a month, in year \a year.
265
266 An implementation should return 0 if the given year had no such month. If
267 year is QCalendar::Unspecified, return the usual number of days for the
268 month, in those years that include it.
269
270 Calendars with intercallary days may represent these as extra days of the
271 preceding month, or as short months separate from the usual ones. In the
272 former case, daysInMonth(month, year) should be the number of ordinary days
273 in the month, although \c{isDateValid(year, month, day)} might return \c true
274 for some larger values of \c day.
275
276 \sa daysInYear(), monthsInYear(), minimumDaysInMonth(), maximumDaysInMonth()
277*/
278
279// properties of the calendar
280
281/*!
282 \fn bool QCalendarBackend::isLeapYear(int year) const
283
284 Returns \c true if the specified \a year is a leap year for this calendar.
285
286 \sa daysInYear(), isDateValid()
287*/
288
289/*!
290 \fn bool QCalendarBackend::isLunar() const
291
292 Returns \c true if this calendar is a lunar calendar. Otherwise returns \c
293 false.
294
295 A lunar calendar is a calendar based upon the monthly cycles of the Moon's
296 phases (synodic months). This contrasts with solar calendars, whose annual
297 cycles are based only upon the solar year.
298
299 \sa isLuniSolar(), isSolar(), isProleptic()
300*/
301
302/*!
303 \fn bool QCalendarBackend::isLuniSolar() const
304
305 Returns \c true if this calendar is a lunisolar calendar. Otherwise returns
306 \c false.
307
308 A lunisolar calendar is a calendar whose date indicates both the moon phase
309 and the time of the solar year.
310
311 \sa isLunar(), isSolar(), isProleptic()
312*/
313
314/*!
315 \fn bool QCalendarBackend::isSolar() const
316
317 Returns \c true if this calendar is a solar calendar. Otherwise returns
318 \c false.
319
320 A solar calendar is a calendar whose dates indicate the season or almost
321 equivalently the apparent position of the sun relative to the fixed stars.
322 The Gregorian calendar, widely accepted as standard in the world,
323 is an example of solar calendar.
324
325 \sa isLuniSolar(), isLunar(), isProleptic()
326*/
327
328/*!
329 Returns the total number of days in the year number \a year.
330 Returns zero if there is no such year in this calendar.
331
332 This base implementation returns 366 for leap years and 365 for ordinary
333 years.
334
335 \sa monthsInYear(), daysInMonth(), isLeapYear()
336*/
337int QCalendarBackend::daysInYear(int year) const
338{
339 return monthsInYear(year) ? isLeapYear(year) ? 366 : 365 : 0;
340}
341
342/*!
343 Returns the total number of months in the year number \a year.
344 Returns zero if there is no such year in this calendar.
345
346 This base implementation returns 12 for any valid year.
347
348 \sa daysInYear(), maximumMonthsInYear(), isDateValid()
349*/
350int QCalendarBackend::monthsInYear(int year) const
351{
352 return year > 0 || (year < 0 ? isProleptic() : hasYearZero()) ? 12 : 0;
353}
354
355/*!
356 Returns \c true if the date specified by \a year, \a month, and \a day is
357 valid for this calendar; otherwise returns \c false. For example,
358 the date 2018-04-19 is valid for the Gregorian calendar, but 2018-16-19 and
359 2018-04-38 are invalid.
360
361 Calendars with intercallary days may represent these as extra days of the
362 preceding month or as short months separate from the usual ones. In the
363 former case, a \a day value greater than \c{daysInMonth(\a{month},
364 \a{year})} may be valid.
365
366 \sa daysInMonth(), monthsInYear()
367*/
368bool QCalendarBackend::isDateValid(int year, int month, int day) const
369{
370 return day > 0 && day <= daysInMonth(month, year);
371}
372
373/*!
374 Returns \c true if this calendar is a proleptic calendar. Otherwise returns
375 \c false.
376
377 A proleptic calendar results from allowing negative year numbers to indicate
378 years before the nominal start of the calendar system.
379
380 \sa isLuniSolar(), isSolar(), isLunar(), hasYearZero()
381*/
382
383bool QCalendarBackend::isProleptic() const
384{
385 return true;
386}
387
388/*!
389 Returns \c true if year number \c 0 is considered a valid year in this
390 calendar. Otherwise returns \c false.
391
392 \sa isDateValid(), isProleptic()
393*/
394
395bool QCalendarBackend::hasYearZero() const
396{
397 return false;
398}
399
400/*!
401 Returns the maximum number of days in a month for any year.
402
403 This base implementation returns 31, as this is a common case.
404
405 For calendars with intercallary days, although daysInMonth() doesn't include
406 the intercallary days in its count for an individual month,
407 maximumDaysInMonth() should include intercallary days, so that it is the
408 maximum value of \c day for which \c{isDateValid(year, month, day)} can be
409 true.
410
411 \sa maximumMonthsInYear(), daysInMonth()
412*/
413int QCalendarBackend::maximumDaysInMonth() const
414{
415 return 31;
416}
417
418/*!
419 Returns the minimum number of days in any valid month of any valid year.
420
421 This base implementation returns 29, as this is a common case.
422
423 \sa maximumMonthsInYear(), daysInMonth()
424*/
425int QCalendarBackend::minimumDaysInMonth() const
426{
427 return 29;
428}
429
430/*!
431 Returns the maximum number of months possible in any year.
432
433 This base implementation returns 12, as this is a common case.
434
435 \sa maximumDaysInMonth(), monthsInYear()
436*/
437int QCalendarBackend::maximumMonthsInYear() const
438{
439 return 12;
440}
441
442// Julian day number calculations
443
444/*!
445 \fn bool QCalendarBackend::dateToJulianDay(int year, int month, int day, qint64 *jd) const
446
447 Computes the Julian day number corresponding to the specified \a year, \a
448 month, and \a day. Returns true and sets \a jd if there is such a date in
449 this calendar; otherwise, returns false.
450
451 \sa QCalendar::partsFromDate(), julianDayToDate()
452*/
453
454/*!
455 \fn QCalendar::YearMonthDay QCalendarBackend::julianDayToDate(qint64 jd) const
456
457 Computes the year, month, and day in this calendar for the given Julian day
458 number \a jd. If the given day falls outside this calendar's scope
459 (e.g. before the start-date of a non-proleptic calendar), the returned
460 structure's isValid() is false; otherwise, its year, month, and day fields
461 provide this calendar's description of the date.
462
463 \sa QCalendar::dateFromParts(), dateToJulianDay()
464*/
465
466/*!
467 Returns the day of the week for the given Julian Day Number \a jd.
468
469 This is 1 for Monday through 7 for Sunday.
470
471 Calendars with intercallary days may return larger values for these
472 intercallary days. They should avoid using 0 for any special purpose (it is
473 already used in QDate::dayOfWeek() to mean an invalid date). The calendar
474 should treat the numbers used as an \c enum, whose values need not be
475 contiguous, nor need they follow closely from the 1 through 7 of the usual
476 returns. It suffices that weekDayName() can recognize each such number as
477 identifying a distinct name, that it returns to identify the particular
478 intercallary day.
479
480 This base implementation uses the day-numbering that various calendars have
481 borrowed off the Hebrew calendar.
482
483 \sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek()
484 */
485int QCalendarBackend::dayOfWeek(qint64 jd) const
486{
487 return QRoundingDown::qMod(jd, 7) + 1;
488}
489
490// Month and week-day name look-ups (implemented in qlocale.cpp):
491/*!
492 \fn QString QCalendarBackend::monthName(const QLocale &locale, int month, int year,
493 QLocale::FormatType format) const
494
495 Returns the name of the specified \a month in the given \a year for the
496 chosen \a locale, using the given \a format to determine how complete the
497 name is.
498
499 If \a year is Unspecified, return the name for the month that usually has
500 this number within a typical year. Calendars with a leap month that isn't
501 always the last may need to take account of the year to map the month number
502 to the particular year's month with that number.
503
504 \note Backends for which CLDR provides data can configure the default
505 implementation of the two month name look-up methods by arranging for
506 localeMonthIndexData() and localeMonthData() to provide access to the CLDR
507 data (see cldr2qlocalexml.py, qlocalexml2cpp.py and existing backends).
508 Conversely, backends that override both month name look-up methods need not
509 return anything meaningful from localeMonthIndexData() or localeMonthData().
510
511 \sa standaloneMonthName(), QLocale::monthName()
512*/
513
514/*!
515 \fn QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int year
516 QLocale::FormatType format) const
517
518 Returns the standalone name of the specified \a month in the chosen \a
519 locale, using the specified \a format to determine how complete the name is.
520
521 If \a year is Unspecified, return the standalone name for the month that
522 usually has this number within a typical year. Calendars with a leap month
523 that isn't always the last may need to take account of the year to map the
524 month number to the particular year's month with that number.
525
526 \sa monthName(), QLocale::standaloneMonthName()
527*/
528
529/*!
530 \fn QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
531 QLocale::FormatType format) const
532
533 Returns the name of the specified \a day of the week in the chosen \a
534 locale, using the specified \a format to determine how complete the name is.
535
536 The base implementation handles \a day values from 1 to 7 using the day
537 names CLDR provides, which are suitable for calendards that use the same
538 (Hebrew-derived) week as the Gregorian calendar.
539
540 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
541 need to reimplement this method to handle such extra week-day values. They
542 can assume that \a day is a value returned by the same calendar's
543 dayOfWeek().
544
545 \sa dayOfWeek(), standaloneWeekDayName(), QLocale::dayName()
546*/
547
548/*!
549 \fn QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
550 QLocale::FormatType format) const
551
552 Returns the standalone name of the specified \a day of the week in the
553 chosen \a locale, using the specified \a format to determine how complete
554 the name is.
555
556 The base implementation handles \a day values from 1 to 7 using the
557 standalone day names CLDR provides, which are suitable for calendards that
558 use the same (Hebrew-derived) week as the Gregorian calendar.
559
560 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
561 need to reimplement this method to handle such extra week-day values. They
562 can assume that \a day is a value returned by the same calendar's
563 dayOfWeek().
564
565 \sa dayOfWeek(), weekDayName(), QLocale::standaloneDayName()
566*/
567
568/*!
569 \fn QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
570 QDate dateOnly, QTime timeOnly,
571 const QLocale &locale) const
572
573 Returns a string representing a given date, time or date-time.
574
575 If \a datetime is specified and valid, it is used and both date and time
576 format tokens are converted to appropriate representations of the parts of
577 the datetime. Otherwise, if \a dateOnly is valid, only date format tokens
578 are converted; else, if \a timeOnly is valid, only time format tokens are
579 converted. If none are valid, an empty string is returned.
580
581 The specified \a locale influences how some format tokens are converted; for
582 example, when substituting day and month names and their short-forms. For
583 the supported formatting tokens, see QDate::toString() and
584 QTime::toString(). As described above, the provided date, time and date-time
585 determine which of these tokens are recognized: where these appear in \a
586 format they are replaced by data. Any text in \a format not recognized as a
587 format token is copied verbatim into the result string.
588
589 \sa QDate::toString(), QTime::toString(), QDateTime::toString()
590*/
591// End of methods implemented in qlocale.cpp
592
593/*!
594 Returns a list of names of the available calendar systems. Any
595 QCalendarBackend sub-class must be registered before being exposed to Date
596 and Time APIs.
597
598 \sa registerAlias(), fromName()
599*/
600QStringList QCalendarBackend::availableCalendars()
601{
602 if (calendarRegistry.isDestroyed())
603 return {};
604 calendarRegistry->populate();
605 return QStringList(calendarRegistry->byName.keyBegin(), calendarRegistry->byName.keyEnd());
606}
607
608/*!
609 Registers an alias for this calendar backend. Once a backend is registered,
610 its name will be included in the list of available calendars and the
611 calendar can be instantiated by name.
612
613 Returns \c false if the given \a name is already in use, otherwise it
614 registers this calendar backend and returns \c true.
615
616 \sa availableCalendars(), fromName()
617*/
618bool QCalendarBackend::registerAlias(const QString &name)
619{
620 if (calendarRegistry.isDestroyed())
621 return false;
622 return calendarRegistry->registerName(this, name);
623}
624
625/*!
626 \internal
627 Returns a pointer to a named calendar backend.
628
629 If the given \a name is present in availableCalendars(), the backend
630 matching it is returned; otherwise, \c nullptr is returned. Matching of
631 names ignores case. Note that this won't provoke construction of a calendar
632 backend, it will only return ones that have been instantiated (and not yet
633 destroyed) by some other means. However, calendars available via the
634 QCalendar::System \c enum are always registered when this is called.
635
636 \sa availableCalendars(), registerAlias(), fromEnum()
637*/
638const QCalendarBackend *QCalendarBackend::fromName(QStringView name)
639{
640 if (calendarRegistry.isDestroyed())
641 return nullptr;
642 calendarRegistry->populate();
643 auto it = calendarRegistry->byName.find(name.toString());
644 return it == calendarRegistry->byName.end() ? nullptr : *it;
645}
646
647/*!
648 \internal
649 \overload
650 */
651const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
652{
653 if (calendarRegistry.isDestroyed())
654 return nullptr;
655 calendarRegistry->populate();
656 auto it = calendarRegistry->byName.find(QString(name));
657 return it == calendarRegistry->byName.end() ? nullptr : *it;
658}
659
660/*!
661 \internal
662 Returns a pointer to a calendar backend, specified by \c enum.
663
664 This will instantiate the indicated calendar (which will enable fromName()
665 to return it subsequently), but only for the Qt-supported calendars for
666 which (where relevant) the appropriate feature has been enabled.
667*/
668const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
669{
670 if (calendarRegistry.isDestroyed() || system == QCalendar::System::User)
671 return nullptr;
672 Q_ASSERT(calendarRegistry->byId.size() >= size_t(system));
673 if (auto *c = calendarRegistry->byId[size_t(system)])
674 return c;
675 return backendFromEnum(system);
676}
677
678/*!
679 \since 5.14
680
681 \class QCalendar
682 \inmodule QtCore
683 \reentrant
684 \brief The QCalendar class describes calendar systems.
685
686 A QCalendar object maps a year, month, and day-number to a specific day
687 (ultimately identified by its Julian day number), using the rules of a
688 particular system.
689
690 The default QCalendar() is a proleptic Gregorian calendar, which has no year
691 zero. Other calendars may be supported by enabling suitable features or
692 loading plugins. Calendars supported as features can be constructed by
693 passing the QCalendar::System enumeration to the constructor. All supported
694 calendars may be constructed by name, once they have been constructed. (Thus
695 plugins instantiate their calendar backend to register it.) Built-in
696 backends, accessible via QCalendar::System, are also always available by
697 name.
698
699 A QCalendar value is immutable.
700
701 \sa QDate, QDateTime
702*/
703
704/*!
705 \enum QCalendar::System
706
707 This enumerated type is used to specify a choice of calendar system.
708
709 \value Gregorian The default calendar, used internationally.
710 \value Julian An ancient Roman calendar with too few leap years.
711 \value Milankovic A revised Julian calendar used by some Orthodox churches.
712 \value Jalali The Solar Hijri calendar (also called Persian).
713 \value IslamicCivil The (tabular) Islamic Civil calendar.
714 \omitvalue Last
715 \omitvalue User
716
717 \sa QCalendar
718*/
719
720/*!
721 \fn QCalendar::QCalendar()
722 \fn QCalendar::QCalendar(QCalendar::System system)
723 \fn QCalendar::QCalendar(QLatin1String name)
724 \fn QCalendar::QCalendar(QStringView name)
725
726 Constructs a calendar object.
727
728 The choice of calendar to use may be indicated as \a system, using the
729 enumeration QCalendar::System, or by \a name, using a string (either Unicode
730 or Latin 1). Construction by name may depend on an instance of the given
731 calendar being constructed by other means first. With no argument, the
732 default constructor returns the Gregorian calendar.
733
734 \sa QCalendar, System, isValid()
735*/
736
737QCalendar::QCalendar()
738 : d(nullptr)
739{
740 if (calendarRegistry.isDestroyed())
741 return;
742 d = calendarRegistry->gregorianCalendar;
743 if (!d)
744 d = new QGregorianCalendar;
745}
746
747QCalendar::QCalendar(QCalendar::System system)
748 : d(QCalendarBackend::fromEnum(system))
749{
750 Q_ASSERT(d);
751}
752
753QCalendar::QCalendar(QLatin1String name)
754 : d(QCalendarBackend::fromName(name)) {}
755
756QCalendar::QCalendar(QStringView name)
757 : d(QCalendarBackend::fromName(name)) {}
758
759/*!
760 \fn bool QCalendar::isValid() const
761
762 Returns true if this is a valid calendar object.
763
764 Constructing a calendar with an unrecognised calendar name may result in an
765 invalid object. Use this method to check after creating a calendar by name.
766*/
767
768// Date queries:
769
770/*!
771 Returns the number of days in the given \a month of the given \a year.
772
773 Months are numbered consecutively, starting with 1 for the first month of
774 each year. If \a year is \c Unspecified (its default, if not passed), the
775 month's length in a normal year is returned.
776
777 \sa maximumDaysInMonth(), minimumDaysInMonth()
778*/
779int QCalendar::daysInMonth(int month, int year) const
780{
781 return d ? d->daysInMonth(month, year) : 0;
782}
783
784/*!
785 Returns the number of days in the given \a year.
786
787 Handling of \c Unspecified as \a year is undefined.
788*/
789int QCalendar::daysInYear(int year) const
790{
791 return d ? d->daysInYear(year) : 0;
792}
793
794/*!
795 Returns the number of months in the given \a year.
796
797 If \a year is \c Unspecified, returns the maximum number of months in a
798 year.
799
800 \sa maximumMonthsInYear()
801*/
802int QCalendar::monthsInYear(int year) const
803{
804 return d ? year == Unspecified ? d->maximumMonthsInYear() : d->monthsInYear(year) : 0;
805}
806
807/*!
808 Returns \c true precisely if the given \a year, \a month, and \a day specify
809 a valid date in this calendar.
810
811 Usually this means 1 <= month <= monthsInYear(year) and 1 <= day <=
812 daysInMonth(month, year). However, calendars with intercallary days or
813 months may complicate that.
814*/
815bool QCalendar::isDateValid(int year, int month, int day) const
816{
817 return d && d->isDateValid(year, month, day);
818}
819
820// properties of the calendar
821
822/*!
823 Returns \c true if this calendar object is the Gregorian calendar object
824 used as default calendar by other Qt APIs, e.g. in QDate.
825*/
826bool QCalendar::isGregorian() const
827{
828 Q_ASSERT(!calendarRegistry.isDestroyed());
829 return d == calendarRegistry->gregorianCalendar;
830}
831
832/*!
833 Returns \c true if the given \a year is a leap year.
834
835 Since the year is not a whole number of days long, some years are longer
836 than others. The difference may be a whole month or just a single day; the
837 details vary between calendars.
838
839 \sa isDateValid()
840*/
841bool QCalendar::isLeapYear(int year) const
842{
843 return d && d->isLeapYear(year);
844}
845
846/*!
847 Returns \c true if this calendar is a lunar calendar.
848
849 A lunar calendar is one based primarily on the phases of the moon.
850*/
851bool QCalendar::isLunar() const
852{
853 return d && d->isLunar();
854}
855
856/*!
857 Returns \c true if this calendar is luni-solar.
858
859 A luni-solar calendar expresses the phases of the moon but adapts itself to
860 also keep track of the Sun's varying position in the sky, relative to the
861 fixed stars.
862*/
863bool QCalendar::isLuniSolar() const
864{
865 return d && d->isLuniSolar();
866}
867
868/*!
869 Returns \c true if this calendar is solar.
870
871 A solar calendar is based primarily on the Sun's varying position in the
872 sky, relative to the fixed stars.
873*/
874bool QCalendar::isSolar() const
875{
876 return d && d->isSolar();
877}
878
879/*!
880 Returns \c true if this calendar is proleptic.
881
882 A proleptic calendar is able to describe years arbitrarily long before its
883 first. These are represented by negative year numbers and possibly by a year
884 zero.
885
886 \sa hasYearZero()
887*/
888bool QCalendar::isProleptic() const
889{
890 return d && d->isProleptic();
891}
892
893/*!
894 Returns \c true if this calendar has a year zero.
895
896 A calendar may represent years from its first year onwards but provide no
897 way to describe years before its first; such a calendar has no year zero and
898 is not proleptic.
899
900 A calendar which represents years before its first may number these years
901 simply by following the usual integer counting, so that the year before the
902 first is year zero, with negative-numbered years preceding this; such a
903 calendar is proleptic and has a year zero. A calendar might also have a year
904 zero (for example, the year of some great event, with subsequent years being
905 the first year after that event, the second year after, and so on) without
906 describing years before its year zero. Such a calendar would have a year
907 zero without being proleptic.
908
909 Some calendars, however, represent years before their first by an alternate
910 numbering; for example, the proleptic Gregorian calendar's first year is 1
911 CE and the year before it is 1 BCE, preceded by 2 BCE and so on. In this
912 case, we use negative year numbers for this alternate numbering, with year
913 -1 as the year before year 1, year -2 as the year before year -1 and so
914 on. Such a calendar is proleptic but has no year zero.
915
916 \sa isProleptic()
917*/
918bool QCalendar::hasYearZero() const
919{
920 return d && d->hasYearZero();
921}
922
923/*!
924 Returns the number of days in the longest month in the calendar, in any year.
925
926 \sa daysInMonth(), minimumDaysInMonth()
927*/
928int QCalendar::maximumDaysInMonth() const
929{
930 return d ? d->maximumDaysInMonth() : 0;
931}
932
933/*!
934 Returns the number of days in the shortest month in the calendar, in any year.
935
936 \sa daysInMonth(), maximumDaysInMonth()
937*/
938int QCalendar::minimumDaysInMonth() const
939{
940 return d ? d->minimumDaysInMonth() : 0;
941}
942
943/*!
944 Returns the largest number of months that any year may contain.
945
946 \sa monthName(), standaloneMonthName(), monthsInYear()
947*/
948int QCalendar::maximumMonthsInYear() const
949{
950 return d ? d->maximumMonthsInYear() : 0;
951}
952
953// Julian Day conversions:
954
955/*!
956 \fn QDate QCalendar::dateFromParts(int year, int month, int day) const
957 \fn QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
958
959 Converts a year, month, and day to a QDate.
960
961 The \a year, \a month, and \a day may be passed as separate numbers or
962 packaged together as the members of \a parts. Returns a QDate with the given
963 year, month, and day of the month in this calendar, if there is one.
964 Otherwise, including the case where any of the values is
965 QCalendar::Unspecified, returns a QDate whose isNull() is true.
966
967 \sa isDateValid(), partsFromDate()
968*/
969QDate QCalendar::dateFromParts(int year, int month, int day) const
970{
971 qint64 jd;
972 return d && d->dateToJulianDay(year, month, day, &jd)
973 ? QDate::fromJulianDay(jd) : QDate();
974}
975
976QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
977{
978 return parts.isValid() ? dateFromParts(parts.year, parts.month, parts.day) : QDate();
979}
980
981/*!
982 Converts a QDate to a year, month, and day of the month.
983
984 The returned structure's isValid() shall be false if the calendar is unable
985 to represent the given \a date. Otherwise its year, month, and day
986 members record the so-named parts of its representation.
987
988 \sa dateFromParts(), isProleptic(), hasYearZero()
989*/
990QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
991{
992 return d ? d->julianDayToDate(date.toJulianDay()) : YearMonthDay();
993}
994
995/*!
996 Returns the day of the week number for the given \a date.
997
998 Returns zero if the calendar is unable to represent the indicated date.
999 Returns 1 for Monday through 7 for Sunday. Calendars with intercallary days
1000 may use other numbers to represent these.
1001
1002 \sa partsFromDate(), Qt::DayOfWeek
1003*/
1004int QCalendar::dayOfWeek(QDate date) const
1005{
1006 return d ? d->dayOfWeek(date.toJulianDay()) : 0;
1007}
1008
1009// Locale data access
1010
1011/*!
1012 Returns a suitably localised name for a month.
1013
1014 The month is indicated by a number, with \a month = 1 meaning the first
1015 month of the year and subsequent months numbered accordingly. Returns an
1016 empty string if the \a month number is unrecognized.
1017
1018 The \a year may be Unspecified, in which case the mapping from numbers to
1019 names for a typical year's months should be used. Some calendars have leap
1020 months that aren't always at the end of the year; their mapping of month
1021 numbers to names may then depend on the placement of a leap month. Thus the
1022 year should normally be specified, if known.
1023
1024 The name is returned in the form that would normally be used in a full date,
1025 in the specified \a locale; the \a format determines how fully it shall be
1026 expressed (i.e. to what extent it is abbreviated).
1027
1028 \sa standaloneMonthName(), maximumMonthsInYear(), dateTimeToString()
1029*/
1030QString QCalendar::monthName(const QLocale &locale, int month, int year,
1031 QLocale::FormatType format) const
1032{
1033 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1034 if (!d || month < 1 || month > maxMonth)
1035 return QString();
1036
1037 return d->monthName(locale, month, year, format);
1038}
1039
1040/*!
1041 Returns a suitably localised standalone name for a month.
1042
1043 The month is indicated by a number, with \a month = 1 meaning the first
1044 month of the year and subsequent months numbered accordingly. Returns an
1045 empty string if the \a month number is unrecognized.
1046
1047 The \a year may be Unspecified, in which case the mapping from numbers to
1048 names for a typical year's months should be used. Some calendars have leap
1049 months that aren't always at the end of the year; their mapping of month
1050 numbers to names may then depend on the placement of a leap month. Thus the
1051 year should normally be specified, if known.
1052
1053 The name is returned in the form that would be used in isolation in the
1054 specified \a locale; the \a format determines how fully it shall be
1055 expressed (i.e. to what extent it is abbreviated).
1056
1057 \sa monthName(), maximumMonthsInYear(), dateTimeToString()
1058*/
1059QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
1060 QLocale::FormatType format) const
1061{
1062 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1063 if (!d || month < 1 || month > maxMonth)
1064 return QString();
1065
1066 return d->standaloneMonthName(locale, month, year, format);
1067}
1068
1069/*!
1070 Returns a suitably localised name for a day of the week.
1071
1072 The days of the week are numbered from 1 for Monday through 7 for
1073 Sunday. Some calendars may support higher numbers for other days
1074 (e.g. intercallary days, that are not part of any week). Returns an empty
1075 string if the \a day number is unrecognized.
1076
1077 The name is returned in the form that would normally be used in a full date,
1078 in the specified \a locale; the \a format determines how fully it shall be
1079 expressed (i.e. to what extent it is abbreviated).
1080
1081 \sa standaloneWeekDayName(), dayOfWeek()
1082*/
1083QString QCalendar::weekDayName(const QLocale &locale, int day,
1084 QLocale::FormatType format) const
1085{
1086 return d ? d->weekDayName(locale, day, format) : QString();
1087}
1088
1089/*!
1090 Returns a suitably localised standalone name for a day of the week.
1091
1092 The days of the week are numbered from 1 for Monday through 7 for
1093 Sunday. Some calendars may support higher numbers for other days
1094 (e.g. intercallary days, that are not part of any week). Returns an empty
1095 string if the \a day number is unrecognized.
1096
1097 The name is returned in the form that would be used in isolation (for
1098 example as a column heading in a calendar's tabular display of a month with
1099 successive weeks as rows) in the specified \a locale; the \a format
1100 determines how fully it shall be expressed (i.e. to what extent it is
1101 abbreviated).
1102
1103 \sa weekDayName(), dayOfWeek()
1104*/
1105QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
1106 QLocale::FormatType format) const
1107{
1108 return d ? d->standaloneWeekDayName(locale, day, format) : QString();
1109}
1110
1111/*!
1112 Returns a string representing a given date, time or date-time.
1113
1114 If \a datetime is valid, it is represented and format specifiers for both
1115 date and time fields are recognized; otherwise, if \a dateOnly is valid, it
1116 is represented and only format specifiers for date fields are recognized;
1117 finally, if \a timeOnly is valid, it is represented and only format
1118 specifiers for time fields are recognized. If none of these is valid, an
1119 empty string is returned.
1120
1121 See QDate::toString and QTime::toString() for the supported field
1122 specifiers. Characters in \a format that are recognized as field specifiers
1123 are replaced by text representing appropriate data from the date and/or time
1124 being represented. The texts to represent them may depend on the \a locale
1125 specified. Other charagers in \a format are copied verbatim into the
1126 returned string.
1127
1128 \sa monthName(), weekDayName(), QDate::toString(), QTime::toString()
1129*/
1130QString QCalendar::dateTimeToString(QStringView format, const QDateTime &datetime,
1131 QDate dateOnly, QTime timeOnly,
1132 const QLocale &locale) const
1133{
1134 return d ? d->dateTimeToString(format, datetime, dateOnly, timeOnly, locale) : QString();
1135}
1136
1137/*!
1138 Returns a list of names of the available calendar systems.
1139
1140 These may be supplied by plugins or other code linked into an application,
1141 in addition to the ones provided by Qt, some of which are controlled by
1142 features.
1143*/
1144QStringList QCalendar::availableCalendars()
1145{
1146 return QCalendarBackend::availableCalendars();
1147}
1148
1149QT_END_NAMESPACE
1150