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