1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#include "qcalendar.h"
4#include "qcalendarbackend_p.h"
5#include "qgregoriancalendar_p.h"
6#ifndef QT_BOOTSTRAPPED
7#include "qjuliancalendar_p.h"
8#include "qmilankoviccalendar_p.h"
9#endif
10#if QT_CONFIG(jalalicalendar)
11#include "qjalalicalendar_p.h"
12#endif
13#if QT_CONFIG(islamiccivilcalendar)
14#include "qislamiccivilcalendar_p.h"
15#endif
16
17#include <private/qflatmap_p.h>
18#include "qatomic.h"
19#include "qdatetime.h"
20#include "qcalendarmath_p.h"
21#include <qhash.h>
22#include <qreadwritelock.h>
23
24#include <vector>
25
26QT_BEGIN_NAMESPACE
27
28struct QCalendarRegistryCaseInsensitiveAnyStringViewLessThan
29{
30 struct is_transparent {};
31 bool operator()(QAnyStringView lhs, QAnyStringView rhs) const
32 {
33 return QAnyStringView::compare(lhs, rhs, cs: Qt::CaseInsensitive) < 0;
34 }
35};
36
37namespace QtPrivate {
38
39/*
40 \internal
41 Handles calendar backend registration.
42*/
43class QCalendarRegistry
44{
45 Q_DISABLE_COPY_MOVE(QCalendarRegistry); // This is a singleton.
46
47 static constexpr qsizetype ExpectedNumberOfBackends = qsizetype(QCalendar::System::Last) + 1;
48
49 /*
50 Lock protecting the registry from concurrent modification.
51 */
52 QReadWriteLock lock;
53
54 /*
55 Vector containing all registered backends.
56
57 The indices 0 to \c QCalendar::System::Last inclusive are allocated
58 for system backends and always present (but may be null).
59 */
60 std::vector<QCalendarBackend *> byId;
61
62 /*
63 Backends registered by name.
64
65 Each backend may be registered with several names associated with it.
66 The names are case-insensitive.
67 */
68 QFlatMap<
69 QString, QCalendarBackend *,
70 QCalendarRegistryCaseInsensitiveAnyStringViewLessThan,
71 QStringList,
72 std::vector<QCalendarBackend *>
73 > byName;
74
75 /*
76 Pointer to the Gregorian backend for faster lockless access to it.
77
78 This pointer may be null if the Gregorian backend is not yet registered.
79 This pointer may only be set once and only when write lock is held on
80 the registry.
81 */
82 QAtomicPointer<const QCalendarBackend> gregorianCalendar = nullptr;
83
84 enum : int {
85 Unpopulated, // The standard backends may not yet be created
86 Populated, // All standard backends were created
87 IsBeingDestroyed, // The registry and the backends are being destroyed
88 };
89
90 /*
91 Fast way to check whether the standard calendars were populated.
92
93 The status should only be changed while the write lock is held.
94 */
95 QAtomicInt status = Unpopulated;
96
97 void ensurePopulated();
98 QCalendarBackend *registerSystemBackendLockHeld(QCalendar::System system);
99 void registerBackendLockHeld(QCalendarBackend *backend, const QStringList &names,
100 QCalendar::System system);
101
102public:
103 QCalendarRegistry()
104 {
105 byId.resize(new_size: ExpectedNumberOfBackends);
106 byName.reserve(s: ExpectedNumberOfBackends * 2); // assume one alias on average
107 }
108
109 ~QCalendarRegistry();
110
111 bool isBeingDestroyed() const { return status.loadRelaxed() == IsBeingDestroyed; }
112
113 void registerCustomBackend(QCalendarBackend *backend, const QStringList &names);
114
115 QStringList availableCalendars();
116
117 /*
118 Returns backend for Gregorian calendar.
119
120 The backend is returned without locking the registry if possible.
121 */
122 const QCalendarBackend *gregorian()
123 {
124 const QCalendarBackend *backend = gregorianCalendar.loadAcquire();
125 if (Q_LIKELY(backend != nullptr))
126 return backend;
127 return fromEnum(system: QCalendar::System::Gregorian);
128 }
129
130 /*
131 Returns \a true if the argument matches the registered Gregorian backend.
132
133 \a backend should not be \nullptr.
134 */
135 bool isGregorian(const QCalendarBackend *backend) const
136 {
137 return backend == gregorianCalendar.loadRelaxed();
138 }
139
140 const QCalendarBackend *fromName(QAnyStringView name);
141 const QCalendarBackend *fromIndex(size_t index);
142 const QCalendarBackend *fromEnum(QCalendar::System system);
143
144 QStringList backendNames(const QCalendarBackend *backend);
145};
146
147/*
148 Destroy the registry.
149
150 This destroys all registered backends. This destructor should only be called
151 in a single-threaded context at program exit.
152*/
153QCalendarRegistry::~QCalendarRegistry()
154{
155 QWriteLocker locker(&lock);
156
157 status.storeRelaxed(newValue: IsBeingDestroyed);
158
159 qDeleteAll(c: byId);
160}
161
162/*
163 Registers a custom backend.
164
165 A new unique ID is allocated for the \a backend. The registry takes
166 ownership of the \a backend.
167
168 The \a names of the backend are also registered. Already registered
169 names are not updated.
170
171 The \a backend should not be already registered.
172
173 The \a backend should be fully initialized. It becomes available
174 to other threads before this function returns.
175*/
176void QCalendarRegistry::registerCustomBackend(QCalendarBackend *backend, const QStringList &names)
177{
178 Q_ASSERT(!backend->calendarId().isValid());
179
180 ensurePopulated();
181
182 QWriteLocker locker(&lock);
183 registerBackendLockHeld(backend, names, system: QCalendar::System::User);
184}
185
186/*
187 Ensures all system calendars have been instantiated.
188
189 This arranges for each system backend to be registered. The method only
190 does anything on its first call, which ensures that name-based lookups can
191 always find all the calendars available via the \c QCalendar::System other
192 than \c QCalendar::System::User.
193*/
194void QCalendarRegistry::ensurePopulated()
195{
196 if (Q_LIKELY(status.loadAcquire() != Unpopulated))
197 return;
198
199 QWriteLocker locker(&lock);
200 if (status.loadAcquire() != Unpopulated)
201 return;
202
203 for (int i = 0; i <= int(QCalendar::System::Last); ++i) {
204 if (byId[i] == nullptr)
205 registerSystemBackendLockHeld(system: QCalendar::System(i));
206 }
207
208#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
209 auto oldValue = status.fetchAndStoreRelease(newValue: Populated);
210 Q_ASSERT(oldValue == Unpopulated);
211#else
212 status.storeRelease(Populated);
213#endif
214}
215
216/*
217 Helper functions for system backend registration.
218
219 This function must be called with write lock held on the registry.
220
221 \sa registerSystemBackend
222*/
223QCalendarBackend *QCalendarRegistry::registerSystemBackendLockHeld(QCalendar::System system)
224{
225 Q_ASSERT(system != QCalendar::System::User);
226
227 QCalendarBackend *backend = nullptr;
228 QStringList names;
229
230 switch (system) {
231 case QCalendar::System::Gregorian:
232 backend = new QGregorianCalendar;
233 names = QGregorianCalendar::nameList();
234 break;
235#ifndef QT_BOOTSTRAPPED
236 case QCalendar::System::Julian:
237 backend = new QJulianCalendar;
238 names = QJulianCalendar::nameList();
239 break;
240 case QCalendar::System::Milankovic:
241 backend = new QMilankovicCalendar;
242 names = QMilankovicCalendar::nameList();
243 break;
244#endif
245#if QT_CONFIG(jalalicalendar)
246 case QCalendar::System::Jalali:
247 backend = new QJalaliCalendar;
248 names = QJalaliCalendar::nameList();
249 break;
250#endif
251#if QT_CONFIG(islamiccivilcalendar)
252 case QCalendar::System::IslamicCivil:
253 backend = new QIslamicCivilCalendar;
254 names = QIslamicCivilCalendar::nameList();
255 break;
256#else // When highest-numbered system isn't enabled, ensure we have a case for Last:
257 case QCalendar::System::Last:
258#endif
259 case QCalendar::System::User:
260 Q_UNREACHABLE();
261 }
262 if (!backend)
263 return nullptr;
264
265 registerBackendLockHeld(backend, names, system);
266 Q_ASSERT(backend == byId[size_t(system)]);
267
268 return backend;
269}
270
271/*
272 Helper function for backend registration.
273
274 This function must be called with write lock held on the registry.
275
276 \sa registerBackend
277*/
278void QCalendarRegistry::registerBackendLockHeld(QCalendarBackend *backend, const QStringList &names,
279 QCalendar::System system)
280{
281 Q_ASSERT(!backend->calendarId().isValid());
282
283 auto index = size_t(system);
284
285 // Note: it is important to update the calendar ID before making
286 // the calendar available for queries.
287 if (system == QCalendar::System::User) {
288 backend->setIndex(byId.size());
289 byId.push_back(x: backend);
290 } else if (byId[index] == nullptr) {
291 backend->setIndex(index);
292 if (system == QCalendar::System::Gregorian) {
293#if defined(QT_FORCE_ASSERTS) || !defined(QT_NO_DEBUG)
294 auto oldValue = gregorianCalendar.fetchAndStoreRelease(newValue: backend);
295 Q_ASSERT(oldValue == nullptr);
296#else
297 gregorianCalendar.storeRelease(backend);
298#endif
299 }
300
301 Q_ASSERT(byId.size() > index);
302 Q_ASSERT(byId[index] == nullptr);
303 byId[index] = backend;
304 }
305
306 // Register any names.
307 for (const auto &name : names) {
308 auto [it, inserted] = byName.try_emplace(key: name, args&: backend);
309 if (!inserted) {
310 Q_ASSERT(system == QCalendar::System::User);
311 qWarning(msg: "Cannot register name %ls (already in use) for %ls",
312 qUtf16Printable(name), qUtf16Printable(backend->name()));
313 }
314 }
315}
316
317/*
318 Returns a list of names of the available calendar systems.
319
320 Any QCalendarBackend sub-class must be registered before being exposed to Date
321 and Time APIs.
322
323 \sa fromName()
324*/
325QStringList QCalendarRegistry::availableCalendars()
326{
327 ensurePopulated();
328
329 QReadLocker locker(&lock);
330 return byName.keys();
331}
332
333/*
334 Returns a pointer to a named calendar backend.
335
336 If the given \a name is present in availableCalendars(), the backend
337 matching it is returned. Otherwise, \nullptr is returned. Matching of
338 names ignores case.
339
340 \sa availableCalendars(), fromEnum(), fromIndex()
341*/
342const QCalendarBackend *QCalendarRegistry::fromName(QAnyStringView name)
343{
344 ensurePopulated();
345
346 QReadLocker locker(&lock);
347 return byName.value(key: name, defaultValue: nullptr);
348}
349
350/*
351 Returns a pointer to a calendar backend, specified by index.
352
353 If a calendar with ID \a index is known to the calendar registry, the backend
354 with this ID is returned. Otherwise, \nullptr is returned.
355
356 \sa fromEnum(), calendarId()
357*/
358const QCalendarBackend *QCalendarRegistry::fromIndex(size_t index)
359{
360 {
361 QReadLocker locker(&lock);
362
363 if (index >= byId.size())
364 return nullptr;
365
366 if (auto backend = byId[index])
367 return backend;
368 }
369
370 if (index <= size_t(QCalendar::System::Last))
371 return fromEnum(system: QCalendar::System(index));
372
373 return nullptr;
374}
375
376/*
377 Returns a pointer to a calendar backend, specified by \a system.
378
379 This will instantiate the indicated calendar (which will enable fromName()
380 to return it subsequently), but only for the Qt-supported calendars for
381 which (where relevant) the appropriate feature has been enabled.
382
383 \a system should be a member of \a QCalendar::System other than
384 \a QCalendar::System::User.
385
386 \sa fromName(), fromId()
387*/
388const QCalendarBackend *QCalendarRegistry::fromEnum(QCalendar::System system)
389{
390 Q_ASSERT(system <= QCalendar::System::Last);
391 auto index = size_t(system);
392
393 {
394 QReadLocker locker(&lock);
395 Q_ASSERT(byId.size() > index);
396 if (auto backend = byId[index])
397 return backend;
398 }
399
400 QWriteLocker locker(&lock);
401
402 // Check if the backend was registered after releasing the read lock above.
403 if (auto backend = byId[index])
404 return backend;
405
406 return registerSystemBackendLockHeld(system);
407}
408
409/*
410 Returns a list of names \a backend was registered with.
411*/
412QStringList QCalendarRegistry::backendNames(const QCalendarBackend *backend)
413{
414 QStringList l;
415 l.reserve(asize: byName.size()); // too large, but never really large, so ok
416
417 QT_WARNING_PUSH
418 // Clang complains about the reference still causing a copy. The reference is idiomatic, but
419 // runs afoul of QFlatMap's iterators which return a pair of references instead of a reference
420 // to pair. Suppress the warning, because `const auto [key, value]` would look wrong.
421 QT_WARNING_DISABLE_CLANG("-Wrange-loop-analysis")
422 for (const auto &[key, value] : byName) {
423 if (value == backend)
424 l.push_back(t: key);
425 }
426 QT_WARNING_POP
427
428 return l;
429}
430
431} // namespace QtPrivate
432
433Q_GLOBAL_STATIC(QtPrivate::QCalendarRegistry, calendarRegistry);
434
435/*!
436 \since 5.14
437
438 \class QCalendarBackend
439 \inmodule QtCore
440 \internal
441 \reentrant
442 \brief The QCalendarBackend class provides basic calendaring functions.
443
444 QCalendarBackend provides the base class on which all calendar types are
445 implemented. The backend must be registered before it is available via
446 QCalendar API. The registration for system backends is arranged by
447 the calendar registry. Custom backends may be registered using the
448 \c registerCustomBackend() method.
449
450 A backend may also be registered by one or more names. Registering with the
451 name used by CLDR (the Unicode consortium's Common Locale Data Repository)
452 is recommended, particularly when interacting with third-party software.
453 Once a backend is registered for a name, QCalendar can be constructed using
454 that name to select the backend.
455
456 Each built-in backend has a distinct primary name and all built-in backends
457 are instantiated before any custom backend is registered, to prevent custom
458 backends with conflicting names from replacing built-in backends.
459
460 Each calendar backend must inherit from QCalendarBackend and implement its
461 pure virtual methods. It may also override some other virtual methods, as
462 needed.
463
464 Most backends are pure code, with only one data element (this base-classe's
465 \c m_id). Such backends should normally be implemented as singletons.
466
467 The backends may be used by multiple threads simultaneously. The virtual
468 methods must be implemented in a \l {thread-safe} way.
469
470 \section1 Instantiating backends
471
472 Backends may be defined by third-party, plugin or user code. When such
473 custom backends are registered they shall be allocated a unique ID, by
474 which client code may access it. A custom backend instance can have no names
475 if access by name is not needed, or impractical (e.g. because the backend
476 is not a singleton and constructing names for each instance would not make
477 sense). If a custom backend has names that are already registered for
478 another backend, those names are ignored.
479
480 A backend class that has instance variables as well as code may be
481 instantiated many times, each with a distinct set of names, to implement
482 distinct backends - presumably variants on some parameterized calendar.
483 Each instance is then a distinct backend. A pure code backend class shall
484 typically only be instantiated once, as it is only capable of representing
485 one backend.
486
487 Each backend should be instantiated exactly once, on the heap (using the C++
488 \c new operator), so that the registry can take ownership of it after
489 registration.
490
491 Built-in backends, identified by \c QCalendar::System values other than
492 \c{User}, should only be registered by \c{QCalendarRegistry::fromEnum()};
493 no other code should ever register one, this guarantees that such a backend
494 will be a singleton.
495
496 The shareable base-classes for backends, QRomanCalendar and QHijriCalendar,
497 are not themselves identified by QCalendar::System and may be used as
498 base-classes for custom calendar backends, but cannot be instantiated
499 themselves.
500
501 \sa calendarId(), QDate, QDateTime, QDateEdit,
502 QDateTimeEdit, QCalendarWidget
503*/
504
505/*!
506 Destroys the calendar backend.
507
508 Each calendar backend, once instantiated and successfully registered by ID,
509 shall exist until it is destroyed by the registry. Destroying a
510 successfully-registered backend otherwise may leave existing QCalendar
511 instances referencing the destroyed calendar, with undefined results.
512
513 If a backend has not been registered it may safely be deleted.
514
515 \sa calendarId()
516*/
517QCalendarBackend::~QCalendarBackend()
518{
519 Q_ASSERT(!m_id.isValid() || calendarRegistry.isDestroyed()
520 || calendarRegistry->isBeingDestroyed());
521}
522
523/*!
524 \fn QString QCalendarBackend::name() const
525 Returns the primary name of the calendar.
526 */
527
528/*!
529 Returns list of names this backend was registered with.
530
531 The list is a subset of the names passed to \c registerCustomBackend().
532 Some names passed during the registration may not be associated
533 with a backend if they were claimed by another backend first.
534
535 \sa registerCustomBackend()
536*/
537QStringList QCalendarBackend::names() const
538{
539 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
540 return {};
541
542 return calendarRegistry->backendNames(backend: this);
543}
544
545/*!
546 Set the internal index of the backed to the specified value.
547
548 This method exists to allow QCalendarRegistry to update the backend ID
549 after registration without exposing it in public API for QCalendar.
550 */
551void QCalendarBackend::setIndex(size_t index)
552{
553 Q_ASSERT(!m_id.isValid());
554 m_id.id = index;
555}
556
557/*!
558 Register this backend as a custom backend.
559
560 The backend should not already be registered. This method should only be
561 called on objects that are completely initialized because they become
562 available to other threads immediately. In particular, this function should
563 not be called from backend constructors.
564
565 The backend is also registered by names passed in \a names. Only the names
566 that are not already registered are associated with the backend. The name
567 matching is case-insensitive. The list of names associated with the backend
568 can be queried using \c names() method after successful registration.
569
570 Returns the new ID assigned to this backend. If its isValid() is \c true,
571 the calendar registry has taken ownership of the object; this ID can then
572 be used to create \c QCalendar instances. Otherwise, registration failed
573 and the caller is responsible for destruction of the backend, which shall
574 not be available for use by \c QCalendar. Failure should normally only
575 happen if registration is attempted during program termination.
576
577 \sa names()
578*/
579QCalendar::SystemId QCalendarBackend::registerCustomBackend(const QStringList &names)
580{
581 Q_ASSERT(!m_id.isValid());
582
583 if (Q_LIKELY(!calendarRegistry.isDestroyed()))
584 calendarRegistry->registerCustomBackend(backend: this, names);
585
586 return m_id;
587}
588
589bool QCalendarBackend::isGregorian() const
590{
591 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
592 return false;
593
594 return calendarRegistry->isGregorian(backend: this);
595}
596
597/*!
598 \since 6.2
599 \fn QCalendar::SystemId QCalendarBackend::calendarId() const
600
601 Each backend is allocated an ID when successfully registered. A backend whose
602 calendarId() has isValid() \c{false} has not been registered; it also cannot
603 be used, as it is not known to any of the available ways to create a QCalendar.
604
605 \sa calendarSystem(), fromId()
606*/
607
608/*!
609 The calendar system of this calendar.
610
611 \sa fromEnum(), calendarId()
612*/
613QCalendar::System QCalendarBackend::calendarSystem() const
614{
615 return m_id.isInEnum() ? QCalendar::System(m_id.index()) : QCalendar::System::User;
616}
617
618/*
619 Create local variable d containing the backend associated with a QCalendar
620 instance unless the calendar registry is destroyed together with all backends,
621 then return nullptr.
622
623 This assumes that the registry is only destroyed in single threaded context.
624*/
625#define SAFE_D() const auto d = Q_UNLIKELY(calendarRegistry.isDestroyed()) ? nullptr : d_ptr
626
627/*!
628 The primary name of this calendar.
629
630 The calendar may also be known by some aliases. A calendar instantiated by
631 name may use such an alias, in which case its name() need not match the
632 alias by which it was instantiated.
633*/
634QString QCalendar::name() const
635{
636 SAFE_D();
637 return d ? d->name() : QString();
638}
639
640// date queries
641/*!
642 \fn int QCalendarBackend::daysInMonth(int month, int year) const
643
644 Returns number of days in the month number \a month, in year \a year.
645
646 An implementation should return 0 if the given year had no such month. If
647 year is QCalendar::Unspecified, return the usual number of days for the
648 month, in those years that include it.
649
650 Calendars with intercallary days may represent these as extra days of the
651 preceding month, or as short months separate from the usual ones. In the
652 former case, daysInMonth(month, year) should be the number of ordinary days
653 in the month, although \c{isDateValid(year, month, day)} might return \c true
654 for some larger values of \c day.
655
656 \sa daysInYear(), monthsInYear(), minimumDaysInMonth(), maximumDaysInMonth()
657*/
658
659// properties of the calendar
660
661/*!
662 \fn bool QCalendarBackend::isLeapYear(int year) const
663
664 Returns \c true if the specified \a year is a leap year for this calendar.
665
666 \sa daysInYear(), isDateValid()
667*/
668
669/*!
670 \fn bool QCalendarBackend::isLunar() const
671
672 Returns \c true if this calendar is a lunar calendar. Otherwise returns \c
673 false.
674
675 A lunar calendar is a calendar based upon the monthly cycles of the Moon's
676 phases (synodic months). This contrasts with solar calendars, whose annual
677 cycles are based only upon the solar year.
678
679 \sa isLuniSolar(), isSolar(), isProleptic()
680*/
681
682/*!
683 \fn bool QCalendarBackend::isLuniSolar() const
684
685 Returns \c true if this calendar is a lunisolar calendar. Otherwise returns
686 \c false.
687
688 A lunisolar calendar is a calendar whose date indicates both the moon phase
689 and the time of the solar year.
690
691 \sa isLunar(), isSolar(), isProleptic()
692*/
693
694/*!
695 \fn bool QCalendarBackend::isSolar() const
696
697 Returns \c true if this calendar is a solar calendar. Otherwise returns
698 \c false.
699
700 A solar calendar is a calendar whose dates indicate the season or almost
701 equivalently the apparent position of the sun relative to the fixed stars.
702 The Gregorian calendar, widely accepted as standard in the world,
703 is an example of solar calendar.
704
705 \sa isLuniSolar(), isLunar(), isProleptic()
706*/
707
708/*!
709 Returns the total number of days in the year number \a year.
710 Returns zero if there is no such year in this calendar.
711
712 This base implementation returns 366 for leap years and 365 for ordinary
713 years.
714
715 \sa monthsInYear(), daysInMonth(), isLeapYear()
716*/
717int QCalendarBackend::daysInYear(int year) const
718{
719 return monthsInYear(year) ? isLeapYear(year) ? 366 : 365 : 0;
720}
721
722/*!
723 Returns the total number of months in the year number \a year.
724 Returns zero if there is no such year in this calendar.
725
726 This base implementation returns 12 for any valid year.
727
728 \sa daysInYear(), maximumMonthsInYear(), isDateValid()
729*/
730int QCalendarBackend::monthsInYear(int year) const
731{
732 return year > 0 || (year < 0 ? isProleptic() : hasYearZero()) ? 12 : 0;
733}
734
735/*!
736 Returns \c true if the date specified by \a year, \a month, and \a day is
737 valid for this calendar; otherwise returns \c false. For example,
738 the date 2018-04-19 is valid for the Gregorian calendar, but 2018-16-19 and
739 2018-04-38 are invalid.
740
741 Calendars with intercallary days may represent these as extra days of the
742 preceding month or as short months separate from the usual ones. In the
743 former case, a \a day value greater than \c{daysInMonth(\a{month},
744 \a{year})} may be valid.
745
746 \sa daysInMonth(), monthsInYear()
747*/
748bool QCalendarBackend::isDateValid(int year, int month, int day) const
749{
750 return day > 0 && day <= daysInMonth(month, year);
751}
752
753/*!
754 Returns \c true if this calendar is a proleptic calendar. Otherwise returns
755 \c false.
756
757 A proleptic calendar results from allowing negative year numbers to indicate
758 years before the nominal start of the calendar system.
759
760 \sa isLuniSolar(), isSolar(), isLunar(), hasYearZero()
761*/
762
763bool QCalendarBackend::isProleptic() const
764{
765 return true;
766}
767
768/*!
769 Returns \c true if year number \c 0 is considered a valid year in this
770 calendar. Otherwise returns \c false.
771
772 \sa isDateValid(), isProleptic()
773*/
774
775bool QCalendarBackend::hasYearZero() const
776{
777 return false;
778}
779
780/*!
781 Returns the maximum number of days in a month for any year.
782
783 This base implementation returns 31, as this is a common case.
784
785 For calendars with intercallary days, although daysInMonth() doesn't include
786 the intercallary days in its count for an individual month,
787 maximumDaysInMonth() should include intercallary days, so that it is the
788 maximum value of \c day for which \c{isDateValid(year, month, day)} can be
789 true.
790
791 \sa maximumMonthsInYear(), daysInMonth()
792*/
793int QCalendarBackend::maximumDaysInMonth() const
794{
795 return 31;
796}
797
798/*!
799 Returns the minimum number of days in any valid month of any valid year.
800
801 This base implementation returns 29, as this is a common case.
802
803 \sa maximumMonthsInYear(), daysInMonth()
804*/
805int QCalendarBackend::minimumDaysInMonth() const
806{
807 return 29;
808}
809
810/*!
811 Returns the maximum number of months possible in any year.
812
813 This base implementation returns 12, as this is a common case.
814
815 \sa maximumDaysInMonth(), monthsInYear()
816*/
817int QCalendarBackend::maximumMonthsInYear() const
818{
819 return 12;
820}
821
822// Julian day number calculations
823
824/*!
825 \fn bool QCalendarBackend::dateToJulianDay(int year, int month, int day, qint64 *jd) const
826
827 Computes the Julian day number corresponding to the specified \a year, \a
828 month, and \a day. Returns true and sets \a jd if there is such a date in
829 this calendar; otherwise, returns false.
830
831 \sa QCalendar::partsFromDate(), julianDayToDate()
832*/
833
834/*!
835 \fn QCalendar::YearMonthDay QCalendarBackend::julianDayToDate(qint64 jd) const
836
837 Computes the year, month, and day in this calendar for the given Julian day
838 number \a jd. If the given day falls outside this calendar's scope
839 (e.g. before the start-date of a non-proleptic calendar), the returned
840 structure's isValid() is false; otherwise, its year, month, and day fields
841 provide this calendar's description of the date.
842
843 \sa QCalendar::dateFromParts(), dateToJulianDay()
844*/
845
846/*!
847 Returns the day of the week for the given Julian Day Number \a jd.
848
849 This is 1 for Monday through 7 for Sunday.
850
851 Calendars with intercallary days may return larger values for these
852 intercallary days. They should avoid using 0 for any special purpose (it is
853 already used in QDate::dayOfWeek() to mean an invalid date). The calendar
854 should treat the numbers used as an \c enum, whose values need not be
855 contiguous, nor need they follow closely from the 1 through 7 of the usual
856 returns. It suffices that weekDayName() can recognize each such number as
857 identifying a distinct name, that it returns to identify the particular
858 intercallary day.
859
860 This base implementation uses the day-numbering that various calendars have
861 borrowed off the Hebrew calendar.
862
863 \sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek()
864 */
865int QCalendarBackend::dayOfWeek(qint64 jd) const
866{
867 return QRoundingDown::qMod<7>(a: jd) + 1;
868}
869
870// Month and week-day name look-ups (implemented in qlocale.cpp):
871/*!
872 \fn QString QCalendarBackend::monthName(const QLocale &locale, int month, int year,
873 QLocale::FormatType format) const
874
875 Returns the name of the specified \a month in the given \a year for the
876 chosen \a locale, using the given \a format to determine how complete the
877 name is.
878
879 If \a year is Unspecified, return the name for the month that usually has
880 this number within a typical year. Calendars with a leap month that isn't
881 always the last may need to take account of the year to map the month number
882 to the particular year's month with that number.
883
884 \note Backends for which CLDR provides data can configure the default
885 implementation of the two month name look-up methods by arranging for
886 localeMonthIndexData() and localeMonthData() to provide access to the CLDR
887 data (see cldr2qlocalexml.py, qlocalexml2cpp.py and existing backends).
888 Conversely, backends that override both month name look-up methods need not
889 return anything meaningful from localeMonthIndexData() or localeMonthData().
890
891 \sa standaloneMonthName(), QLocale::monthName()
892*/
893
894/*!
895 \fn QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int year
896 QLocale::FormatType format) const
897
898 Returns the standalone name of the specified \a month in the chosen \a
899 locale, using the specified \a format to determine how complete the name is.
900
901 If \a year is Unspecified, return the standalone name for the month that
902 usually has this number within a typical year. Calendars with a leap month
903 that isn't always the last may need to take account of the year to map the
904 month number to the particular year's month with that number.
905
906 \sa monthName(), QLocale::standaloneMonthName()
907*/
908
909/*!
910 \fn QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
911 QLocale::FormatType format) const
912
913 Returns the name of the specified \a day of the week in the chosen \a
914 locale, using the specified \a format to determine how complete the name is.
915
916 The base implementation handles \a day values from 1 to 7 using the day
917 names CLDR provides, which are suitable for calendards that use the same
918 (Hebrew-derived) week as the Gregorian calendar.
919
920 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
921 need to reimplement this method to handle such extra week-day values. They
922 can assume that \a day is a value returned by the same calendar's
923 dayOfWeek().
924
925 \sa dayOfWeek(), standaloneWeekDayName(), QLocale::dayName()
926*/
927
928/*!
929 \fn QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
930 QLocale::FormatType format) const
931
932 Returns the standalone name of the specified \a day of the week in the
933 chosen \a locale, using the specified \a format to determine how complete
934 the name is.
935
936 The base implementation handles \a day values from 1 to 7 using the
937 standalone day names CLDR provides, which are suitable for calendards that
938 use the same (Hebrew-derived) week as the Gregorian calendar.
939
940 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
941 need to reimplement this method to handle such extra week-day values. They
942 can assume that \a day is a value returned by the same calendar's
943 dayOfWeek().
944
945 \sa dayOfWeek(), weekDayName(), QLocale::standaloneDayName()
946*/
947
948/*!
949 \fn QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
950 QDate dateOnly, QTime timeOnly,
951 const QLocale &locale) const
952
953 Returns a string representing a given date, time or date-time.
954
955 If \a datetime is specified and valid, it is used and both date and time
956 format tokens are converted to appropriate representations of the parts of
957 the datetime. Otherwise, if \a dateOnly is valid, only date format tokens
958 are converted; else, if \a timeOnly is valid, only time format tokens are
959 converted. If none are valid, an empty string is returned.
960
961 The specified \a locale influences how some format tokens are converted; for
962 example, when substituting day and month names and their short-forms. For
963 the supported formatting tokens, see QDate::toString() and
964 QTime::toString(). As described above, the provided date, time and date-time
965 determine which of these tokens are recognized: where these appear in \a
966 format they are replaced by data. Any text in \a format not recognized as a
967 format token is copied verbatim into the result string.
968
969 \sa QDate::toString(), QTime::toString(), QDateTime::toString()
970*/
971// End of methods implemented in qlocale.cpp
972
973/*!
974 Returns a list of names of the available calendar systems. Any
975 QCalendarBackend sub-class must be registered before being exposed to Date
976 and Time APIs.
977
978 \sa fromName()
979*/
980QStringList QCalendarBackend::availableCalendars()
981{
982 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
983 return {};
984
985 return calendarRegistry->availableCalendars();
986}
987
988/*!
989 \internal
990 Returns a pointer to a named calendar backend.
991
992 If the given \a name is present in availableCalendars(), the backend
993 matching it is returned; otherwise, \nullptr is returned. Matching of
994 names ignores case.
995
996 \sa availableCalendars(), fromEnum(), fromId()
997*/
998const QCalendarBackend *QCalendarBackend::fromName(QAnyStringView name)
999{
1000 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
1001 return nullptr;
1002
1003 return calendarRegistry->fromName(name);
1004}
1005
1006/*!
1007 \internal
1008 Returns a pointer to a calendar backend, specified by ID.
1009
1010 If a calendar with ID \a id is known to the calendar registry, the backend
1011 with this ID is returned; otherwise, \nullptr is returned.
1012
1013 \sa fromEnum(), calendarId()
1014*/
1015const QCalendarBackend *QCalendarBackend::fromId(QCalendar::SystemId id)
1016{
1017 if (Q_UNLIKELY(calendarRegistry.isDestroyed() || !id.isValid()))
1018 return nullptr;
1019
1020 return calendarRegistry->fromIndex(index: id.index());
1021}
1022
1023/*!
1024 \internal
1025 Returns a pointer to a calendar backend, specified by \c enum.
1026
1027 This will instantiate the indicated calendar (which will enable fromName()
1028 to return it subsequently), but only for the Qt-supported calendars for
1029 which (where relevant) the appropriate feature has been enabled.
1030
1031 \sa fromName(), fromId()
1032*/
1033const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
1034{
1035 if (Q_UNLIKELY(calendarRegistry.isDestroyed() || system == QCalendar::System::User))
1036 return nullptr;
1037
1038 return calendarRegistry->fromEnum(system);
1039}
1040
1041/*!
1042 \internal
1043 Returns backend for Gregorian calendar.
1044
1045 The backend is returned without locking the registry if possible.
1046*/
1047const QCalendarBackend *QCalendarBackend::gregorian()
1048{
1049 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
1050 return nullptr;
1051
1052 return calendarRegistry->gregorian();
1053}
1054
1055/*!
1056 \since 5.14
1057
1058 \class QCalendar
1059 \inmodule QtCore
1060 \reentrant
1061 \brief The QCalendar class describes calendar systems.
1062
1063 A QCalendar object maps a year, month, and day-number to a specific day
1064 (ultimately identified by its Julian day number), using the rules of a
1065 particular system.
1066
1067 The default QCalendar() is a proleptic Gregorian calendar, which has no year
1068 zero. Other calendars may be supported by enabling suitable features or
1069 loading plugins. Calendars supported as features can be constructed by
1070 passing the QCalendar::System enumeration to the constructor. All supported
1071 calendars may be constructed by name, once they have been constructed. (Thus
1072 plugins instantiate their calendar backend to register it.) Built-in
1073 backends, accessible via QCalendar::System, are also always available by
1074 name. Calendars using custom backends may also be constructed using a unique
1075 ID allocated to the backend on construction.
1076
1077 A QCalendar value is immutable.
1078
1079 \sa QDate, QDateTime
1080*/
1081
1082/*!
1083 \enum QCalendar::System
1084
1085 This enumerated type is used to specify a choice of calendar system.
1086
1087 \value Gregorian The default calendar, used internationally.
1088 \value Julian An ancient Roman calendar.
1089 \value Milankovic A revised Julian calendar used by some Orthodox churches.
1090 \value Jalali The Solar Hijri calendar (also called Persian).
1091 \value IslamicCivil The (tabular) Islamic Civil calendar.
1092 \omitvalue Last
1093 \omitvalue User
1094
1095 \sa QCalendar, QCalendar::SystemId
1096*/
1097
1098/*!
1099 \class QCalendar::SystemId
1100 \inmodule QtCore
1101 \since 6.2
1102
1103 This is an opaque type used to identify custom calendar implementations. The
1104 only supported source for values of this type is the backend's \c
1105 calendarId() method. A value of this type whose isValid() is false does not
1106 identify a successfully-registered backend. The only valid consumer of
1107 values of this type is a QCalendar constructor, which will only produce a
1108 valid QCalendar instance if the ID passed to it is valid.
1109
1110 \sa QCalendar, QCalendar::System
1111*/
1112
1113/*!
1114 \fn QCalendar::SystemId::isValid() const
1115
1116 Returns \c true if this is a valid calendar implementation identifier,
1117 \c false otherwise.
1118
1119 \sa QCalendar
1120*/
1121
1122/*!
1123 \internal
1124 \fn QCalendar::SystemId::SystemId()
1125
1126 Constructs an invalid calendar system identifier.
1127*/
1128
1129/*!
1130 \internal
1131 \fn QCalendar::SystemId::index()
1132
1133 Returns the internal representation of the identifier.
1134*/
1135
1136/*!
1137 \fn QCalendar::QCalendar()
1138 \fn QCalendar::QCalendar(QCalendar::System system)
1139 \fn QCalendar::QCalendar(QAnyStringView name)
1140
1141 Constructs a calendar object.
1142
1143 The choice of calendar to use may be indicated by \a system, using the
1144 enumeration QCalendar::System, or by \a name, using a string (either Unicode
1145 or Latin 1). Construction by name may depend on an instance of the given
1146 calendar being constructed by other means first. With no argument, the
1147 default constructor returns the Gregorian calendar.
1148
1149 \note In Qt versions before 6.4, the constructor by \a name accepted only
1150 QStringView and QLatin1String, not QAnyStringView.
1151
1152 \sa QCalendar, System, isValid()
1153*/
1154
1155QCalendar::QCalendar()
1156 : d_ptr(QCalendarBackend::gregorian())
1157{
1158 Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
1159}
1160
1161QCalendar::QCalendar(QCalendar::System system) : d_ptr(QCalendarBackend::fromEnum(system))
1162{
1163 // If system is valid, we should get a valid d for that system.
1164 Q_ASSERT(!d_ptr || (uint(system) > uint(QCalendar::System::Last))
1165 || (d_ptr->calendarId().index() == size_t(system)));
1166}
1167
1168/*!
1169 \overload
1170 \since 6.2
1171
1172 Constructs a calendar object.
1173
1174 When using a custom calendar implementation, its backend is allocated a unique
1175 ID when created; passing that as \a id to this constructor will get a
1176 QCalendar using that backend. This can be useful when the backend is not
1177 registered by name.
1178*/
1179QCalendar::QCalendar(QCalendar::SystemId id)
1180 : d_ptr(QCalendarBackend::fromId(id))
1181{
1182 Q_ASSERT(!d_ptr || d_ptr->calendarId().index() == id.index());
1183}
1184
1185QCalendar::QCalendar(QAnyStringView name)
1186 : d_ptr(QCalendarBackend::fromName(name))
1187{
1188 Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
1189}
1190
1191/*!
1192 \fn bool QCalendar::isValid() const
1193
1194 Returns true if this is a valid calendar object.
1195
1196 Constructing a calendar with an unrecognised calendar name may result in an
1197 invalid object. Use this method to check after creating a calendar by name.
1198*/
1199
1200// Date queries:
1201
1202/*!
1203 Returns the number of days in the given \a month of the given \a year.
1204
1205 Months are numbered consecutively, starting with 1 for the first month of
1206 each year. If \a year is \c Unspecified (its default, if not passed), the
1207 month's length in a normal year is returned.
1208
1209 \sa maximumDaysInMonth(), minimumDaysInMonth()
1210*/
1211int QCalendar::daysInMonth(int month, int year) const
1212{
1213 SAFE_D();
1214 return d ? d->daysInMonth(month, year) : 0;
1215}
1216
1217/*!
1218 Returns the number of days in the given \a year.
1219
1220 Handling of \c Unspecified as \a year is undefined.
1221*/
1222int QCalendar::daysInYear(int year) const
1223{
1224 SAFE_D();
1225 return d ? d->daysInYear(year) : 0;
1226}
1227
1228/*!
1229 Returns the number of months in the given \a year.
1230
1231 If \a year is \c Unspecified, returns the maximum number of months in a
1232 year.
1233
1234 \sa maximumMonthsInYear()
1235*/
1236int QCalendar::monthsInYear(int year) const
1237{
1238 SAFE_D();
1239 return d ? year == Unspecified ? d->maximumMonthsInYear() : d->monthsInYear(year) : 0;
1240}
1241
1242/*!
1243 Returns \c true precisely if the given \a year, \a month, and \a day specify
1244 a valid date in this calendar.
1245
1246 Usually this means 1 <= month <= monthsInYear(year) and 1 <= day <=
1247 daysInMonth(month, year). However, calendars with intercallary days or
1248 months may complicate that.
1249*/
1250bool QCalendar::isDateValid(int year, int month, int day) const
1251{
1252 SAFE_D();
1253 return d && d->isDateValid(year, month, day);
1254}
1255
1256// properties of the calendar
1257
1258/*!
1259 Returns \c true if this calendar object is the Gregorian calendar object
1260 used as default calendar by other Qt APIs, e.g. in QDate.
1261*/
1262bool QCalendar::isGregorian() const
1263{
1264 SAFE_D();
1265 return d && d->isGregorian();
1266}
1267
1268/*!
1269 Returns \c true if the given \a year is a leap year.
1270
1271 Since the year is not a whole number of days long, some years are longer
1272 than others. The difference may be a whole month or just a single day; the
1273 details vary between calendars.
1274
1275 \sa isDateValid()
1276*/
1277bool QCalendar::isLeapYear(int year) const
1278{
1279 SAFE_D();
1280 return d && d->isLeapYear(year);
1281}
1282
1283/*!
1284 Returns \c true if this calendar is a lunar calendar.
1285
1286 A lunar calendar is one based primarily on the phases of the moon.
1287*/
1288bool QCalendar::isLunar() const
1289{
1290 SAFE_D();
1291 return d && d->isLunar();
1292}
1293
1294/*!
1295 Returns \c true if this calendar is luni-solar.
1296
1297 A luni-solar calendar expresses the phases of the moon but adapts itself to
1298 also keep track of the Sun's varying position in the sky, relative to the
1299 fixed stars.
1300*/
1301bool QCalendar::isLuniSolar() const
1302{
1303 SAFE_D();
1304 return d && d->isLuniSolar();
1305}
1306
1307/*!
1308 Returns \c true if this calendar is solar.
1309
1310 A solar calendar is based primarily on the Sun's varying position in the
1311 sky, relative to the fixed stars.
1312*/
1313bool QCalendar::isSolar() const
1314{
1315 SAFE_D();
1316 return d && d->isSolar();
1317}
1318
1319/*!
1320 Returns \c true if this calendar is proleptic.
1321
1322 A proleptic calendar is able to describe years arbitrarily long before its
1323 first. These are represented by negative year numbers and possibly by a year
1324 zero.
1325
1326 \sa hasYearZero()
1327*/
1328bool QCalendar::isProleptic() const
1329{
1330 SAFE_D();
1331 return d && d->isProleptic();
1332}
1333
1334/*!
1335 Returns \c true if this calendar has a year zero.
1336
1337 A calendar may represent years from its first year onwards but provide no
1338 way to describe years before its first; such a calendar has no year zero and
1339 is not proleptic.
1340
1341 A calendar which represents years before its first may number these years
1342 simply by following the usual integer counting, so that the year before the
1343 first is year zero, with negative-numbered years preceding this; such a
1344 calendar is proleptic and has a year zero. A calendar might also have a year
1345 zero (for example, the year of some great event, with subsequent years being
1346 the first year after that event, the second year after, and so on) without
1347 describing years before its year zero. Such a calendar would have a year
1348 zero without being proleptic.
1349
1350 Some calendars, however, represent years before their first by an alternate
1351 numbering; for example, the proleptic Gregorian calendar's first year is 1
1352 CE and the year before it is 1 BCE, preceded by 2 BCE and so on. In this
1353 case, we use negative year numbers for this alternate numbering, with year
1354 -1 as the year before year 1, year -2 as the year before year -1 and so
1355 on. Such a calendar is proleptic but has no year zero.
1356
1357 \sa isProleptic()
1358*/
1359bool QCalendar::hasYearZero() const
1360{
1361 SAFE_D();
1362 return d && d->hasYearZero();
1363}
1364
1365/*!
1366 Returns the number of days in the longest month in the calendar, in any year.
1367
1368 \sa daysInMonth(), minimumDaysInMonth()
1369*/
1370int QCalendar::maximumDaysInMonth() const
1371{
1372 SAFE_D();
1373 return d ? d->maximumDaysInMonth() : 0;
1374}
1375
1376/*!
1377 Returns the number of days in the shortest month in the calendar, in any year.
1378
1379 \sa daysInMonth(), maximumDaysInMonth()
1380*/
1381int QCalendar::minimumDaysInMonth() const
1382{
1383 SAFE_D();
1384 return d ? d->minimumDaysInMonth() : 0;
1385}
1386
1387/*!
1388 Returns the largest number of months that any year may contain.
1389
1390 \sa monthName(), standaloneMonthName(), monthsInYear()
1391*/
1392int QCalendar::maximumMonthsInYear() const
1393{
1394 SAFE_D();
1395 return d ? d->maximumMonthsInYear() : 0;
1396}
1397
1398// Julian Day conversions:
1399
1400/*!
1401 \fn QDate QCalendar::dateFromParts(int year, int month, int day) const
1402 \fn QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
1403
1404 Converts a year, month, and day to a QDate.
1405
1406 The \a year, \a month, and \a day may be passed as separate numbers or
1407 packaged together as the members of \a parts. Returns a QDate with the given
1408 year, month, and day of the month in this calendar, if there is one.
1409 Otherwise, including the case where any of the values is
1410 QCalendar::Unspecified, returns a QDate whose isNull() is true.
1411
1412 \sa isDateValid(), partsFromDate()
1413*/
1414QDate QCalendar::dateFromParts(int year, int month, int day) const
1415{
1416 SAFE_D();
1417 qint64 jd;
1418 return d && d->dateToJulianDay(year, month, day, jd: &jd)
1419 ? QDate::fromJulianDay(jd_: jd) : QDate();
1420}
1421
1422QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
1423{
1424 return parts.isValid() ? dateFromParts(year: parts.year, month: parts.month, day: parts.day) : QDate();
1425}
1426
1427/*!
1428 Converts a QDate to a year, month, and day of the month.
1429
1430 The returned structure's isValid() shall be false if the calendar is unable
1431 to represent the given \a date. Otherwise its year, month, and day
1432 members record the so-named parts of its representation.
1433
1434 \sa dateFromParts(), isProleptic(), hasYearZero()
1435*/
1436QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
1437{
1438 SAFE_D();
1439 return d && date.isValid() ? d->julianDayToDate(jd: date.toJulianDay()) : YearMonthDay();
1440}
1441
1442/*!
1443 Returns the day of the week number for the given \a date.
1444
1445 Returns zero if the calendar is unable to represent the indicated date.
1446 Returns 1 for Monday through 7 for Sunday. Calendars with intercallary days
1447 may use other numbers to represent these.
1448
1449 \sa partsFromDate(), Qt::DayOfWeek
1450*/
1451int QCalendar::dayOfWeek(QDate date) const
1452{
1453 SAFE_D();
1454 return d && date.isValid() ? d->dayOfWeek(jd: date.toJulianDay()) : 0;
1455}
1456
1457// Locale data access
1458
1459/*!
1460 Returns a suitably localised name for a month.
1461
1462 The month is indicated by a number, with \a month = 1 meaning the first
1463 month of the year and subsequent months numbered accordingly. Returns an
1464 empty string if the \a month number is unrecognized.
1465
1466 The \a year may be Unspecified, in which case the mapping from numbers to
1467 names for a typical year's months should be used. Some calendars have leap
1468 months that aren't always at the end of the year; their mapping of month
1469 numbers to names may then depend on the placement of a leap month. Thus the
1470 year should normally be specified, if known.
1471
1472 The name is returned in the form that would normally be used in a full date,
1473 in the specified \a locale; the \a format determines how fully it shall be
1474 expressed (i.e. to what extent it is abbreviated).
1475
1476 \sa standaloneMonthName(), maximumMonthsInYear(), dateTimeToString()
1477*/
1478QString QCalendar::monthName(const QLocale &locale, int month, int year,
1479 QLocale::FormatType format) const
1480{
1481 SAFE_D();
1482 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1483 if (!d || month < 1 || month > maxMonth)
1484 return QString();
1485
1486 return d->monthName(locale, month, year, format);
1487}
1488
1489/*!
1490 Returns a suitably localised standalone name for a month.
1491
1492 The month is indicated by a number, with \a month = 1 meaning the first
1493 month of the year and subsequent months numbered accordingly. Returns an
1494 empty string if the \a month number is unrecognized.
1495
1496 The \a year may be Unspecified, in which case the mapping from numbers to
1497 names for a typical year's months should be used. Some calendars have leap
1498 months that aren't always at the end of the year; their mapping of month
1499 numbers to names may then depend on the placement of a leap month. Thus the
1500 year should normally be specified, if known.
1501
1502 The name is returned in the form that would be used in isolation in the
1503 specified \a locale; the \a format determines how fully it shall be
1504 expressed (i.e. to what extent it is abbreviated).
1505
1506 \sa monthName(), maximumMonthsInYear(), dateTimeToString()
1507*/
1508QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
1509 QLocale::FormatType format) const
1510{
1511 SAFE_D();
1512 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1513 if (!d || month < 1 || month > maxMonth)
1514 return QString();
1515
1516 return d->standaloneMonthName(locale, month, year, format);
1517}
1518
1519/*!
1520 Returns a suitably localised name for a day of the week.
1521
1522 The days of the week are numbered from 1 for Monday through 7 for
1523 Sunday. Some calendars may support higher numbers for other days
1524 (e.g. intercallary days, that are not part of any week). Returns an empty
1525 string if the \a day number is unrecognized.
1526
1527 The name is returned in the form that would normally be used in a full date,
1528 in the specified \a locale; the \a format determines how fully it shall be
1529 expressed (i.e. to what extent it is abbreviated).
1530
1531 \sa standaloneWeekDayName(), dayOfWeek()
1532*/
1533QString QCalendar::weekDayName(const QLocale &locale, int day,
1534 QLocale::FormatType format) const
1535{
1536 SAFE_D();
1537 return d ? d->weekDayName(locale, day, format) : QString();
1538}
1539
1540/*!
1541 Returns a suitably localised standalone name for a day of the week.
1542
1543 The days of the week are numbered from 1 for Monday through 7 for
1544 Sunday. Some calendars may support higher numbers for other days
1545 (e.g. intercallary days, that are not part of any week). Returns an empty
1546 string if the \a day number is unrecognized.
1547
1548 The name is returned in the form that would be used in isolation (for
1549 example as a column heading in a calendar's tabular display of a month with
1550 successive weeks as rows) in the specified \a locale; the \a format
1551 determines how fully it shall be expressed (i.e. to what extent it is
1552 abbreviated).
1553
1554 \sa weekDayName(), dayOfWeek()
1555*/
1556QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
1557 QLocale::FormatType format) const
1558{
1559 SAFE_D();
1560 return d ? d->standaloneWeekDayName(locale, day, format) : QString();
1561}
1562
1563/*!
1564 Returns a string representing a given date, time or date-time.
1565
1566 If \a datetime is valid, it is represented and format specifiers for both
1567 date and time fields are recognized; otherwise, if \a dateOnly is valid, it
1568 is represented and only format specifiers for date fields are recognized;
1569 finally, if \a timeOnly is valid, it is represented and only format
1570 specifiers for time fields are recognized. If none of these is valid, an
1571 empty string is returned.
1572
1573 See QDate::toString and QTime::toString() for the supported field
1574 specifiers. Characters in \a format that are recognized as field specifiers
1575 are replaced by text representing appropriate data from the date and/or time
1576 being represented. The texts to represent them may depend on the \a locale
1577 specified. Other charagers in \a format are copied verbatim into the
1578 returned string.
1579
1580 \sa monthName(), weekDayName(), QDate::toString(), QTime::toString()
1581*/
1582QString QCalendar::dateTimeToString(QStringView format, const QDateTime &datetime,
1583 QDate dateOnly, QTime timeOnly,
1584 const QLocale &locale) const
1585{
1586 SAFE_D();
1587 return d ? d->dateTimeToString(format, datetime, dateOnly, timeOnly, locale) : QString();
1588}
1589
1590/*!
1591 Returns a list of names of the available calendar systems.
1592
1593 These may be supplied by plugins or other code linked into an application,
1594 in addition to the ones provided by Qt, some of which are controlled by
1595 features.
1596*/
1597QStringList QCalendar::availableCalendars()
1598{
1599 return QCalendarBackend::availableCalendars();
1600}
1601
1602QT_END_NAMESPACE
1603
1604#ifndef QT_BOOTSTRAPPED
1605#include "moc_qcalendar.cpp"
1606#endif
1607

source code of qtbase/src/corelib/time/qcalendar.cpp