summaryrefslogtreecommitdiffstats
path: root/src/corelib/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/time')
-rw-r--r--src/corelib/time/qcalendar.cpp551
-rw-r--r--src/corelib/time/qcalendar.h10
-rw-r--r--src/corelib/time/qcalendarbackend_p.h6
-rw-r--r--src/corelib/time/qdatetime.cpp98
-rw-r--r--src/corelib/time/qdatetimeparser.cpp26
-rw-r--r--src/corelib/time/qgregoriancalendar.cpp2
-rw-r--r--src/corelib/time/qhijricalendar.cpp49
-rw-r--r--src/corelib/time/qhijricalendar_p.h2
-rw-r--r--src/corelib/time/qislamiccivilcalendar.cpp32
-rw-r--r--src/corelib/time/qromancalendar.cpp22
-rw-r--r--src/corelib/time/qromancalendar_p.h2
-rw-r--r--src/corelib/time/qtimezone.cpp23
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp48
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h3
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp42
15 files changed, 519 insertions, 397 deletions
diff --git a/src/corelib/time/qcalendar.cpp b/src/corelib/time/qcalendar.cpp
index b569a6834c..d308aeba2b 100644
--- a/src/corelib/time/qcalendar.cpp
+++ b/src/corelib/time/qcalendar.cpp
@@ -136,6 +136,7 @@ Q_GLOBAL_STATIC(Registry, calendarRegistry);
\class QCalendarBackend
\inmodule QtCore
+ \internal
\reentrant
\brief The QCalendarBackend class provides basic calendaring functions.
@@ -167,7 +168,7 @@ Q_GLOBAL_STATIC(Registry, calendarRegistry);
*/
/*!
- Constructs the calendar and registers it.
+ Constructs the calendar and registers it under \a name using \a id.
*/
QCalendarBackend::QCalendarBackend(const QString &name, QCalendar::System id)
{
@@ -192,7 +193,7 @@ QCalendarBackend::~QCalendarBackend()
return the member of that enum that produces it. Other calendars should
return User.
- \sa QCalendar::fromEnum()
+ \sa QCalendarBackend::fromEnum()
*/
QCalendar::System QCalendarBackend::calendarSystem() const
{
@@ -200,7 +201,7 @@ QCalendar::System QCalendarBackend::calendarSystem() const
}
/*!
- The primary name of this calendar.
+ The primary name of this calendar.
*/
QString QCalendar::name() const
{
@@ -220,10 +221,10 @@ QString QCalendar::name() const
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.
+ 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()
+ \sa daysInYear(), monthsInYear(), minimumDaysInMonth(), maximumDaysInMonth()
*/
// properties of the calendar
@@ -295,7 +296,7 @@ int QCalendarBackend::daysInYear(int year) const
This base implementation returns 12 for any valid year.
- \sa daysInYear(), maxMonthsInYear(), isDateValid()
+ \sa daysInYear(), maximumMonthsInYear(), isDateValid()
*/
int QCalendarBackend::monthsInYear(int year) const
{
@@ -353,13 +354,14 @@ bool QCalendarBackend::hasYearZero() const
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.
+ the intercallary days in its count for an individual month,
+ maximumDaysInMonth() 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()
+ \sa maximumMonthsInYear(), daysInMonth()
*/
-int QCalendarBackend::maxDaysInMonth() const
+int QCalendarBackend::maximumDaysInMonth() const
{
return 31;
}
@@ -369,9 +371,9 @@ int QCalendarBackend::maxDaysInMonth() const
This base implementation returns 29, as this is a common case.
- \sa maxMonthsInYear(), daysInMonth()
+ \sa maximumMonthsInYear(), daysInMonth()
*/
-int QCalendarBackend::minDaysInMonth() const
+int QCalendarBackend::minimumDaysInMonth() const
{
return 29;
}
@@ -381,9 +383,9 @@ int QCalendarBackend::minDaysInMonth() const
This base implementation returns 12, as this is a common case.
- \sa maxDaysInMonth(), monthsInYear()
+ \sa maximumDaysInMonth(), monthsInYear()
*/
-int QCalendarBackend::maxMonthsInYear() const
+int QCalendarBackend::maximumMonthsInYear() const
{
return 12;
}
@@ -391,7 +393,7 @@ int QCalendarBackend::maxMonthsInYear() const
// Julian day number calculations
/*!
- \fn bool dateToJulianDay(int year, int month, int day, qint64 *jd) const
+ \fn bool QCalendarBackend::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
@@ -401,7 +403,7 @@ int QCalendarBackend::maxMonthsInYear() const
*/
/*!
- \fn QCalendar::YearMonthDay julianDayToDate(qint64 jd) const
+ \fn QCalendar::YearMonthDay QCalendarBackend::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
@@ -413,7 +415,7 @@ int QCalendarBackend::maxMonthsInYear() const
*/
/*!
- Returns the day of the week for a given Julian Day Number.
+ Returns the day of the week for the given Julian Day Number \a jd.
This is 1 for Monday through 7 for Sunday.
@@ -438,101 +440,104 @@ int QCalendarBackend::dayOfWeek(qint64 jd) const
// 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
+ \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.
+ 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.
+ 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().
+ \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()
+ \sa standaloneMonthName(), QLocale::monthName()
*/
/*!
- \fn QString QCalendarBackend::standaloneMonthName(const QLocale &locale, int month, int year
- QLocale::FormatType format) const
+ \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.
+ 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.
+ 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()
+ \sa monthName(), QLocale::standaloneMonthName()
*/
/*!
- \fn QString QCalendarBackend::weekDayName(const QLocale &locale, int day,
- QLocale::FormatType format) const
+ \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.
+ 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.
+ 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().
+ 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()
+ \sa dayOfWeek(), standaloneWeekDayName(), QLocale::dayName()
*/
/*!
- \fn QString QCalendarBackend::standaloneWeekDayName(const QLocale &locale, int day,
- QLocale::FormatType format) const
+ \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.
+ 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.
+ 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().
+ 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()
+ \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()
+ \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
@@ -541,7 +546,7 @@ int QCalendarBackend::dayOfWeek(qint64 jd) const
QCalendarBackend sub-class must be registered before being exposed to Date
and Time APIs.
- \sa registerCalendar(), fromName()
+ \sa registerAlias(), fromName()
*/
QStringList QCalendarBackend::availableCalendars()
{
@@ -569,16 +574,16 @@ bool QCalendarBackend::registerAlias(const QString &name)
}
/*!
- Returns a pointer to a named calendar backend.
+ 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.
+ 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()
+ \sa availableCalendars(), registerAlias(), fromEnum()
*/
const QCalendarBackend *QCalendarBackend::fromName(QStringView name)
{
@@ -590,7 +595,7 @@ const QCalendarBackend *QCalendarBackend::fromName(QStringView name)
}
/*!
- \overload
+ \overload
*/
const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
{
@@ -602,11 +607,11 @@ const QCalendarBackend *QCalendarBackend::fromName(QLatin1String name)
}
/*!
- Returns a pointer to a calendar backend, specified by enum.
+ 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.
+ 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)
{
@@ -641,28 +646,29 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
}
/*!
- \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.
+ \since 5.14
- 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.
+ \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.
+ A QCalendar value is immutable.
- \sa QCalendarBackend, QDate, QDateTime
+ \sa QDate, QDateTime
*/
/*!
@@ -675,25 +681,27 @@ const QCalendarBackend *QCalendarBackend::fromEnum(QCalendar::System system)
\value Milankovic A revised Julian calendar used by some Orthodox churches.
\value Jalali The Solar Hijri calendar (also called Persian).
\value IslamicCivil The (tabular) Islamic Civil calendar.
+ \omitvalue Last
+ \omitvalue User
\sa QCalendar
*/
/*!
- \fn QCalendar::QCalendar()
- \fn QCalendar::QCalendar(QCalendar::System system)
- \fn QCalendar::QCalendar(QLatin1String name)
- \fn QCalendar::QCalendar(QStringView name)
+ \fn QCalendar::QCalendar()
+ \fn QCalendar::QCalendar(QCalendar::System system)
+ \fn QCalendar::QCalendar(QLatin1String name)
+ \fn QCalendar::QCalendar(QStringView name)
- Constructs a calendar object.
+ 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.
+ 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
+ \sa QCalendar, System, isValid()
*/
QCalendar::QCalendar()
@@ -715,15 +723,25 @@ QCalendar::QCalendar(QLatin1String name)
QCalendar::QCalendar(QStringView name)
: d(QCalendarBackend::fromName(name)) {}
+/*
+ \fn bool QCalendar::isValid() const
+
+ Returns true if this is a valid calendar object.
+
+ Constructing a calendar with an unrecognised calendar name may result in an
+ invalid object. Use this method to check after creating a calendar by name.
+*/
+
// Date queries:
/*!
- Returns the number of days in the given \a month of the given \a year.
+ 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.
+ Months are numbered consecutively, starting with 1 for the first month of
+ each year. If \a year is \c Unspecified (its default, if not passed), the
+ month's length in a normal year is returned.
- \sa maxDaysInMonth(), minDaysInMonth()
+ \sa maximumDaysInMonth(), minimumDaysInMonth()
*/
int QCalendar::daysInMonth(int month, int year) const
{
@@ -731,7 +749,7 @@ int QCalendar::daysInMonth(int month, int year) const
}
/*!
- Returns the number of days in the given \a year.
+ Returns the number of days in the given \a year.
*/
int QCalendar::daysInYear(int year) const
{
@@ -747,12 +765,12 @@ int QCalendar::monthsInYear(int year) const
}
/*!
- Returns \c true precisely if the given \a year, \a month, and \a day specify a
- valid date in this calendar.
+ 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.
+ 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
{
@@ -772,13 +790,13 @@ bool QCalendar::isGregorian() const
}
/*!
- Returns \c true if the given year is a leap year.
+ Returns \c true if the given \a 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.
+ 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()
+ \sa isDateValid()
*/
bool QCalendar::isLeapYear(int year) const
{
@@ -786,9 +804,9 @@ bool QCalendar::isLeapYear(int year) const
}
/*!
- Returns \c true if this calendar is a lunar calendar.
+ Returns \c true if this calendar is a lunar calendar.
- A lunar calendar is one based primarily on the phases of the moon.
+ A lunar calendar is one based primarily on the phases of the moon.
*/
bool QCalendar::isLunar() const
{
@@ -796,11 +814,11 @@ bool QCalendar::isLunar() const
}
/*!
- Returns \c true if this calendar is luni-solar.
+ 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.
+ 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
{
@@ -808,10 +826,10 @@ bool QCalendar::isLuniSolar() const
}
/*!
- Returns \c true if this calendar is solar.
+ Returns \c true if this calendar is solar.
- A solar calendar is based primarily on the Sun's varying position in the sky,
- relative to the fixed stars.
+ A solar calendar is based primarily on the Sun's varying position in the
+ sky, relative to the fixed stars.
*/
bool QCalendar::isSolar() const
{
@@ -819,13 +837,13 @@ bool QCalendar::isSolar() const
}
/*!
- Returns \c true if this calendar is proleptic.
+ 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.
+ 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()
+ \sa hasYearZero()
*/
bool QCalendar::isProleptic() const
{
@@ -833,29 +851,29 @@ bool QCalendar::isProleptic() const
}
/*!
- 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()
+ Returns \c true if this calendar has a year zero.
+
+ A calendar may represent years from its first year onwards but provide 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 for this alternate numbering, 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
{
@@ -863,40 +881,40 @@ bool QCalendar::hasYearZero() const
}
/*!
- Returns the number of days in the longest month in the calendar, in any year.
+ Returns the number of days in the longest month in the calendar, in any year.
- \sa daysInMonth(), minDaysInMonth()
+ \sa daysInMonth(), minimumDaysInMonth()
*/
-int QCalendar::maxDaysInMonth() const
+int QCalendar::maximumDaysInMonth() const
{
- return d ? d->maxDaysInMonth() : 0;
+ return d ? d->maximumDaysInMonth() : 0;
}
/*!
- Returns the number of days in the shortest month in the calendar, in any year.
+ Returns the number of days in the shortest month in the calendar, in any year.
- \sa daysInMonth(), maxDaysInMonth()
+ \sa daysInMonth(), maximumDaysInMonth()
*/
-int QCalendar::minDaysInMonth() const
+int QCalendar::minimumDaysInMonth() const
{
- return d ? d->minDaysInMonth() : 0;
+ return d ? d->minimumDaysInMonth() : 0;
}
/*!
- Returns the largest number of months that any year may contain.
+ Returns the largest number of months that any year may contain.
- \sa monthName(), standaloneMonthName(), monthsInYear()
+ \sa monthName(), standaloneMonthName(), monthsInYear()
*/
-int QCalendar::maxMonthsInYear() const
+int QCalendar::maximumMonthsInYear() const
{
- return d ? d->maxMonthsInYear() : 0;
+ return d ? d->maximumMonthsInYear() : 0;
}
// Julian Day conversions:
/*!
\fn QDate QCalendar::dateFromParts(int year, int month, int day) const
- \fn QDate QCalendar::dateFromParts(QCalendar::YearMonthDay parts) const
+ \fn QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
Converts a year, month, and day to a QDate.
@@ -924,7 +942,7 @@ QDate QCalendar::dateFromParts(const QCalendar::YearMonthDay &parts) const
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
+ to represent the given \a date. Otherwise its year, month, and day
members record the so-named parts of its representation.
\sa dateFromParts(), isProleptic(), hasYearZero()
@@ -935,13 +953,13 @@ QCalendar::YearMonthDay QCalendar::partsFromDate(QDate date) const
}
/*!
- Returns the day of the week number for the given \a date.
+ 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.
+ 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
+ \sa partsFromDate(), Qt::DayOfWeek
*/
int QCalendar::dayOfWeek(QDate date) const
{
@@ -951,28 +969,28 @@ int QCalendar::dayOfWeek(QDate date) const
// Locale data access
/*!
- Returns a suitably localised name for a month.
+ 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 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 \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).
+ 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()
+ \sa standaloneMonthName(), maximumMonthsInYear(), dateTimeToString()
*/
QString QCalendar::monthName(const QLocale &locale, int month, int year,
QLocale::FormatType format) const
{
- const int maxMonth = year == Unspecified ? maxMonthsInYear() : monthsInYear(year);
+ const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
if (!d || month < 1 || month > maxMonth)
return QString();
@@ -980,28 +998,28 @@ QString QCalendar::monthName(const QLocale &locale, int month, int year,
}
/*!
- Returns a suitably localised standalone name for a month.
+ 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 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 \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).
+ 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()
+ \sa monthName(), maximumMonthsInYear(), dateTimeToString()
*/
QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int year,
QLocale::FormatType format) const
{
- const int maxMonth = year == Unspecified ? maxMonthsInYear() : monthsInYear(year);
+ const int maxMonth = year == Unspecified ? maximumMonthsInYear() : monthsInYear(year);
if (!d || month < 1 || month > maxMonth)
return QString();
@@ -1009,18 +1027,18 @@ QString QCalendar::standaloneMonthName(const QLocale &locale, int month, int yea
}
/*!
- Returns a suitably localised name for a day of the week.
+ 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 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).
+ 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()
+ \sa standaloneWeekDayName(), dayOfWeek()
*/
QString QCalendar::weekDayName(const QLocale &locale, int day,
QLocale::FormatType format) const
@@ -1029,19 +1047,20 @@ QString QCalendar::weekDayName(const QLocale &locale, int day,
}
/*!
- Returns a suitably localised standalone name for a day of the week.
+ 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 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).
+ 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()
+ \sa weekDayName(), dayOfWeek()
*/
QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
QLocale::FormatType format) const
@@ -1050,23 +1069,23 @@ QString QCalendar::standaloneWeekDayName(const QLocale &locale, int day,
}
/*!
- 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()
+ 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,
diff --git a/src/corelib/time/qcalendar.h b/src/corelib/time/qcalendar.h
index b117f4d6a9..42c8e150c5 100644
--- a/src/corelib/time/qcalendar.h
+++ b/src/corelib/time/qcalendar.h
@@ -128,7 +128,7 @@ public:
User = -1
};
// New entries must be added to the \enum doc in qcalendar.cpp and
- // handled in QCalendar::fromEnum()
+ // handled in QCalendarBackend::fromEnum()
Q_ENUM(System)
explicit QCalendar(); // Gregorian, optimised
@@ -137,7 +137,7 @@ public:
explicit QCalendar(QStringView name);
// QCalendar is a trivially copyable value type.
- bool isValid() { return d != nullptr; }
+ bool isValid() const { return d != nullptr; }
// Date queries:
int daysInMonth(int month, int year = Unspecified) const;
@@ -155,9 +155,9 @@ public:
bool isSolar() const;
bool isProleptic() const;
bool hasYearZero() const;
- int maxDaysInMonth() const;
- int minDaysInMonth() const;
- int maxMonthsInYear() const;
+ int maximumDaysInMonth() const;
+ int minimumDaysInMonth() const;
+ int maximumMonthsInYear() const;
QString name() const;
// QDate conversions:
diff --git a/src/corelib/time/qcalendarbackend_p.h b/src/corelib/time/qcalendarbackend_p.h
index 12db8928ca..21506e9e2c 100644
--- a/src/corelib/time/qcalendarbackend_p.h
+++ b/src/corelib/time/qcalendarbackend_p.h
@@ -95,9 +95,9 @@ public:
virtual bool isSolar() const = 0;
virtual bool isProleptic() const;
virtual bool hasYearZero() const;
- virtual int maxDaysInMonth() const;
- virtual int minDaysInMonth() const;
- virtual int maxMonthsInYear() const;
+ virtual int maximumDaysInMonth() const;
+ virtual int minimumDaysInMonth() const;
+ virtual int maximumMonthsInYear() const;
// Julian Day conversions:
virtual bool dateToJulianDay(int year, int month, int day, qint64 *jd) const = 0;
virtual QCalendar::YearMonthDay julianDayToDate(qint64 jd) const = 0;
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index a9fc47e053..95a7255a04 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -1465,7 +1465,7 @@ QDate QDate::addMonths(int nmonths, QCalendar cal) const
}
/*!
- \override
+ \overload
*/
QDate QDate::addMonths(int nmonths) const
@@ -1530,7 +1530,7 @@ QDate QDate::addYears(int nyears, QCalendar cal) const
}
/*!
- \override
+ \overload
*/
QDate QDate::addYears(int nyears) const
@@ -3432,15 +3432,15 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
datetime by adding a number of seconds, days, months, or years.
QDateTime can describe datetimes with respect to \l{Qt::LocalTime}{local
- time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset
- from UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction
- with the QTimeZone class. For example, a time zone of "Europe/Berlin" will
- apply the daylight-saving rules as used in Germany since 1970. In contrast,
- an offset from UTC of +3600 seconds is one hour ahead of UTC (usually
- written in ISO standard notation as "UTC+01:00"), with no daylight-saving
- offset or changes. When using either local time or a specified time zone,
- time-zone transitions such as the starts and ends of daylight-saving time
- (DST) are taken into account. The choice of system used to represent a
+ time}, to \l{Qt::UTC}{UTC}, to a specified \l{Qt::OffsetFromUTC}{offset from
+ UTC} or to a specified \l{Qt::TimeZone}{time zone}, in conjunction with the
+ QTimeZone class. For example, a time zone of "Europe/Berlin" will apply the
+ daylight-saving rules as used in Germany since 1970. In contrast, an offset
+ from UTC of +3600 seconds is one hour ahead of UTC (usually written in ISO
+ standard notation as "UTC+01:00"), with no daylight-saving offset or
+ changes. When using either local time or a specified time zone, time-zone
+ transitions such as the starts and ends of daylight-saving time (DST; but
+ see below) are taken into account. The choice of system used to represent a
datetime is described as its "timespec".
A QDateTime object is typically created either by giving a date and time
@@ -3528,11 +3528,13 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
The range of valid dates taking DST into account is 1970-01-01 to the
present, and rules are in place for handling DST correctly until 2037-12-31,
- but these could change. For dates falling outside that range, QDateTime
- makes a \e{best guess} using the rules for year 1970 or 2037, but we can't
- guarantee accuracy. This means QDateTime doesn't take into account changes
- in a time zone before 1970, even if the system's time zone database provides
- that information.
+ but these could change. For dates after 2037, QDateTime makes a \e{best
+ guess} using the rules for year 2037, but we can't guarantee accuracy;
+ indeed, for \e{any} future date, the time-zone may change its rules before
+ that date comes around. For dates before 1970, QDateTime doesn't take DST
+ changes into account, even if the system's time zone database provides that
+ information, although it does take into account changes to the time-zone's
+ standard offset, where this information is available.
\section2 Offsets From UTC
@@ -3546,6 +3548,7 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
*/
/*!
+ \since 5.14
\enum QDateTime::YearRange
This enumerated type describes the range of years (in the Gregorian
@@ -3797,17 +3800,22 @@ QTimeZone QDateTime::timeZone() const
/*!
\since 5.2
- Returns the current Offset From UTC in seconds.
+ Returns this date-time's Offset From UTC in seconds.
- If the timeSpec() is Qt::OffsetFromUTC this will be the value originally set.
-
- If the timeSpec() is Qt::TimeZone this will be the offset effective in the
- Time Zone including any Daylight-Saving Offset.
-
- If the timeSpec() is Qt::LocalTime this will be the difference between the
- Local Time and UTC including any Daylight-Saving Offset.
+ The result depends on timeSpec():
+ \list
+ \li \c Qt::UTC The offset is 0.
+ \li \c Qt::OffsetFromUTC The offset is the value originally set.
+ \li \c Qt::LocalTime The local time's offset from UTC is returned.
+ \li \c Qt::TimeZone The offset used by the time-zone is returned.
+ \endlist
- If the timeSpec() is Qt::UTC this will be 0.
+ For the last two, the offset at this date and time will be returned, taking
+ account of Daylight-Saving Offset unless the date precedes the start of
+ 1970. The offset is the difference between the local time or time in the
+ given time-zone and UTC time; it is positive in time-zones ahead of UTC
+ (East of The Prime Meridian), negative for those behind UTC (West of The
+ Prime Meridian).
\sa setOffsetFromUtc()
*/
@@ -3853,6 +3861,9 @@ int QDateTime::offsetFromUtc() const
QString QDateTime::timeZoneAbbreviation() const
{
+ if (!isValid())
+ return QString();
+
switch (getSpec(d)) {
case Qt::UTC:
return QLatin1String("UTC");
@@ -3887,6 +3898,9 @@ QString QDateTime::timeZoneAbbreviation() const
bool QDateTime::isDaylightTime() const
{
+ if (!isValid())
+ return false;
+
switch (getSpec(d)) {
case Qt::UTC:
case Qt::OffsetFromUTC:
@@ -4753,17 +4767,24 @@ QDateTime QDateTime::toTimeZone(const QTimeZone &timeZone) const
Returns \c true if this datetime is equal to the \a other datetime;
otherwise returns \c false.
+ Since 5.14, all invalid datetimes are equal to one another and differ from
+ all other datetimes.
+
\sa operator!=()
*/
bool QDateTime::operator==(const QDateTime &other) const
{
- if (getSpec(d) == Qt::LocalTime
- && getStatus(d) == getStatus(other.d)) {
+ if (!isValid())
+ return !other.isValid();
+ if (!other.isValid())
+ return false;
+
+ if (getSpec(d) == Qt::LocalTime && getStatus(d) == getStatus(other.d))
return getMSecs(d) == getMSecs(other.d);
- }
+
// Convert to UTC and compare
- return (toMSecsSinceEpoch() == other.toMSecsSinceEpoch());
+ return toMSecsSinceEpoch() == other.toMSecsSinceEpoch();
}
/*!
@@ -4772,8 +4793,9 @@ bool QDateTime::operator==(const QDateTime &other) const
Returns \c true if this datetime is different from the \a other
datetime; otherwise returns \c false.
- Two datetimes are different if either the date, the time, or the
- time zone components are different.
+ Two datetimes are different if either the date, the time, or the time zone
+ components are different. Since 5.14, any invalid datetime is less than all
+ valid datetimes.
\sa operator==()
*/
@@ -4785,12 +4807,16 @@ bool QDateTime::operator==(const QDateTime &other) const
bool QDateTime::operator<(const QDateTime &other) const
{
- if (getSpec(d) == Qt::LocalTime
- && getStatus(d) == getStatus(other.d)) {
+ if (!isValid())
+ return other.isValid();
+ if (!other.isValid())
+ return false;
+
+ if (getSpec(d) == Qt::LocalTime && getStatus(d) == getStatus(other.d))
return getMSecs(d) < getMSecs(other.d);
- }
+
// Convert to UTC and compare
- return (toMSecsSinceEpoch() < other.toMSecsSinceEpoch());
+ return toMSecsSinceEpoch() < other.toMSecsSinceEpoch();
}
/*!
@@ -5841,7 +5867,7 @@ uint qHash(const QDateTime &key, uint seed)
// QDate/QTime/spec/offset because QDateTime::operator== converts both arguments
// to the same timezone. If we don't, qHash would return different hashes for
// two QDateTimes that are equivalent once converted to the same timezone.
- return qHash(key.toMSecsSinceEpoch(), seed);
+ return key.isValid() ? qHash(key.toMSecsSinceEpoch(), seed) : seed;
}
/*! \fn uint qHash(const QDate &key, uint seed = 0)
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index d0f34358b9..2c566e3584 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -223,21 +223,23 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs;
#endif
case Hour24Section:
- case Hour12Section: return 23; // this is special-cased in
- // parseSection. We want it to be
- // 23 for the stepBy case.
+ case Hour12Section:
+ // This is special-cased in parseSection.
+ // We want it to be 23 for the stepBy case.
+ return 23;
case MinuteSection:
case SecondSection: return 59;
case MSecSection: return 999;
case YearSection2Digits:
- case YearSection: return 9999; // sectionMaxSize will prevent
- // people from typing in a larger
- // number in count == 2 sections.
- // stepBy() will work on real years anyway
- case MonthSection: return calendar.maxMonthsInYear();
+ case YearSection:
+ // sectionMaxSize will prevent people from typing in a larger number in
+ // count == 2 sections; stepBy() will work on real years anyway.
+ return 9999;
+ case MonthSection: return calendar.maximumMonthsInYear();
case DaySection:
case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: return cur.isValid() ? cur.date().daysInMonth(calendar) : calendar.maxDaysInMonth() ;
+ case DayOfWeekSectionLong:
+ return cur.isValid() ? cur.date().daysInMonth(calendar) : calendar.maximumDaysInMonth();
case AmPmSection: return 1;
default: break;
}
@@ -615,7 +617,7 @@ int QDateTimeParser::sectionSize(int sectionIndex) const
int QDateTimeParser::sectionMaxSize(Section s, int count) const
{
#if QT_CONFIG(textdate)
- int mcount = calendar.maxMonthsInYear();
+ int mcount = calendar.maximumMonthsInYear();
#endif
switch (s) {
@@ -1291,9 +1293,9 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
}
if (!calendar.isDateValid(year, month, day)) {
- if (day <= calendar.maxDaysInMonth())
+ if (day <= calendar.maximumDaysInMonth())
cachedDay = day;
- if (day > calendar.minDaysInMonth() && calendar.isDateValid(year, month, 1))
+ if (day > calendar.minimumDaysInMonth() && calendar.isDateValid(year, month, 1))
needfixday = true;
}
if (needfixday) {
diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp
index 447185d124..633b1ea94e 100644
--- a/src/corelib/time/qgregoriancalendar.cpp
+++ b/src/corelib/time/qgregoriancalendar.cpp
@@ -57,7 +57,7 @@ using namespace QRoundingDown;
The Gregorian calendar is a refinement of the earlier Julian calendar,
itself a late form of the Roman calendar. It is widely used.
- \sa QRomanCalendar, QJulianCalendar, QCalendarBackend, QCalendar
+ \sa QRomanCalendar, QJulianCalendar, QCalendar
*/
QGregorianCalendar::QGregorianCalendar()
diff --git a/src/corelib/time/qhijricalendar.cpp b/src/corelib/time/qhijricalendar.cpp
index 1a1155be6d..b5d89fbc5c 100644
--- a/src/corelib/time/qhijricalendar.cpp
+++ b/src/corelib/time/qhijricalendar.cpp
@@ -44,36 +44,37 @@
QT_BEGIN_NAMESPACE
/*!
- \since 5.14
+ \since 5.14
+ \internal
- \class QHijriCalendar
- \inmodule QtCore
- \brief The QHijriCalendar class supports Islamic (Hijri) calendar implementations.
+ \class QHijriCalendar
+ \inmodule QtCore
+ \brief The QHijriCalendar class supports Islamic (Hijri) calendar implementations.
- \section1 Islamic Calendar System
+ \section1 Islamic Calendar System
- The Islamic, Muslim, or Hijri calendar is a lunar calendar consisting of 12
- months in a year of 354 or 355 days. It is used (often alongside the
- Gregorian calendar) to date events in many Muslim countries. It is also used
- by Muslims to determine the proper days of Islamic holidays and rituals,
- such as the annual period of fasting and the proper time for the pilgrimage
- to Mecca.
+ The Islamic, Muslim, or Hijri calendar is a lunar calendar consisting of 12
+ months in a year of 354 or 355 days. It is used (often alongside the
+ Gregorian calendar) to date events in many Muslim countries. It is also used
+ by Muslims to determine the proper days of Islamic holidays and rituals,
+ such as the annual period of fasting and the proper time for the pilgrimage
+ to Mecca.
- Source: \l {https://en.wikipedia.org/wiki/Islamic_calendar}{Wikipedia page on
- Hijri Calendar}
+ Source: \l {https://en.wikipedia.org/wiki/Islamic_calendar}{Wikipedia page
+ on Hijri Calendar}
- \section1 Support for variants
+ \section1 Support for variants
- This base class provides the common details shared by all variants on the
- Islamic calendar. Each year comprises 12 months of 29 or 30 days each; most
- years have as many of 29 as of 30, but leap years extend one 29-day month to
- 30 days. In tabular versions of the calendar (where mathematical rules are
- used to determine the details), odd-numbered months have 30 days, as does the
- last (twelfth) month of a leap year; all other months have 29 days. Other
- versions are based on actual astronomical observations of the moon's phase at
- sunset, which vary from place to place.
+ This base class provides the common details shared by all variants on the
+ Islamic calendar. Each year comprises 12 months of 29 or 30 days each; most
+ years have as many of 29 as of 30, but leap years extend one 29-day month to
+ 30 days. In tabular versions of the calendar (where mathematical rules are
+ used to determine the details), odd-numbered months have 30 days, as does
+ the last (twelfth) month of a leap year; all other months have 29
+ days. Other versions are based on actual astronomical observations of the
+ moon's phase at sunset, which vary from place to place.
- \sa QIslamicCivilCalendar, QCalendar
+ \sa QIslamicCivilCalendar, QCalendar
*/
bool QHijriCalendar::isLunar() const
@@ -102,7 +103,7 @@ int QHijriCalendar::daysInMonth(int month, int year) const
return month % 2 == 0 ? 29 : 30;
}
-int QHijriCalendar::maxDaysInMonth() const
+int QHijriCalendar::maximumDaysInMonth() const
{
return 30;
}
diff --git a/src/corelib/time/qhijricalendar_p.h b/src/corelib/time/qhijricalendar_p.h
index 8f15495d11..60820488b4 100644
--- a/src/corelib/time/qhijricalendar_p.h
+++ b/src/corelib/time/qhijricalendar_p.h
@@ -63,7 +63,7 @@ class Q_CORE_EXPORT QHijriCalendar : public QCalendarBackend
{
public:
int daysInMonth(int month, int year = QCalendar::Unspecified) const override;
- int maxDaysInMonth() const override;
+ int maximumDaysInMonth() const override;
int daysInYear(int year) const override;
bool isLunar() const override;
diff --git a/src/corelib/time/qislamiccivilcalendar.cpp b/src/corelib/time/qislamiccivilcalendar.cpp
index 27c93f5c00..a6a2afd207 100644
--- a/src/corelib/time/qislamiccivilcalendar.cpp
+++ b/src/corelib/time/qislamiccivilcalendar.cpp
@@ -47,27 +47,29 @@ QT_BEGIN_NAMESPACE
using namespace QRoundingDown;
/*!
- \since 5.14
+ \since 5.14
+ \internal
- \class QIslamicCivilCalendar
- \inmodule QtCore
- \brief Implements a commonly-used computed version of the Islamic calendar.
+ \class QIslamicCivilCalendar
+ \inmodule QtCore
+ \brief Implements a commonly-used computed version of the Islamic calendar.
- \section1 Civil Islamic Calendar
+ \section1 Civil Islamic Calendar
- QIslamicCivilCalendar implements a tabular version of the Hijri calendar which
- is known as the Islamic Civil Calendar. It has the same numbering of years and
- months, but the months are determined by arithmetical rules rather than by
- observation or astronomical calculations.
+ QIslamicCivilCalendar implements a tabular version of the Hijri calendar
+ which is known as the Islamic Civil Calendar. It has the same numbering of
+ years and months, but the months are determined by arithmetical rules rather
+ than by observation or astronomical calculations.
- \section2 Calendar Organization
+ \section2 Calendar Organization
- The civil calendar follows the usual tabular scheme of odd-numbered months and
- the last month of each leap year being 30 days long, the rest being 29 days
- long. Its determination of leap years follows a 30-year cycle, in each of
- which the years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26 and 29 are leap years.
+ The civil calendar follows the usual tabular scheme of odd-numbered months
+ and the last month of each leap year being 30 days long, the rest being 29
+ days long. Its determination of leap years follows a 30-year cycle, in each
+ of which the years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26 and 29 are leap
+ years.
- \sa QJijriCalendar, QCalendar
+ \sa QHijriCalendar, QCalendar
*/
QIslamicCivilCalendar::QIslamicCivilCalendar()
diff --git a/src/corelib/time/qromancalendar.cpp b/src/corelib/time/qromancalendar.cpp
index 81b8d93d43..c3cd134490 100644
--- a/src/corelib/time/qromancalendar.cpp
+++ b/src/corelib/time/qromancalendar.cpp
@@ -44,20 +44,20 @@
QT_BEGIN_NAMESPACE
/*!
- \since 5.14
+ \since 5.14
- \class QRomanCalendar
- \inmodule QtCore
- \brief The QRomanCalendar class is a shared base for calendars based on the
- ancient Roman calendar.
+ \class QRomanCalendar
+ \inmodule QtCore
+ \brief The QRomanCalendar class is a shared base for calendars based on the
+ ancient Roman calendar.
- \section1
+ \section1
- Calendars based on the ancient Roman calendar share the names of months, whose
- lengths depend in a common way on whether the year is a leap year. They differ
- in how they determine which years are leap years.
+ Calendars based on the ancient Roman calendar share the names of months,
+ whose lengths depend in a common way on whether the year is a leap
+ year. They differ in how they determine which years are leap years.
- \sa QGregorianCalendar, QJulianCalendar, QMilankovicCalendar
+ \sa QGregorianCalendar, QJulianCalendar, QMilankovicCalendar
*/
int QRomanCalendar::daysInMonth(int month, int year) const
@@ -72,7 +72,7 @@ int QRomanCalendar::daysInMonth(int month, int year) const
return 30 | ((month & 1) ^ (month >> 3));
}
-int QRomanCalendar::minDaysInMonth() const
+int QRomanCalendar::minimumDaysInMonth() const
{
return 28;
}
diff --git a/src/corelib/time/qromancalendar_p.h b/src/corelib/time/qromancalendar_p.h
index ea2f9d01f0..49efb3df89 100644
--- a/src/corelib/time/qromancalendar_p.h
+++ b/src/corelib/time/qromancalendar_p.h
@@ -60,7 +60,7 @@ class Q_CORE_EXPORT QRomanCalendar : public QCalendarBackend
public:
// date queries:
int daysInMonth(int month, int year = QCalendar::Unspecified) const override;
- int minDaysInMonth() const override;
+ int minimumDaysInMonth() const override;
// properties of the calendar
bool isLunar() const override;
bool isLuniSolar() const override;
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index ef323de14a..410a16e3c5 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -325,20 +325,33 @@ QTimeZone::QTimeZone() noexcept
/*!
Creates an instance of the requested time zone \a ianaId.
- The ID must be one of the available system IDs otherwise an invalid
- time zone will be returned.
+ The ID must be one of the available system IDs or a valid UTC-with-offset
+ ID, otherwise an invalid time zone will be returned.
\sa availableTimeZoneIds()
*/
QTimeZone::QTimeZone(const QByteArray &ianaId)
{
- // Try and see if it's a valid UTC offset ID, just as quick to try create as look-up
+ // Try and see if it's a CLDR UTC offset ID - just as quick by creating as
+ // by looking up.
d = new QUtcTimeZonePrivate(ianaId);
- // If not a valid UTC offset ID then try create it with the system backend
- // Relies on backend not creating valid tz with invalid name
+ // If not a CLDR UTC offset ID then try creating it with the system backend.
+ // Relies on backend not creating valid TZ with invalid name.
if (!d->isValid())
d = newBackendTimeZone(ianaId);
+ // Can also handle UTC with arbitrary (valid) offset, but only do so as
+ // fall-back, since either of the above may handle it more informatively.
+ if (!d->isValid()) {
+ qint64 offset = QUtcTimeZonePrivate::offsetFromUtcString(ianaId);
+ if (offset != QTimeZonePrivate::invalidSeconds()) {
+ // Should have abs(offset) < 24 * 60 * 60 = 86400.
+ qint32 seconds = qint32(offset);
+ Q_ASSERT(qint64(seconds) == offset);
+ // NB: this canonicalises the name, so it might not match ianaId
+ d = new QUtcTimeZonePrivate(seconds);
+ }
+ }
}
/*!
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 569b343187..72a0e3c24e 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2013 John Layt <jlayt@kde.org>
** Contact: https://www.qt.io/licensing/
**
@@ -761,6 +762,39 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(const QByteArray &id)
}
}
+qint64 QUtcTimeZonePrivate::offsetFromUtcString(const QByteArray &id)
+{
+ // Convert reasonable UTC[+-]\d+(:\d+){,2} to offset in seconds.
+ // Assumption: id has already been tried as a CLDR UTC offset ID (notably
+ // including plain "UTC" itself) and a system offset ID; it's neither.
+ if (!id.startsWith("UTC") || id.size() < 5)
+ return invalidSeconds(); // Doesn't match
+ const char signChar = id.at(3);
+ if (signChar != '-' && signChar != '+')
+ return invalidSeconds(); // No sign
+ const int sign = signChar == '-' ? -1 : 1;
+
+ const auto offsets = id.mid(4).split(':');
+ if (offsets.isEmpty() || offsets.size() > 3)
+ return invalidSeconds(); // No numbers, or too many.
+
+ qint32 seconds = 0;
+ int prior = 0; // Number of fields parsed thus far
+ for (const auto &offset : offsets) {
+ bool ok = false;
+ unsigned short field = offset.toUShort(&ok);
+ // Bound hour above at 24, minutes and seconds at 60:
+ if (!ok || field >= (prior ? 60 : 24))
+ return invalidSeconds();
+ seconds = seconds * 60 + field;
+ ++prior;
+ }
+ while (prior++ < 3)
+ seconds *= 60;
+
+ return seconds * sign;
+}
+
// Create offset from UTC
QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
{
@@ -874,22 +908,25 @@ QByteArray QUtcTimeZonePrivate::systemTimeZoneId() const
bool QUtcTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{
+ // Only the zone IDs supplied by CLDR and recognized by constructor.
for (int i = 0; i < utcDataTableSize; ++i) {
const QUtcData *data = utcData(i);
- if (utcId(data) == ianaId) {
+ if (utcId(data) == ianaId)
return true;
- }
}
+ // But see offsetFromUtcString(), which lets us accept some "unavailable" IDs.
return false;
}
QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds() const
{
+ // Only the zone IDs supplied by CLDR and recognized by constructor.
QList<QByteArray> result;
result.reserve(utcDataTableSize);
for (int i = 0; i < utcDataTableSize; ++i)
result << utcId(utcData(i));
- std::sort(result.begin(), result.end()); // ### or already sorted??
+ // Not guaranteed to be sorted, so sort:
+ std::sort(result.begin(), result.end());
// ### assuming no duplicates
return result;
}
@@ -904,13 +941,16 @@ QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(QLocale::Country cou
QList<QByteArray> QUtcTimeZonePrivate::availableTimeZoneIds(qint32 offsetSeconds) const
{
+ // Only if it's present in CLDR. (May get more than one ID: UTC, UTC+00:00
+ // and UTC-00:00 all have the same offset.)
QList<QByteArray> result;
for (int i = 0; i < utcDataTableSize; ++i) {
const QUtcData *data = utcData(i);
if (data->offsetFromUtc == offsetSeconds)
result << utcId(data);
}
- std::sort(result.begin(), result.end()); // ### or already sorted??
+ // Not guaranteed to be sorted, so sort:
+ std::sort(result.begin(), result.end());
// ### assuming no duplicates
return result;
}
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 5f6491ef81..a57f61f381 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -188,6 +188,9 @@ public:
QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
virtual ~QUtcTimeZonePrivate();
+ // Fall-back for UTC[+-]\d+(:\d+){,2} IDs.
+ static qint64 offsetFromUtcString(const QByteArray &id);
+
QUtcTimeZonePrivate *clone() const override;
Data data(qint64 forMSecsSinceEpoch) const override;
diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
index 1bf2366748..5a480222e0 100644
--- a/src/corelib/time/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
@@ -371,6 +371,7 @@ QDate calculateTransitionLocalDate(const SYSTEMTIME &rule, int year)
// Otherwise, the rule date is annual and relative:
const int dayOfWeek = rule.wDayOfWeek == 0 ? 7 : rule.wDayOfWeek;
QDate date(year, rule.wMonth, 1);
+ Q_ASSERT(date.isValid());
// How many days before was last dayOfWeek before target month ?
int adjust = dayOfWeek - date.dayOfWeek(); // -6 <= adjust < 7
if (adjust >= 0) // Ensure -7 <= adjust < 0:
@@ -401,6 +402,7 @@ qint64 calculateTransitionForYear(const SYSTEMTIME &rule, int year, int bias)
{
// TODO Consider caching the calculated values - i.e. replace SYSTEMTIME in
// WinTransitionRule; do this in init() once and store the results.
+ Q_ASSERT(year);
const QDate date = calculateTransitionLocalDate(rule, year);
const QTime time = QTime(rule.wHour, rule.wMinute, rule.wSecond);
if (date.isValid() && time.isValid())
@@ -479,6 +481,7 @@ struct TransitionTimePair
int yearEndOffset(const QWinTimeZonePrivate::QWinTransitionRule &rule, int year)
{
+ Q_ASSERT(year);
int offset = rule.standardTimeBias;
// Only needed to help another TransitionTimePair work out year + 1's start
// offset; and the oldYearOffset we use only affects an alleged transition
@@ -743,11 +746,12 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
// Does this rule's period include any transition at all ?
if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
- const int endYear = qMax(rule.startYear, year - 1);
+ int prior = year == 1 ? -1 : year - 1; // No year 0.
+ const int endYear = qMax(rule.startYear, prior);
while (year >= endYear) {
const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
- ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
- : yearEndOffset(rule, year - 1);
+ ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
+ : yearEndOffset(rule, prior);
const TransitionTimePair pair(rule, year, newYearOffset);
bool isDst = false;
if (pair.std != invalidMSecs() && pair.std <= forMSecsSinceEpoch) {
@@ -755,7 +759,8 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
} else if (pair.dst != invalidMSecs() && pair.dst <= forMSecsSinceEpoch) {
isDst = true;
} else {
- --year; // Try an earlier year for this rule (once).
+ year = prior; // Try an earlier year for this rule (once).
+ prior = year == 1 ? -1 : year - 1; // No year 0.
continue;
}
return ruleToData(rule, forMSecsSinceEpoch,
@@ -767,8 +772,11 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::data(qint64 forMSecsSinceEpoch) cons
// No transition, no DST, use the year's standard time.
return ruleToData(rule, forMSecsSinceEpoch, QTimeZone::StandardTime);
}
- if (year >= rule.startYear)
+ if (year >= rule.startYear) {
year = rule.startYear - 1; // Seek last transition in new rule.
+ if (!year)
+ --year;
+ }
}
// We don't have relevant data :-(
return invalidData();
@@ -795,9 +803,10 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
year = rule.startYear; // Seek first transition in this rule.
const int endYear = ruleIndex + 1 < m_tranRules.count()
? qMin(m_tranRules.at(ruleIndex + 1).startYear, year + 2) : (year + 2);
+ int prior = year == 1 ? -1 : year - 1; // No year 0.
int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
- ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
- : yearEndOffset(rule, year - 1);
+ ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
+ : yearEndOffset(rule, prior);
while (year < endYear) {
const TransitionTimePair pair(rule, year, newYearOffset);
bool isDst = false;
@@ -810,7 +819,9 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
newYearOffset = rule.standardTimeBias;
if (pair.dst > pair.std)
newYearOffset += rule.daylightTimeBias;
- ++year; // Try a later year for this rule (once).
+ // Try a later year for this rule (once).
+ prior = year;
+ year = year == -1 ? 1 : year + 1; // No year 0
continue;
}
@@ -837,11 +848,12 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
const QWinTransitionRule &rule = m_tranRules.at(ruleIndex);
// Does this rule's period include any transition at all ?
if (rule.standardTimeRule.wMonth > 0 || rule.daylightTimeRule.wMonth > 0) {
- const int endYear = qMax(rule.startYear, year - 1);
+ int prior = year == 1 ? -1 : year - 1; // No year 0.
+ const int endYear = qMax(rule.startYear, prior);
while (year >= endYear) {
const int newYearOffset = (year <= rule.startYear && ruleIndex > 0)
- ? yearEndOffset(m_tranRules.at(ruleIndex - 1), year - 1)
- : yearEndOffset(rule, year - 1);
+ ? yearEndOffset(m_tranRules.at(ruleIndex - 1), prior)
+ : yearEndOffset(rule, prior);
const TransitionTimePair pair(rule, year, newYearOffset);
bool isDst = false;
if (pair.std != invalidMSecs() && pair.std < beforeMSecsSinceEpoch) {
@@ -849,7 +861,8 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
} else if (pair.dst != invalidMSecs() && pair.dst < beforeMSecsSinceEpoch) {
isDst = true;
} else {
- --year; // Try an earlier year for this rule (once).
+ year = prior; // Try an earlier year for this rule (once).
+ prior = year == 1 ? -1 : year - 1; // No year 0.
continue;
}
if (isDst)
@@ -863,8 +876,11 @@ QTimeZonePrivate::Data QWinTimeZonePrivate::previousTransition(qint64 beforeMSec
// rule:
return ruleToData(rule, startOfTime, QTimeZone::StandardTime, false);
} // else: no transition during rule's period
- if (year >= rule.startYear)
+ if (year >= rule.startYear) {
year = rule.startYear - 1; // Seek last transition in new rule
+ if (!year)
+ --year;
+ }
}
// Apparently no transition before the given time:
return invalidData();