mirror of https://github.com/qt/qtbase.git
1061 lines
35 KiB
C++
1061 lines
35 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2019 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the QtCore module of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:GPL$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3 or (at your option) any later version
|
|
** approved by the KDE Free Qt Foundation. The licenses are as published by
|
|
** the Free Software Foundation and appearing in the file LICENSE.GPL3
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
#include "qcalendar.h"
|
|
#include "qcalendarbackend_p.h"
|
|
#include "qgregoriancalendar_p.h"
|
|
|
|
#include "qdatetime.h"
|
|
#include "qcalendarmath_p.h"
|
|
#include <qhash.h>
|
|
#include <qdebug.h>
|
|
|
|
#include <unordered_map>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
namespace {
|
|
|
|
struct CalendarName : public QString
|
|
{
|
|
CalendarName(const QString &name) : QString(name) {}
|
|
};
|
|
|
|
inline bool operator==(const CalendarName &u, const CalendarName &v)
|
|
{
|
|
return u.compare(v, Qt::CaseInsensitive) == 0;
|
|
}
|
|
|
|
inline uint qHash(const CalendarName &key, uint seed = 0) noexcept
|
|
{
|
|
return qHash(key.toLower(), seed);
|
|
}
|
|
|
|
struct Registry {
|
|
std::vector<QCalendarBackend *> byId;
|
|
QHash<CalendarName, QCalendarBackend *> byName;
|
|
QCalendarBackend *gregorianCalendar = nullptr;
|
|
bool populated = false;
|
|
|
|
Registry()
|
|
{
|
|
byId.resize(int(QCalendar::System::Last) + 1);
|
|
}
|
|
|
|
~Registry()
|
|
{
|
|
qDeleteAll(byId);
|
|
}
|
|
|
|
bool registerName(QCalendarBackend *calendar, const QString &name)
|
|
{
|
|
if (byName.find(name) != byName.end()) {
|
|
qWarning() << "Calendar name" << name
|
|
<< "is already taken, new calendar will not be registered.";
|
|
return false;
|
|
}
|
|
byName.insert(name, calendar);
|
|
return true;
|
|
}
|
|
void addCalendar(QCalendarBackend *calendar, const QString &name, QCalendar::System id)
|
|
{
|
|
if (!registerName(calendar, name))
|
|
return;
|
|
Q_ASSERT(byId.size() >= size_t(id));
|
|
if (id == QCalendar::System::User) {
|
|
byId.push_back(calendar);
|
|
} else {
|
|
Q_ASSERT(byId.at(size_t(id)) == nullptr);
|
|
byId[size_t(id)] = calendar;
|
|
}
|
|
if (id == QCalendar::System::Gregorian) {
|
|
Q_ASSERT(!gregorianCalendar);
|
|
gregorianCalendar = calendar;
|
|
}
|
|
}
|
|
/*
|
|
\internal
|
|
Ensures each enum-available calendar has been instantiated.
|
|
|
|
This arranges for each to register itself by name; it only does anything on
|
|
its first call, which ensures that name-based lookups can always find all
|
|
the calendars available via the enum.
|
|
*/
|
|
void populate()
|
|
{
|
|
if (populated)
|
|
return;
|
|
|
|
for (int i = 0; i <= int(QCalendar::System::Last); ++i)
|
|
(void)QCalendar(QCalendar::System(i));
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
Q_GLOBAL_STATIC(Registry, calendarRegistry);
|
|
|
|
|
|
/*!
|
|
\since 5.14
|
|
|
|
\class QCalendarBackend
|
|
\inmodule QtCore
|
|
\reentrant
|
|
\brief The QCalendarBackend class provides basic calendaring functions.
|
|
|
|
QCalendarBackend provides the base class on which all calendar types are
|
|
implemented. On construction, the backend is registered with its primary
|
|
name.
|
|
|
|
A backend may also be registered with aliases, where the calendar is known
|
|
by several names. Registering with the name used by CLDR (the Unicode
|
|
consortium's Common Locale Data Repository) is recommended, particularly
|
|
when interacting with third-party software. Once a backend is registered for
|
|
a name, QCalendar can be constructed using that name to select the backend.
|
|
|
|
Each calendar backend must inherit from QCalendarBackend and implement its
|
|
pure virtual methods. It may also override some other virtual methods, as
|
|
needed.
|
|
|
|
Most backends are pure code, with no data elements. Such backends should
|
|
normally be implemented as singletons. For a backend to be added to the
|
|
QCalendar::System enum, it should be such a singleton, with a case in
|
|
QCalendar::fromEnum()'s switch statement to instantiate it.
|
|
|
|
Non-singleton calendar backends should ensure that each instance is created
|
|
with a distinct primary name. Later instances attempting to register with a
|
|
name already in use shall fail to register and be unavailable to QCalendar,
|
|
hence unusable.
|
|
|
|
\sa registerAlias(), QDate, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
|
|
*/
|
|
|
|
/*!
|
|
Constructs the calendar and registers it.
|
|
*/
|
|
QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System id)
|
|
{
|
|
calendarRegistry->addCalendar(this, name, id);
|
|
}
|
|
|
|
/*!
|
|
Destroys the calendar.
|
|
|
|
Never call this from user code. Each calendar backend, once instantiated,
|
|
shall exist for the lifetime of the program. Its destruction is taken care
|
|
of by destruction of the registry of calendar backends and their names.
|
|
*/
|
|
QCalendarBackend::~QCalendarBackend()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
The calendar system of this calendar.
|
|
|
|
Each calendar backend constructible from the QCalendar::System enum should
|
|
return the member of that enum that produces it. Other calendars should
|
|
return User.
|
|
|
|
\sa QCalendar::fromEnum()
|
|
*/
|
|
QCalendar::System QCalendarBackend::calendarSystem() const
|
|
{
|
|
return QCalendar::System::User;
|
|
}
|
|
|
|
/*!
|
|
The primary name of this calendar.
|
|
*/
|
|
QString QCalendar::name() const
|
|
{
|
|
return d ? d->name() : QString();
|
|
}
|
|
|
|
// date queries
|
|
/*!
|
|
\fn int QCalendarBackend::daysInMonth(int month, int year) const
|
|
|
|
Returns number of days in the month number \a month, in year \a year.
|
|
|
|
An implementation should return 0 if the given year had no such month. If
|
|
year is QCalendar::Unspecified, return the usual number of days for the
|
|
month, in those years that include it.
|
|
|
|
Calendars with intercallary days may represent these as extra days of the
|
|
preceding month, or as short months separate from the usual ones. In the
|
|
former case, daysInMonth(month, year) should be the number of ordinary days
|
|
in the month, although \c{isDateValid(year, month, day)} might return \c true for
|
|
some larger values of \c day.
|
|
|
|
\sa daysInYear(), monthsInYear(), minDaysInMonth(), maxDaysInMonth()
|
|
*/
|
|
|
|
// properties of the calendar
|
|
|
|
/*!
|
|
\fn bool QCalendarBackend::isLeapYear(int year) const
|
|
|
|
Returns \c true if the specified \a year is a leap year for this calendar.
|
|
|
|
\sa daysInYear(), isDateValid()
|
|
*/
|
|
|
|
/*!
|
|
\fn bool QCalendarBackend::isLunar() const
|
|
|
|
Returns \c true if this calendar is a lunar calendar. Otherwise returns \c
|
|
false.
|
|
|
|
A lunar calendar is a calendar based upon the monthly cycles of the Moon's
|
|
phases (synodic months). This contrasts with solar calendars, whose annual
|
|
cycles are based only upon the solar year.
|
|
|
|
\sa isLuniSolar(), isSolar(), isProleptic()
|
|
*/
|
|
|
|
/*!
|
|
\fn bool QCalendarBackend::isLuniSolar() const
|
|
|
|
Returns \c true if this calendar is a lunisolar calendar. Otherwise returns
|
|
\c false.
|
|
|
|
A lunisolar calendar is a calendar whose date indicates both the moon phase
|
|
and the time of the solar year.
|
|
|
|
\sa isLunar(), isSolar(), isProleptic()
|
|
*/
|
|
|
|
/*!
|
|
\fn bool QCalendarBackend::isSolar() const
|
|
|
|
Returns \c true if this calendar is a solar calendar. Otherwise returns
|
|
\c false.
|
|
|
|
A solar calendar is a calendar whose dates indicate the season or almost
|
|
equivalently the apparent position of the sun relative to the fixed stars.
|
|
The Gregorian calendar, widely accepted as standard in the world,
|
|
is an example of solar calendar.
|
|
|
|
\sa isLuniSolar(), isLunar(), isProleptic()
|
|
*/
|
|
|
|
/*!
|
|
Returns the total number of days in the year number \a year.
|
|
Returns zero if there is no such year in this calendar.
|
|
|
|
This base implementation returns 366 for leap years and 365 for ordinary
|
|
years.
|
|
|
|
\sa monthsInYear(), daysInMonth(), isLeapYear()
|
|
*/
|
|
int QCalendarBackend::daysInYear(int year) const
|
|
{
|
|
return monthsInYear(year) ? isLeapYear(year) ? 366 : 365 : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the total number of months in the year number \a year.
|
|
Returns zero if there is no such year in this calendar.
|
|
|
|
This base implementation returns 12 for any valid year.
|
|
|
|
\sa daysInYear(), maxMonthsInYear(), isDateValid()
|
|
*/
|
|
int QCalendarBackend::monthsInYear(int year) const
|
|
{
|
|
return year > 0 || (year < 0 ? isProleptic() : hasYearZero()) ? 12 : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if the date specified by \a year, \a month, and \a day is
|
|
valid for this calendar; otherwise returns \c false. For example,
|
|
the date 2018-04-19 is valid for the Gregorian calendar, but 2018-16-19 and
|
|
2018-04-38 are invalid.
|
|
|
|
Calendars with intercallary days may represent these as extra days of the
|
|
preceding month or as short months separate from the usual ones. In the
|
|
former case, a \a day value greater than \c{daysInMonth(\a{month},
|
|
\a{year})} may be valid.
|
|
|
|
\sa daysInMonth(), monthsInYear()
|
|
*/
|
|
bool QCalendarBackend::isDateValid(int year, int month, int day) const
|
|
{
|
|
return day > 0 && day <= daysInMonth(month, year);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar is a proleptic calendar. Otherwise returns
|
|
\c false.
|
|
|
|
A proleptic calendar results from allowing negative year numbers to indicate
|
|
years before the nominal start of the calendar system.
|
|
|
|
\sa isLuniSolar(), isSolar(), isLunar(), hasYearZero()
|
|
*/
|
|
|
|
bool QCalendarBackend::isProleptic() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if year number \c 0 is considered a valid year in this
|
|
calendar. Otherwise returns \c false.
|
|
|
|
\sa isDateValid(), isProleptic()
|
|
*/
|
|
|
|
bool QCalendarBackend::hasYearZero() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/*!
|
|
Returns the maximum number of days in a month for any year.
|
|
|
|
This base implementation returns 31, as this is a common case.
|
|
|
|
For calendars with intercallary days, although daysInMonth() doesn't include
|
|
the intercallary days in its count for an individual month, maxDaysInMonth()
|
|
should include intercallary days, so that it is the maximum value of \c day
|
|
for which \c{isDateValid(year, month, day)} can be true.
|
|
|
|
\sa maxMonthsInYear(), daysInMonth()
|
|
*/
|
|
int QCalendarBackend::maxDaysInMonth() const
|
|
{
|
|
return 31;
|
|
}
|
|
|
|
/*!
|
|
Returns the minimum number of days in any valid month of any valid year.
|
|
|
|
This base implementation returns 29, as this is a common case.
|
|
|
|
\sa maxMonthsInYear(), daysInMonth()
|
|
*/
|
|
int QCalendarBackend::minDaysInMonth() const
|
|
{
|
|
return 29;
|
|
}
|
|
|
|
/*!
|
|
Returns the maximum number of months possible in any year.
|
|
|
|
This base implementation returns 12, as this is a common case.
|
|
|
|
\sa maxDaysInMonth(), monthsInYear()
|
|
*/
|
|
int QCalendarBackend::maxMonthsInYear() const
|
|
{
|
|
return 12;
|
|
}
|
|
|
|
// Julian day number calculations
|
|
|
|
/*!
|
|
\fn bool dateToJulianDay(int year, int month, int day, qint64 *jd) const
|
|
|
|
Computes the Julian day number corresponding to the specified \a year, \a
|
|
month, and \a day. Returns true and sets \a jd if there is such a date in
|
|
this calendar; otherwise, returns false.
|
|
|
|
\sa QCalendar::partsFromDate(), julianDayToDate()
|
|
*/
|
|
|
|
/*!
|
|
\fn QCalendar::YearMonthDay julianDayToDate(qint64 jd) const
|
|
|
|
Computes the year, month, and day in this calendar for the given Julian day
|
|
number \a jd. If the given day falls outside this calendar's scope
|
|
(e.g. before the start-date of a non-proleptic calendar), the returned
|
|
structure's isValid() is false; otherwise, its year, month, and day fields
|
|
provide this calendar's description of the date.
|
|
|
|
\sa QCalendar::dateFromParts(), dateToJulianDay()
|
|
*/
|
|
|
|
/*!
|
|
Returns the day of the week for a given Julian Day Number.
|
|
|
|
This is 1 for Monday through 7 for Sunday.
|
|
|
|
Calendars with intercallary days may return larger values for these
|
|
intercallary days. They should avoid using 0 for any special purpose (it is
|
|
already used in QDate::dayOfWeek() to mean an invalid date). The calendar
|
|
should treat the numbers used as an \c enum, whose values need not be
|
|
contiguous, nor need they follow closely from the 1 through 7 of the usual
|
|
returns. It suffices that weekDayName() can recognize each such number as
|
|
identifying a distinct name, that it returns to identify the particular
|
|
intercallary day.
|
|
|
|
This base implementation uses the day-numbering that various calendars have
|
|
borrowed off the Hebrew calendar.
|
|
|
|
\sa weekDayName(), standaloneWeekDayName(), QDate::dayOfWeek()
|
|
*/
|
|
int QCalendarBackend::dayOfWeek(qint64 jd) const
|
|
{
|
|
return QRoundingDown::qMod(jd, 7) + 1;
|
|
}
|
|
|
|
// Month and week-day name look-ups (implemented in qlocale.cpp):
|
|
/*!
|
|
\fn QString QCalendarBackend::monthName(const QLocale &locale, int month, int year,
|
|
QLocale::FormatType format) const
|
|
|
|
Returns the name of the specified \a month in the given \a year for the chosen
|
|
\a locale, using the given \a format to determine how complete the name is.
|
|
|
|
If \a year is Unspecified, return the name for the month that usually has this
|
|
number within a typical year. Calendars with a leap month that isn't always
|
|
the last may need to take account of the year to map the month number to the
|
|
particular year's month with that number.
|
|
|
|
\note Backends for which CLDR provides data can configure the default
|
|
implementation of the two month name look-up methods by arranging for
|
|
localeMonthIndexData() and localeMonthData() to provide access to the CLDR
|
|
data (see cldr2qlocalexml.py, qlocalexml2cpp.py and existing backends).
|
|
Conversely, backends that override both month name look-up methods need not
|
|
return anything meaningful from localeMonthIndexData() or localeMonthData().
|
|
|
|
\sa standaloneMonthName(), QLocale::monthName()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int year
|
|
QLocale::FormatType format) const
|
|
|
|
Returns the standalone name of the specified \a month in the chosen \a locale,
|
|
using the specified \a format to determine how complete the name is.
|
|
|
|
If \a year is Unspecified, return the standalone name for the month that
|
|
usually has this number within a typical year. Calendars with a leap month
|
|
that isn't always the last may need to take account of the year to map the
|
|
month number to the particular year's month with that number.
|
|
|
|
\sa monthName(), QLocale::standaloneMonthName()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
|
|
QLocale::FormatType format) const
|
|
|
|
Returns the name of the specified \a day of the week in the chosen \a locale,
|
|
using the specified \a format to determine how complete the name is.
|
|
|
|
The base implementation handles \a day values from 1 to 7 using the day names
|
|
CLDR provides, which are suitable for calendards that use the same
|
|
(Hebrew-derived) week as the Gregorian calendar.
|
|
|
|
Calendars whose dayOfWeek() returns a value outside the range from 1 to 7 need
|
|
to reimplement this method to handle such extra week-day values. They can
|
|
assume that \a day is a value returned by the same calendar's dayOfWeek().
|
|
|
|
\sa dayOfWeek(), standaloneWeekDayName(), QLocale::dayName()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
|
|
QLocale::FormatType format) const
|
|
|
|
Returns the standalone name of the specified \a day of the week in the chosen
|
|
\a locale, using the specified \a format to determine how complete the name
|
|
is.
|
|
|
|
The base implementation handles \a day values from 1 to 7 using the standalone
|
|
day names CLDR provides, which are suitable for calendards that use the same
|
|
(Hebrew-derived) week as the Gregorian calendar.
|
|
|
|
Calendars whose dayOfWeek() returns a value outside the range from 1 to 7 need
|
|
to reimplement this method to handle such extra week-day values. They can
|
|
assume that \a day is a value returned by the same calendar's dayOfWeek().
|
|
|
|
\sa dayOfWeek(), weekDayName(), QLocale::standaloneDayName()
|
|
*/
|
|
|
|
/*!
|
|
\fn QString QCalendarBackend::dateTimeToString(QStringView format, const QDateTime &datetime,
|
|
const QDate &dateOnly, const QTime &timeOnly,
|
|
const QLocale &locale) const
|
|
|
|
Returns a string representing a given date, time or date-time.
|
|
|
|
If \a datetime is specified and valid, it is used and both date and time
|
|
format tokens are converted to appropriate representations of the parts of the
|
|
datetime. Otherwise, if \a dateOnly is valid, only date format tokens are
|
|
converted; else, if \a timeOnly is valid, only time format tokens are
|
|
converted. If none are valid, an empty string is returned.
|
|
|
|
The specified \a locale influences how some format tokens are converted; for
|
|
example, when substituting day and month names and their short-forms. For the
|
|
supported formatting tokens, see QDate::toString() and QTime::toString(). As
|
|
described above, the provided date, time and date-time determine which of
|
|
these tokens are recognized: where these appear in \a format they are replaced
|
|
by data. Any text in \a format not recognized as a format token is copied
|
|
verbatim into the result string.
|
|
|
|
\sa QDate::toString(), QTime::toString(), QDateTime::toString()
|
|
*/
|
|
// End of methods implemented in qlocale.cpp
|
|
|
|
/*!
|
|
Returns a list of names of the available calendar systems. Any
|
|
QCalendarBackend sub-class must be registered before being exposed to Date
|
|
and Time APIs.
|
|
|
|
\sa registerCalendar(), fromName()
|
|
*/
|
|
QStringList QCalendarBackend::availableCalendars()
|
|
{
|
|
if (calendarRegistry.isDestroyed())
|
|
return {};
|
|
calendarRegistry->populate();
|
|
return QStringList(calendarRegistry->byName.keyBegin(), calendarRegistry->byName.keyEnd());
|
|
}
|
|
|
|
/*!
|
|
Registers an alias for this calendar backend. Once a backend is registered,
|
|
its name will be included in the list of available calendars and the
|
|
calendar can be instantiated by name.
|
|
|
|
Returns \c false if the given \a name is already in use, otherwise it
|
|
registers this calendar backend and returns \c true.
|
|
|
|
\sa availableCalendars(), fromName()
|
|
*/
|
|
bool QCalendarBackend::registerAlias(const QString &name)
|
|
{
|
|
if (calendarRegistry.isDestroyed())
|
|
return false;
|
|
return calendarRegistry->registerName(this, name);
|
|
}
|
|
|
|
/*!
|
|
Returns a pointer to a named calendar backend.
|
|
|
|
If the given \a name is present in availableCalendars(), the backend matching
|
|
it is returned; otherwise, \c nullptr is returned. Matching of names ignores
|
|
case. Note that this won't provoke construction of a calendar backend, it will
|
|
only return ones that have been instantiated (and not yet destroyed) by some
|
|
other means. However, calendars available via the QCalendar::System enum are
|
|
always registered when this is called.
|
|
|
|
\sa availableCalendars(), registerCalendar(), fromEnum()
|
|
*/
|
|
const QCalendarBackend *QCalendarBackend::fromName(QStringView name)
|
|
{
|
|
if (calendarRegistry.isDestroyed())
|
|
return nullptr;
|
|
calendarRegistry->populate();
|
|
auto it = calendarRegistry->byName.find(name.toString());
|
|
return it == calendarRegistry->byName.end() ? nullptr : *it;
|
|
}
|
|
|
|
/*!
|
|
\overload
|
|
*/
|
|
const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
|
|
{
|
|
if (calendarRegistry.isDestroyed())
|
|
return nullptr;
|
|
calendarRegistry->populate();
|
|
auto it = calendarRegistry->byName.find(QString(name));
|
|
return it == calendarRegistry->byName.end() ? nullptr : *it;
|
|
}
|
|
|
|
/*!
|
|
Returns a pointer to a calendar backend, specified by enum.
|
|
|
|
This will instantiate the indicated calendar (which will enable fromName() to
|
|
return it subsequently), but only for the Qt-supported calendars for which
|
|
(where relevant) the appropriate feature has been enabled.
|
|
*/
|
|
const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
|
|
{
|
|
if (calendarRegistry.isDestroyed() || system == QCalendar::System::User)
|
|
return nullptr;
|
|
Q_ASSERT(calendarRegistry->byId.size() >= size_t(system));
|
|
if (auto *c = calendarRegistry->byId.at(size_t(system)))
|
|
return c;
|
|
switch (system) {
|
|
case QCalendar::System::Gregorian:
|
|
return new QGregorianCalendar;
|
|
case QCalendar::System::User:
|
|
Q_UNREACHABLE();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
\since 5.14
|
|
|
|
\class QCalendar
|
|
\inmodule QtCore
|
|
\reentrant
|
|
\brief The QCalendar class describes calendar systems.
|
|
|
|
A QCalendar object maps a year, month, and day-number to a specific day
|
|
(ultimately identified by its Julian day number), using the rules of a
|
|
particular system.
|
|
|
|
The default QCalendar() is a proleptic Gregorian calendar, which has no year
|
|
zero. Other calendars may be supported by enabling suitable features or
|
|
loading plugins. Calendars supported as features can be constructed by passing
|
|
the QCalendar::System enumeration to the constructor. All supported calendars
|
|
may be constructed by name, once they have been constructed. (Thus plugins
|
|
instantiate their calendar backend to register it.) Built-in backends,
|
|
accessible via QCalendar::System, are also always available by name.
|
|
|
|
A QCalendar value is immutable.
|
|
|
|
\sa QCalendarBackend, QDate, QDateTime
|
|
*/
|
|
|
|
/*!
|
|
\enum QCalendar::System
|
|
|
|
This enumerated type is used to specify a choice of calendar system.
|
|
|
|
\value Gregorian The default calendar, used internationally.
|
|
|
|
\sa QCalendar
|
|
*/
|
|
|
|
/*!
|
|
\fn QCalendar::QCalendar()
|
|
\fn QCalendar::QCalendar(QCalendar::System system)
|
|
\fn QCalendar::QCalendar(QLatin1String name)
|
|
\fn QCalendar::QCalendar(QStringView name)
|
|
|
|
Constructs a calendar object.
|
|
|
|
The choice of calendar to use may be indicated as \a system, using the
|
|
enumeration QCalendar::System, or by \a name, using a string (either Unicode
|
|
or Latin 1). Construction by name may depend on an instance of the given
|
|
calendar being constructed by other means first. With no argument, the default
|
|
constructor returns the Gregorian calendar.
|
|
|
|
\sa QCalendar, System
|
|
*/
|
|
|
|
QCalendar::QCalendar()
|
|
: d(nullptr)
|
|
{
|
|
if (calendarRegistry.isDestroyed())
|
|
return;
|
|
d = calendarRegistry->gregorianCalendar;
|
|
if (!d)
|
|
d = new QGregorianCalendar;
|
|
}
|
|
|
|
QCalendar::QCalendar(QCalendar::System system)
|
|
: d(QCalendarBackend::fromEnum(system)) {}
|
|
|
|
QCalendar::QCalendar(QLatin1String name)
|
|
: d(QCalendarBackend::fromName(name)) {}
|
|
|
|
QCalendar::QCalendar(QStringView name)
|
|
: d(QCalendarBackend::fromName(name)) {}
|
|
|
|
// Date queries:
|
|
|
|
/*!
|
|
Returns the number of days in the given \a month of the given \a year.
|
|
|
|
Months are numbered consecutively, starting with 1 for the first month of each
|
|
year.
|
|
|
|
\sa maxDaysInMonth(), minDaysInMonth()
|
|
*/
|
|
int QCalendar::daysInMonth(int month, int year) const
|
|
{
|
|
return d ? d->daysInMonth(month, year) : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of days in the given \a year.
|
|
*/
|
|
int QCalendar::daysInYear(int year) const
|
|
{
|
|
return d ? d->daysInYear(year) : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of months in the given \a year.
|
|
*/
|
|
int QCalendar::monthsInYear(int year) const
|
|
{
|
|
return d ? d->monthsInYear(year) : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true precisely if the given \a year, \a month, and \a day specify a
|
|
valid date in this calendar.
|
|
|
|
Usually this means 1 <= month <= monthsInYear(year) and 1 <= day <=
|
|
daysInMonth(month, year). However, calendars with intercallary days or months
|
|
may complicate that.
|
|
*/
|
|
bool QCalendar::isDateValid(int year, int month, int day) const
|
|
{
|
|
return d && d->isDateValid(year, month, day);
|
|
}
|
|
|
|
// properties of the calendar
|
|
|
|
/*!
|
|
Returns \c true if this calendar object is the Gregorian calendar object
|
|
used as default calendar by other Qt APIs, e.g. in QDate.
|
|
*/
|
|
bool QCalendar::isGregorian() const
|
|
{
|
|
Q_ASSERT(!calendarRegistry.isDestroyed());
|
|
return d == calendarRegistry->gregorianCalendar;
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if the given year is a leap year.
|
|
|
|
Since the year is not a whole number of days long, some years are longer than
|
|
others. The difference may be a whole month or just a single day; the details
|
|
vary between calendars.
|
|
|
|
\sa isDateValid()
|
|
*/
|
|
bool QCalendar::isLeapYear(int year) const
|
|
{
|
|
return d && d->isLeapYear(year);
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar is a lunar calendar.
|
|
|
|
A lunar calendar is one based primarily on the phases of the moon.
|
|
*/
|
|
bool QCalendar::isLunar() const
|
|
{
|
|
return d && d->isLunar();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar is luni-solar.
|
|
|
|
A luni-solar calendar expresses the phases of the moon but adapts itself to
|
|
also keep track of the Sun's varying position in the sky, relative to the
|
|
fixed stars.
|
|
*/
|
|
bool QCalendar::isLuniSolar() const
|
|
{
|
|
return d && d->isLuniSolar();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar is solar.
|
|
|
|
A solar calendar is based primaril on the Sun's varying position in the sky,
|
|
relative to the fixed stars.
|
|
*/
|
|
bool QCalendar::isSolar() const
|
|
{
|
|
return d && d->isSolar();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar is proleptic.
|
|
|
|
A proleptic calendar is able to describe years arbitrarily long before its
|
|
first. These are represented by negative year numbers and possibly by a year
|
|
zero.
|
|
|
|
\sa hasYearZero()
|
|
*/
|
|
bool QCalendar::isProleptic() const
|
|
{
|
|
return d && d->isProleptic();
|
|
}
|
|
|
|
/*!
|
|
Returns \c true if this calendar has a year zero.
|
|
|
|
A non-proleptic calendar with no year zero represents years from its first
|
|
year onwards but provides no way to describe years before its first; such a
|
|
calendar has no year zero and is not proleptic.
|
|
|
|
A calendar which represents years before its first may number these years
|
|
simply by following the usual integer counting, so that the year before the
|
|
first is year zero, with negative-numbered years preceding this; such a
|
|
calendar is proleptic and has a year zero. A calendar might also have a year
|
|
zero (for example, the year of some great event, with subsequent years being
|
|
the first year after that event, the second year after, and so on) without
|
|
describing years before its year zero. Such a calendar would have a year zero
|
|
without being proleptic.
|
|
|
|
Some calendars, however, represent years before their first by an alternate
|
|
numbering; for example, the proleptic Gregorian calendar's first year is 1 CE
|
|
and the year before it is 1 BCE, preceded by 2 BCE and so on. In this case,
|
|
we use negative year numbers, with year -1 as the year before year 1, year -2
|
|
as the year before year -1 and so on. Such a calendar is proleptic but has no
|
|
year zero.
|
|
|
|
\sa isProleptic()
|
|
*/
|
|
bool QCalendar::hasYearZero() const
|
|
{
|
|
return d && d->hasYearZero();
|
|
}
|
|
|
|
/*!
|
|
Returns the number of days in the longest month in the calendar, in any year.
|
|
|
|
\sa daysInMonth(), minDaysInMonth()
|
|
*/
|
|
int QCalendar::maxDaysInMonth() const
|
|
{
|
|
return d ? d->maxDaysInMonth() : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of days in the shortest month in the calendar, in any year.
|
|
|
|
\sa daysInMonth(), maxDaysInMonth()
|
|
*/
|
|
int QCalendar::minDaysInMonth() const
|
|
{
|
|
return d ? d->minDaysInMonth() : 0;
|
|
}
|
|
|
|
/*!
|
|
Returns the largest number of months that any year may contain.
|
|
|
|
\sa monthName(), standaloneMonthName(), monthsInYear()
|
|
*/
|
|
int QCalendar::maxMonthsInYear() const
|
|
{
|
|
return d ? d->maxMonthsInYear() : 0;
|
|
}
|
|
|
|
// Julian Day conversions:
|
|
|
|
/*!
|
|
\fn QDate QCalendar::dateFromParts(int year, int month, int day) const
|
|
\fn QDate QCalendar::dateFromParts(QCalendar::YearMonthDay parts) const
|
|
|
|
Converts a year, month, and day to a QDate.
|
|
|
|
The \a year, \a month, and \a day may be passed as separate numbers or
|
|
packaged together as the members of \a parts. Returns a QDate with the given
|
|
year, month, and day of the month in this calendar, if there is one.
|
|
Otherwise, including the case where any of the values is
|
|
QCalendar::Unspecified, returns a QDate whose isNull() is true.
|
|
|
|
\sa isDateValid(), partsFromDate()
|
|
*/
|
|
QDate QCalendar::dateFromParts(int year, int month, int day) const
|
|
{
|
|
qint64 jd;
|
|
return d && d->dateToJulianDay(year, month, day, &jd)
|
|
? QDate::fromJulianDay(jd) : QDate();
|
|
}
|
|
|
|
QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
|
|
{
|
|
return parts.isValid() ? dateFromParts(parts.year, parts.month, parts.day) : QDate();
|
|
}
|
|
|
|
/*!
|
|
Converts a QDate to a year, month, and day of the month.
|
|
|
|
The returned structure's isValid() shall be false if the calendar is unable
|
|
to represent the given \a date. Otherwise its \a year, \a month, and \a day
|
|
members record the so-named parts of its representation.
|
|
|
|
\sa dateFromParts(), isProleptic(), hasYearZero()
|
|
*/
|
|
QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
|
|
{
|
|
return d ? d->julianDayToDate(date.toJulianDay()) : YearMonthDay();
|
|
}
|
|
|
|
/*!
|
|
Returns the day of the week number for the given \a date.
|
|
|
|
Returns zero if the calendar is unable to represent the indicated date.
|
|
Returns 1 for Monday through 7 for Sunday. Calendars with intercallary days
|
|
may use other numbers to represent these.
|
|
|
|
\sa partsFromDate(), Qt::DayOfWeek
|
|
*/
|
|
int QCalendar::dayOfWeek(QDate date) const
|
|
{
|
|
return d ? d->dayOfWeek(date.toJulianDay()) : 0;
|
|
}
|
|
|
|
// Locale data access
|
|
|
|
/*!
|
|
Returns a suitably localised name for a month.
|
|
|
|
The month is indicated by a number, with \a month = 1 meaning the first month
|
|
of the year and subsequent months numbered accordingly. Returns an empty
|
|
string if the \a month number is unrecognized.
|
|
|
|
The \a year may be Unspecified, in which case the mapping from numbers to
|
|
names for a typical year's months should be used. Some calendars have leap
|
|
months that aren't always at the end of the year; their mapping of month
|
|
numbers to names may then depend on the placement of a leap month. Thus the
|
|
year should normally be specified, if known.
|
|
|
|
The name is returned in the form that would normally be used in a full date,
|
|
in the specified \a locale; the \a format determines how fully it shall be
|
|
expressed (i.e. to what extent it is abbreviated).
|
|
|
|
\sa standaloneMonthName(), maxMonthsInYear(), dateTimeString()
|
|
*/
|
|
QString QCalendar::monthName(const QLocale &locale, int month, int year,
|
|
QLocale::FormatType format) const
|
|
{
|
|
const int maxMonth = year == Unspecified ? maxMonthsInYear() : monthsInYear(year);
|
|
if (!d || month < 1 || month > maxMonth)
|
|
return QString();
|
|
|
|
return d->monthName(locale, month, year, format);
|
|
}
|
|
|
|
/*!
|
|
Returns a suitably localised standalone name for a month.
|
|
|
|
The month is indicated by a number, with \a month = 1 meaning the first month
|
|
of the year and subsequent months numbered accordingly. Returns an empty
|
|
string if the \a month number is unrecognized.
|
|
|
|
The \a year may be Unspecified, in which case the mapping from numbers to
|
|
names for a typical year's months should be used. Some calendars have leap
|
|
months that aren't always at the end of the year; their mapping of month
|
|
numbers to names may then depend on the placement of a leap month. Thus the
|
|
year should normally be specified, if known.
|
|
|
|
The name is returned in the form that would be used in isolation in the
|
|
specified \a locale; the \a format determines how fully it shall be expressed
|
|
(i.e. to what extent it is abbreviated).
|
|
|
|
\sa monthName(), maxMonthsInYear(), dateTimeString()
|
|
*/
|
|
QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
|
|
QLocale::FormatType format) const
|
|
{
|
|
const int maxMonth = year == Unspecified ? maxMonthsInYear() : monthsInYear(year);
|
|
if (!d || month < 1 || month > maxMonth)
|
|
return QString();
|
|
|
|
return d->standaloneMonthName(locale, month, year, format);
|
|
}
|
|
|
|
/*!
|
|
Returns a suitably localised name for a day of the week.
|
|
|
|
The days of the week are numbered from 1 for Monday through 7 for Sunday. Some
|
|
calendars may support higher numbers for other days (e.g. intercallary days,
|
|
that are not part of any week). Returns an empty string if the \a day number
|
|
is unrecognized.
|
|
|
|
The name is returned in the form that would normally be used in a full date,
|
|
in the specified \a locale; the \a format determines how fully it shall be
|
|
expressed (i.e. to what extent it is abbreviated).
|
|
|
|
\sa standaloneWeekDayName(), dayOfWeek()
|
|
*/
|
|
QString QCalendar::weekDayName(const QLocale &locale, int day,
|
|
QLocale::FormatType format) const
|
|
{
|
|
return d ? d->weekDayName(locale, day, format) : QString();
|
|
}
|
|
|
|
/*!
|
|
Returns a suitably localised standalone name for a day of the week.
|
|
|
|
The days of the week are numbered from 1 for Monday through 7 for Sunday. Some
|
|
calendars may support higher numbers for other days (e.g. intercallary days,
|
|
that are not part of any week). Returns an empty string if the \a day number
|
|
is unrecognized.
|
|
|
|
The name is returned in the form that would be used in isolation (for example
|
|
as a column heading in a calendar's tabular display of a month with successive
|
|
weeks as rows) in the specified \a locale; the \a format determines how fully
|
|
it shall be expressed (i.e. to what extent it is abbreviated).
|
|
|
|
\sa weekDayName(), dayOfWeek()
|
|
*/
|
|
QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
|
|
QLocale::FormatType format) const
|
|
{
|
|
return d ? d->standaloneWeekDayName(locale, day, format) : QString();
|
|
}
|
|
|
|
/*!
|
|
Returns a string representing a given date, time or date-time.
|
|
|
|
If \a datetime is valid, it is represented and format specifiers for both date
|
|
and time fields are recognized; otherwise, if \a dateOnly is valid, it is
|
|
represented and only format specifiers for date fields are recognized;
|
|
finally, if \a timeOnly is valid, it is represented and only format specifiers
|
|
for time fields are recognized. If none of these is valid, an empty string is
|
|
returned.
|
|
|
|
See QDate::toString and QTime::toString() for the supported field specifiers.
|
|
Characters in \a format that are recognized as field specifiers are replaced
|
|
by text representing appropriate data from the date and/or time being
|
|
represented. The texts to represent them may depend on the \a locale
|
|
specified. Other charagers in \a format are copied verbatim into the returned
|
|
string.
|
|
|
|
\sa monthName(), weekDayName(), QDate::toString(), QTime::toString()
|
|
*/
|
|
QString QCalendar::dateTimeToString(QStringView format, const QDateTime &datetime,
|
|
const QDate &dateOnly, const QTime &timeOnly,
|
|
const QLocale &locale) const
|
|
{
|
|
return d ? d->dateTimeToString(format, datetime, dateOnly, timeOnly, locale) : QString();
|
|
}
|
|
|
|
/*!
|
|
Returns a list of names of the available calendar systems.
|
|
|
|
These may be supplied by plugins or other code linked into an application,
|
|
in addition to the ones provided by Qt, some of which are controlled by
|
|
features.
|
|
*/
|
|
QStringList QCalendar::availableCalendars()
|
|
{
|
|
return QCalendarBackend::availableCalendars();
|
|
}
|
|
|
|
QT_END_NAMESPACE
|