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 usual number of days for the
649 month, in those years that include it.
650
651 Calendars with intercallary 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 intercallary 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 intercallary days, although daysInMonth() doesn't include
787 the intercallary days in its count for an individual month,
788 maximumDaysInMonth() should include intercallary 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.
831
832 \sa QCalendar::partsFromDate(), julianDayToDate()
833*/
834
835/*!
836 \fn QCalendar::YearMonthDay QCalendarBackend::julianDayToDate(qint64 jd) const
837
838 Computes the year, month, and day in this calendar for the given Julian day
839 number \a jd. If the given day falls outside this calendar's scope
840 (e.g. before the start-date of a non-proleptic calendar), the returned
841 structure's isValid() is false; otherwise, its year, month, and day fields
842 provide this calendar's description of the date.
843
844 \sa QCalendar::dateFromParts(), dateToJulianDay()
845*/
846
847/*!
848 Returns the day of the week for the given Julian Day Number \a jd.
849
850 This is 1 for Monday through 7 for Sunday.
851
852 Calendars with intercallary days may return larger values for these
853 intercallary days. They should avoid using 0 for any special purpose (it is
854 already used in QDate::dayOfWeek() to mean an invalid date). The calendar
855 should treat the numbers used as an \c enum, whose values need not be
856 contiguous, nor need they follow closely from the 1 through 7 of the usual
857 returns. It suffices that;
858 \list
859 \li weekDayName() can recognize each such number as identifying a distinct
860 name, that it returns to identify the particular intercallary day; and
861 \li matchCenturyToWeekday() can determine what century adjustment aligns a
862 given date within a century to a given day of the week, where this is
863 relevant and possible.
864 \endlist
865
866 This base implementation uses the day-numbering that various calendars have
867 borrowed off the Hebrew calendar.
868
869 \sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek(), Qt::DayOfWeek
870*/
871int QCalendarBackend::dayOfWeek(qint64 jd) const
872{
873 return QRoundingDown::qMod<7>(jd) + 1;
874}
875
876/*!
877 \since 6.7
878 Adjusts century of \a parts to match \a dow.
879
880 Preserves parts.month and parts.day while adjusting parts.year by a multiple
881 of 100 (taking the absence of year zero into account, when relevant) to
882 obtain a date for which dayOfWeek() is \a dow. Prefers smaller changes over
883 larger and increases to the century over decreases of the same
884 magnitude. Returns the Julian Day number for the selected date or
885 std::numeric_limits<qint64>::min(), a.k.a. QDate::nullJd(), if there is no
886 date matching these requirements.
887
888 The base-class provides a brute-force implementation that steps outwards
889 from the given date by centures, above and below by up to 14 centuries, in
890 search of a matching date. This is neither computationally efficient nor
891 elegant but should work as advertised for calendars in which every month-day
892 combination does appear on all days of the week, across sufficiently many
893 centuries.
894*/
895qint64 QCalendarBackend::matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const
896{
897 Q_ASSERT(parts.isValid());
898 // Brute-force solution as fall-back.
899 const auto checkOffset = [parts, dow, this](int centuries) -> std::optional<qint64> {
900 // Offset parts.year by the given number of centuries:
901 int year = parts.year + centuries * 100;
902 // but take into account the effect of crossing zero, if we did:
903 if (!hasYearZero() && (parts.year > 0) != (year > 0))
904 year += parts.year > 0 ? -1 : +1;
905 qint64 jd;
906 if (isDateValid(year, parts.month, parts.day)
907 && dateToJulianDay(year, parts.month, parts.day, &jd)
908 && dayOfWeek(jd) == dow) {
909 return jd;
910 }
911 return std::nullopt;
912 };
913 // Empirically, aside from Gregorian, each calendar finds every dow within
914 // any 29-century run, so 14 centuries is the biggest offset we ever need.
915 for (int offset = 0; offset < 15; ++offset) {
916 if (auto jd = checkOffset(offset))
917 return *jd;
918 if (offset) {
919 if (auto jd = checkOffset(-offset))
920 return *jd;
921 }
922 }
923 return (std::numeric_limits<qint64>::min)();
924}
925
926// Month and week-day name look-ups (implemented in qlocale.cpp):
927/*!
928 \fn QString QCalendarBackend::monthName(const QLocale &locale, int month, int year,
929 QLocale::FormatType format) const
930
931 Returns the name of the specified \a month in the given \a year for the
932 chosen \a locale, using the given \a format to determine how complete the
933 name is.
934
935 If \a year is Unspecified, return the name for the month that usually has
936 this number within a typical year. Calendars with a leap month that isn't
937 always the last may need to take account of the year to map the month number
938 to the particular year's month with that number.
939
940 \note Backends for which CLDR provides data can configure the default
941 implementation of the two month name look-up methods by arranging for
942 localeMonthIndexData() and localeMonthData() to provide access to the CLDR
943 data (see cldr2qlocalexml.py, qlocalexml2cpp.py and existing backends).
944 Conversely, backends that override both month name look-up methods need not
945 return anything meaningful from localeMonthIndexData() or localeMonthData().
946
947 \sa standaloneMonthName(), QLocale::monthName()
948*/
949
950/*!
951 \fn QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int year
952 QLocale::FormatType format) const
953
954 Returns the standalone name of the specified \a month in the chosen \a
955 locale, using the specified \a format to determine how complete the name is.
956
957 If \a year is Unspecified, return the standalone name for the month that
958 usually has this number within a typical year. Calendars with a leap month
959 that isn't always the last may need to take account of the year to map the
960 month number to the particular year's month with that number.
961
962 \sa monthName(), QLocale::standaloneMonthName()
963*/
964
965/*!
966 \fn QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
967 QLocale::FormatType format) const
968
969 Returns the name of the specified \a day of the week in the chosen \a
970 locale, using the specified \a format to determine how complete the name is.
971
972 The base implementation handles \a day values from 1 to 7 using the day
973 names CLDR provides, which are suitable for calendards that use the same
974 (Hebrew-derived) week as the Gregorian calendar.
975
976 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
977 need to reimplement this method to handle such extra week-day values. They
978 can assume that \a day is a value returned by the same calendar's
979 dayOfWeek().
980
981 \sa dayOfWeek(), standaloneWeekDayName(), QLocale::dayName()
982*/
983
984/*!
985 \fn QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
986 QLocale::FormatType format) const
987
988 Returns the standalone name of the specified \a day of the week in the
989 chosen \a locale, using the specified \a format to determine how complete
990 the name is.
991
992 The base implementation handles \a day values from 1 to 7 using the
993 standalone day names CLDR provides, which are suitable for calendards that
994 use the same (Hebrew-derived) week as the Gregorian calendar.
995
996 Calendars whose dayOfWeek() returns a value outside the range from 1 to 7
997 need to reimplement this method to handle such extra week-day values. They
998 can assume that \a day is a value returned by the same calendar's
999 dayOfWeek().
1000
1001 \sa dayOfWeek(), weekDayName(), QLocale::standaloneDayName()
1002*/
1003
1004/*!
1005 \fn QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
1006 QDate dateOnly, QTime timeOnly,
1007 const QLocale &locale) const
1008
1009 Returns a string representing a given date, time or date-time.
1010
1011 If \a datetime is specified and valid, it is used and both date and time
1012 format tokens are converted to appropriate representations of the parts of
1013 the datetime. Otherwise, if \a dateOnly is valid, only date format tokens
1014 are converted; else, if \a timeOnly is valid, only time format tokens are
1015 converted. If none are valid, an empty string is returned.
1016
1017 The specified \a locale influences how some format tokens are converted; for
1018 example, when substituting day and month names and their short-forms. For
1019 the supported formatting tokens, see QDate::toString() and
1020 QTime::toString(). As described above, the provided date, time and date-time
1021 determine which of these tokens are recognized: where these appear in \a
1022 format they are replaced by data. Any text in \a format not recognized as a
1023 format token is copied verbatim into the result string.
1024
1025 \sa QDate::toString(), QTime::toString(), QDateTime::toString()
1026*/
1027// End of methods implemented in qlocale.cpp
1028
1029/*!
1030 Returns a list of names of the available calendar systems. Any
1031 QCalendarBackend sub-class must be registered before being exposed to Date
1032 and Time APIs.
1033
1034 \sa fromName()
1035*/
1036QStringList QCalendarBackend::availableCalendars()
1037{
1038 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
1039 return {};
1040
1041 return calendarRegistry->availableCalendars();
1042}
1043
1044/*!
1045 \internal
1046 Returns a pointer to a named calendar backend.
1047
1048 If the given \a name is present in availableCalendars(), the backend
1049 matching it is returned; otherwise, \nullptr is returned. Matching of
1050 names ignores case.
1051
1052 \sa availableCalendars(), fromEnum(), fromId()
1053*/
1054const QCalendarBackend *QCalendarBackend::fromName(QAnyStringView name)
1055{
1056 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
1057 return nullptr;
1058
1059 return calendarRegistry->fromName(name);
1060}
1061
1062/*!
1063 \internal
1064 Returns a pointer to a calendar backend, specified by ID.
1065
1066 If a calendar with ID \a id is known to the calendar registry, the backend
1067 with this ID is returned; otherwise, \nullptr is returned.
1068
1069 \sa fromEnum(), calendarId()
1070*/
1071const QCalendarBackend *QCalendarBackend::fromId(QCalendar::SystemId id)
1072{
1073 if (Q_UNLIKELY(calendarRegistry.isDestroyed() || !id.isValid()))
1074 return nullptr;
1075
1076 return calendarRegistry->fromIndex(id.index());
1077}
1078
1079/*!
1080 \internal
1081 Returns a pointer to a calendar backend, specified by \c enum.
1082
1083 This will instantiate the indicated calendar (which will enable fromName()
1084 to return it subsequently), but only for the Qt-supported calendars for
1085 which (where relevant) the appropriate feature has been enabled.
1086
1087 \sa fromName(), fromId()
1088*/
1089const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
1090{
1091 if (Q_UNLIKELY(calendarRegistry.isDestroyed() || system == QCalendar::System::User))
1092 return nullptr;
1093
1094 return calendarRegistry->fromEnum(system);
1095}
1096
1097/*!
1098 \internal
1099 Returns backend for Gregorian calendar.
1100
1101 The backend is returned without locking the registry if possible.
1102*/
1103const QCalendarBackend *QCalendarBackend::gregorian()
1104{
1105 if (Q_UNLIKELY(calendarRegistry.isDestroyed()))
1106 return nullptr;
1107
1108 return calendarRegistry->gregorian();
1109}
1110
1111/*!
1112 \since 5.14
1113
1114 \class QCalendar
1115 \inmodule QtCore
1116 \reentrant
1117 \brief The QCalendar class describes calendar systems.
1118
1119 A QCalendar object maps a year, month, and day-number to a specific day
1120 (ultimately identified by its Julian day number), using the rules of a
1121 particular system.
1122
1123 The default QCalendar() is a proleptic Gregorian calendar, which has no year
1124 zero. Other calendars may be supported by enabling suitable features or
1125 loading plugins. Calendars supported as features can be constructed by
1126 passing the QCalendar::System enumeration to the constructor. All supported
1127 calendars may be constructed by name, once they have been constructed. (Thus
1128 plugins instantiate their calendar backend to register it.) Built-in
1129 backends, accessible via QCalendar::System, are also always available by
1130 name. Calendars using custom backends may also be constructed using a unique
1131 ID allocated to the backend on construction.
1132
1133 A QCalendar value is immutable.
1134
1135 \sa QDate, QDateTime
1136*/
1137
1138/*!
1139 \enum QCalendar::System
1140
1141 This enumerated type is used to specify a choice of calendar system.
1142
1143 \value Gregorian The default calendar, used internationally.
1144 \value Julian An ancient Roman calendar.
1145 \value Milankovic A revised Julian calendar used by some Orthodox churches.
1146 \value Jalali The Solar Hijri calendar (also called Persian).
1147 \value IslamicCivil The (tabular) Islamic Civil calendar.
1148 \omitvalue Last
1149 \omitvalue User
1150
1151 \sa QCalendar, QCalendar::SystemId
1152*/
1153
1154/*!
1155 \class QCalendar::SystemId
1156 \inmodule QtCore
1157 \since 6.2
1158
1159 This is an opaque type used to identify custom calendar implementations. The
1160 only supported source for values of this type is the backend's \c
1161 calendarId() method. A value of this type whose isValid() is false does not
1162 identify a successfully-registered backend. The only valid consumer of
1163 values of this type is a QCalendar constructor, which will only produce a
1164 valid QCalendar instance if the ID passed to it is valid.
1165
1166 \sa QCalendar, QCalendar::System
1167*/
1168
1169/*!
1170 \fn QCalendar::SystemId::isValid() const
1171
1172 Returns \c true if this is a valid calendar implementation identifier,
1173 \c false otherwise.
1174
1175 \sa QCalendar
1176*/
1177
1178/*!
1179 \internal
1180 \fn QCalendar::SystemId::SystemId()
1181
1182 Constructs an invalid calendar system identifier.
1183*/
1184
1185/*!
1186 \internal
1187 \fn QCalendar::SystemId::index()
1188
1189 Returns the internal representation of the identifier.
1190*/
1191
1192/*!
1193 \fn QCalendar::QCalendar()
1194 \fn QCalendar::QCalendar(QCalendar::System system)
1195 \fn QCalendar::QCalendar(QAnyStringView name)
1196
1197 Constructs a calendar object.
1198
1199 The choice of calendar to use may be indicated by \a system, using the
1200 enumeration QCalendar::System, or by \a name, using a string (either Unicode
1201 or Latin 1). Construction by name may depend on an instance of the given
1202 calendar being constructed by other means first. With no argument, the
1203 default constructor returns the Gregorian calendar.
1204
1205 \note In Qt versions before 6.4, the constructor by \a name accepted only
1206 QStringView and QLatin1String, not QAnyStringView.
1207
1208 \sa QCalendar, System, isValid()
1209*/
1210
1211QCalendar::QCalendar()
1212 : d_ptr(QCalendarBackend::gregorian())
1213{
1214 Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
1215}
1216
1217QCalendar::QCalendar(QCalendar::System system) : d_ptr(QCalendarBackend::fromEnum(system))
1218{
1219 // If system is valid, we should get a valid d for that system.
1220 Q_ASSERT(!d_ptr || (uint(system) > uint(QCalendar::System::Last))
1221 || (d_ptr->calendarId().index() == size_t(system)));
1222}
1223
1224/*!
1225 \overload
1226 \since 6.2
1227
1228 Constructs a calendar object.
1229
1230 When using a custom calendar implementation, its backend is allocated a unique
1231 ID when created; passing that as \a id to this constructor will get a
1232 QCalendar using that backend. This can be useful when the backend is not
1233 registered by name.
1234*/
1235QCalendar::QCalendar(QCalendar::SystemId id)
1236 : d_ptr(QCalendarBackend::fromId(id))
1237{
1238 Q_ASSERT(!d_ptr || d_ptr->calendarId().index() == id.index());
1239}
1240
1241QCalendar::QCalendar(QAnyStringView name)
1242 : d_ptr(QCalendarBackend::fromName(name))
1243{
1244 Q_ASSERT(!d_ptr || d_ptr->calendarId().isValid());
1245}
1246
1247/*!
1248 \fn bool QCalendar::isValid() const
1249
1250 Returns true if this is a valid calendar object.
1251
1252 Constructing a calendar with an unrecognised calendar name may result in an
1253 invalid object. Use this method to check after creating a calendar by name.
1254*/
1255
1256// Date queries:
1257
1258/*!
1259 Returns the number of days in the given \a month of the given \a year.
1260
1261 Months are numbered consecutively, starting with 1 for the first month of
1262 each year. If \a year is \c Unspecified (its default, if not passed), the
1263 month's greatest length in any year is returned.
1264
1265 \sa maximumDaysInMonth(), minimumDaysInMonth()
1266*/
1267int QCalendar::daysInMonth(int month, int year) const
1268{
1269 SAFE_D();
1270 return d ? d->daysInMonth(month, year) : 0;
1271}
1272
1273/*!
1274 Returns the number of days in the given \a year.
1275
1276 Handling of \c Unspecified as \a year is undefined.
1277*/
1278int QCalendar::daysInYear(int year) const
1279{
1280 SAFE_D();
1281 return d ? d->daysInYear(year) : 0;
1282}
1283
1284/*!
1285 Returns the number of months in the given \a year.
1286
1287 If \a year is \c Unspecified, returns the maximum number of months in a
1288 year.
1289
1290 \sa maximumMonthsInYear()
1291*/
1292int QCalendar::monthsInYear(int year) const
1293{
1294 SAFE_D();
1295 return d ? year == Unspecified ? d->maximumMonthsInYear() : d->monthsInYear(year) : 0;
1296}
1297
1298/*!
1299 Returns \c true precisely if the given \a year, \a month, and \a day specify
1300 a valid date in this calendar.
1301
1302 Usually this means 1 <= month <= monthsInYear(year) and 1 <= day <=
1303 daysInMonth(month, year). However, calendars with intercallary days or
1304 months may complicate that.
1305*/
1306bool QCalendar::isDateValid(int year, int month, int day) const
1307{
1308 SAFE_D();
1309 return d && d->isDateValid(year, month, day);
1310}
1311
1312// properties of the calendar
1313
1314/*!
1315 Returns \c true if this calendar object is the Gregorian calendar object
1316 used as default calendar by other Qt APIs, e.g. in QDate.
1317*/
1318bool QCalendar::isGregorian() const
1319{
1320 SAFE_D();
1321 return d && d->isGregorian();
1322}
1323
1324/*!
1325 Returns \c true if the given \a year is a leap year.
1326
1327 Since the year is not a whole number of days long, some years are longer
1328 than others. The difference may be a whole month or just a single day; the
1329 details vary between calendars.
1330
1331 \sa isDateValid()
1332*/
1333bool QCalendar::isLeapYear(int year) const
1334{
1335 SAFE_D();
1336 return d && d->isLeapYear(year);
1337}
1338
1339/*!
1340 Returns \c true if this calendar is a lunar calendar.
1341
1342 A lunar calendar is one based primarily on the phases of the moon.
1343*/
1344bool QCalendar::isLunar() const
1345{
1346 SAFE_D();
1347 return d && d->isLunar();
1348}
1349
1350/*!
1351 Returns \c true if this calendar is luni-solar.
1352
1353 A luni-solar calendar expresses the phases of the moon but adapts itself to
1354 also keep track of the Sun's varying position in the sky, relative to the
1355 fixed stars.
1356*/
1357bool QCalendar::isLuniSolar() const
1358{
1359 SAFE_D();
1360 return d && d->isLuniSolar();
1361}
1362
1363/*!
1364 Returns \c true if this calendar is solar.
1365
1366 A solar calendar is based primarily on the Sun's varying position in the
1367 sky, relative to the fixed stars.
1368*/
1369bool QCalendar::isSolar() const
1370{
1371 SAFE_D();
1372 return d && d->isSolar();
1373}
1374
1375/*!
1376 Returns \c true if this calendar is proleptic.
1377
1378 A proleptic calendar is able to describe years arbitrarily long before its
1379 first. These are represented by negative year numbers and possibly by a year
1380 zero.
1381
1382 \sa hasYearZero()
1383*/
1384bool QCalendar::isProleptic() const
1385{
1386 SAFE_D();
1387 return d && d->isProleptic();
1388}
1389
1390/*!
1391 Returns \c true if this calendar has a year zero.
1392
1393 A calendar may represent years from its first year onwards but provide no
1394 way to describe years before its first; such a calendar has no year zero and
1395 is not proleptic.
1396
1397 A calendar which represents years before its first may number these years
1398 simply by following the usual integer counting, so that the year before the
1399 first is year zero, with negative-numbered years preceding this; such a
1400 calendar is proleptic and has a year zero. A calendar might also have a year
1401 zero (for example, the year of some great event, with subsequent years being
1402 the first year after that event, the second year after, and so on) without
1403 describing years before its year zero. Such a calendar would have a year
1404 zero without being proleptic.
1405
1406 Some calendars, however, represent years before their first by an alternate
1407 numbering; for example, the proleptic Gregorian calendar's first year is 1
1408 CE and the year before it is 1 BCE, preceded by 2 BCE and so on. In this
1409 case, we use negative year numbers for this alternate numbering, with year
1410 -1 as the year before year 1, year -2 as the year before year -1 and so
1411 on. Such a calendar is proleptic but has no year zero.
1412
1413 \sa isProleptic()
1414*/
1415bool QCalendar::hasYearZero() const
1416{
1417 SAFE_D();
1418 return d && d->hasYearZero();
1419}
1420
1421/*!
1422 Returns the number of days in the longest month in the calendar, in any year.
1423
1424 \sa daysInMonth(), minimumDaysInMonth()
1425*/
1426int QCalendar::maximumDaysInMonth() const
1427{
1428 SAFE_D();
1429 return d ? d->maximumDaysInMonth() : 0;
1430}
1431
1432/*!
1433 Returns the number of days in the shortest month in the calendar, in any year.
1434
1435 \sa daysInMonth(), maximumDaysInMonth()
1436*/
1437int QCalendar::minimumDaysInMonth() const
1438{
1439 SAFE_D();
1440 return d ? d->minimumDaysInMonth() : 0;
1441}
1442
1443/*!
1444 Returns the largest number of months that any year may contain.
1445
1446 \sa monthName(), standaloneMonthName(), monthsInYear()
1447*/
1448int QCalendar::maximumMonthsInYear() const
1449{
1450 SAFE_D();
1451 return d ? d->maximumMonthsInYear() : 0;
1452}
1453
1454// Julian Day conversions:
1455
1456/*!
1457 \fn QDate QCalendar::dateFromParts(int year, int month, int day) const
1458 \fn QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
1459
1460 Converts a year, month, and day to a QDate.
1461
1462 The \a year, \a month, and \a day may be passed as separate numbers or
1463 packaged together as the members of \a parts. Returns a QDate with the given
1464 year, month, and day of the month in this calendar, if there is one.
1465 Otherwise, including the case where any of the values is
1466 QCalendar::Unspecified, returns a QDate whose isNull() is true.
1467
1468 \sa isDateValid(), partsFromDate()
1469*/
1470QDate QCalendar::dateFromParts(int year, int month, int day) const
1471{
1472 SAFE_D();
1473 qint64 jd;
1474 return d && d->dateToJulianDay(year, month, day, &jd)
1475 ? QDate::fromJulianDay(jd) : QDate();
1476}
1477
1478QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
1479{
1480 return parts.isValid() ? dateFromParts(parts.year, parts.month, parts.day) : QDate();
1481}
1482
1483/*!
1484 \since 6.7
1485 Adjusts the century of a date to match a given day of the week.
1486
1487 For use when given a date's day of week, day of month, month and last two
1488 digits of the year. Returns a QDate instance with the given \a dow as its \l
1489 {QDate::}{dayOfWeek()}, matching the given \a parts in month and day of the
1490 month. The returned QDate's \l {QDate::}{year()} shall differ from
1491 \c{parts.year} by a multiple of 100, preferring small multiples over larger
1492 and positive multiples over their negations.
1493
1494 If no date matches these conditions, an invalid QDate is returned: the day
1495 of week is incompatible with the other data given. This arises, for example,
1496 with the Gregorian calendar, whose 400-year cycle is a whole number of weeks
1497 long, so any given month and day of that month only ever falls, in years
1498 with a given last two digits, on four days of the week. (In the special case
1499 of February 29th at the turn of a century, when that is a leap year, only
1500 one day of the week is possible: Tuesday.)
1501*/
1502QDate QCalendar::matchCenturyToWeekday(const QCalendar::YearMonthDay &parts, int dow) const
1503{
1504 SAFE_D();
1505 return d && parts.isValid()
1506 ? QDate::fromJulianDay(d->matchCenturyToWeekday(parts, dow)) : QDate();
1507}
1508
1509/*!
1510 Converts a QDate to a year, month, and day of the month.
1511
1512 The returned structure's isValid() shall be false if the calendar is unable
1513 to represent the given \a date. Otherwise its year, month, and day
1514 members record the so-named parts of its representation.
1515
1516 \sa dateFromParts(), isProleptic(), hasYearZero()
1517*/
1518QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
1519{
1520 SAFE_D();
1521 return d && date.isValid() ? d->julianDayToDate(date.toJulianDay()) : YearMonthDay();
1522}
1523
1524/*!
1525 Returns the day of the week number for the given \a date.
1526
1527 Returns zero if the calendar is unable to represent the indicated date.
1528 Returns 1 for Monday through 7 for Sunday. Calendars with intercallary days
1529 may use other numbers to represent these.
1530
1531 \sa partsFromDate(), Qt::DayOfWeek
1532*/
1533int QCalendar::dayOfWeek(QDate date) const
1534{
1535 SAFE_D();
1536 return d && date.isValid() ? d->dayOfWeek(date.toJulianDay()) : 0;
1537}
1538
1539// Locale data access
1540
1541/*!
1542 Returns a suitably localised name for a month.
1543
1544 The month is indicated by a number, with \a month = 1 meaning the first
1545 month of the year and subsequent months numbered accordingly. Returns an
1546 empty string if the \a month number is unrecognized.
1547
1548 The \a year may be Unspecified, in which case the mapping from numbers to
1549 names for a typical year's months should be used. Some calendars have leap
1550 months that aren't always at the end of the year; their mapping of month
1551 numbers to names may then depend on the placement of a leap month. Thus the
1552 year should normally be specified, if known.
1553
1554 The name is returned in the form that would normally be used in a full date,
1555 in the specified \a locale; the \a format determines how fully it shall be
1556 expressed (i.e. to what extent it is abbreviated).
1557
1558 \sa standaloneMonthName(), maximumMonthsInYear(), dateTimeToString()
1559*/
1560QString QCalendar::monthName(const QLocale &locale, int month, int year,
1561 QLocale::FormatType format) const
1562{
1563 SAFE_D();
1564 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1565 if (!d || month < 1 || month > maxMonth)
1566 return QString();
1567
1568 return d->monthName(locale, month, year, format);
1569}
1570
1571/*!
1572 Returns a suitably localised standalone name for a month.
1573
1574 The month is indicated by a number, with \a month = 1 meaning the first
1575 month of the year and subsequent months numbered accordingly. Returns an
1576 empty string if the \a month number is unrecognized.
1577
1578 The \a year may be Unspecified, in which case the mapping from numbers to
1579 names for a typical year's months should be used. Some calendars have leap
1580 months that aren't always at the end of the year; their mapping of month
1581 numbers to names may then depend on the placement of a leap month. Thus the
1582 year should normally be specified, if known.
1583
1584 The name is returned in the form that would be used in isolation in the
1585 specified \a locale; the \a format determines how fully it shall be
1586 expressed (i.e. to what extent it is abbreviated).
1587
1588 \sa monthName(), maximumMonthsInYear(), dateTimeToString()
1589*/
1590QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
1591 QLocale::FormatType format) const
1592{
1593 SAFE_D();
1594 const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
1595 if (!d || month < 1 || month > maxMonth)
1596 return QString();
1597
1598 return d->standaloneMonthName(locale, month, year, format);
1599}
1600
1601/*!
1602 Returns a suitably localised name for a day of the week.
1603
1604 The days of the week are numbered from 1 for Monday through 7 for
1605 Sunday. Some calendars may support higher numbers for other days
1606 (e.g. intercallary days, that are not part of any week). Returns an empty
1607 string if the \a day number is unrecognized.
1608
1609 The name is returned in the form that would normally be used in a full date,
1610 in the specified \a locale; the \a format determines how fully it shall be
1611 expressed (i.e. to what extent it is abbreviated).
1612
1613 \sa standaloneWeekDayName(), dayOfWeek()
1614*/
1615QString QCalendar::weekDayName(const QLocale &locale, int day,
1616 QLocale::FormatType format) const
1617{
1618 SAFE_D();
1619 return d ? d->weekDayName(locale, day, format) : QString();
1620}
1621
1622/*!
1623 Returns a suitably localised standalone name for a day of the week.
1624
1625 The days of the week are numbered from 1 for Monday through 7 for
1626 Sunday. Some calendars may support higher numbers for other days
1627 (e.g. intercallary days, that are not part of any week). Returns an empty
1628 string if the \a day number is unrecognized.
1629
1630 The name is returned in the form that would be used in isolation (for
1631 example as a column heading in a calendar's tabular display of a month with
1632 successive weeks as rows) in the specified \a locale; the \a format
1633 determines how fully it shall be expressed (i.e. to what extent it is
1634 abbreviated).
1635
1636 \sa weekDayName(), dayOfWeek()
1637*/
1638QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
1639 QLocale::FormatType format) const
1640{
1641 SAFE_D();
1642 return d ? d->standaloneWeekDayName(locale, day, format) : QString();
1643}
1644
1645/*!
1646 Returns a string representing a given date, time or date-time.
1647
1648 If \a datetime is valid, it is represented and format specifiers for both
1649 date and time fields are recognized; otherwise, if \a dateOnly is valid, it
1650 is represented and only format specifiers for date fields are recognized;
1651 finally, if \a timeOnly is valid, it is represented and only format
1652 specifiers for time fields are recognized. If none of these is valid, an
1653 empty string is returned.
1654
1655 See QDate::toString and QTime::toString() for the supported field
1656 specifiers. Characters in \a format that are recognized as field specifiers
1657 are replaced by text representing appropriate data from the date and/or time
1658 being represented. The texts to represent them may depend on the \a locale
1659 specified. Other charagers in \a format are copied verbatim into the
1660 returned string.
1661
1662 \sa monthName(), weekDayName(), QDate::toString(), QTime::toString()
1663*/
1664QString QCalendar::dateTimeToString(QStringView format, const QDateTime &datetime,
1665 QDate dateOnly, QTime timeOnly,
1666 const QLocale &locale) const
1667{
1668 SAFE_D();
1669 return d ? d->dateTimeToString(format, datetime, dateOnly, timeOnly, locale) : QString();
1670}
1671
1672/*!
1673 Returns a list of names of the available calendar systems.
1674
1675 These may be supplied by plugins or other code linked into an application,
1676 in addition to the ones provided by Qt, some of which are controlled by
1677 features.
1678*/
1679QStringList QCalendar::availableCalendars()
1680{
1681 return QCalendarBackend::availableCalendars();
1682}
1683
1684QT_END_NAMESPACE
1685
1686#ifndef QT_BOOTSTRAPPED
1687#include "moc_qcalendar.cpp"
1688#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