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