summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-04-03 03:18:32 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2022-04-13 18:08:38 +0200
commit2e29f55f76e49c1fbffd2af51ec19d59b87f0e72 (patch)
tree75ba1d4be18c72f5742ce84038f63ffe2d61c909 /src
parent33c88f86b5b8714977719a8ccff0f7c15c9cbd44 (diff)
QDate: add conversions for std::chrono calendaring classes
std::chrono::year_month_day and related classes offer very convenient to specify dates. This patch adds implicit constructors to QDate to support this convenience, e.g.: // YYYY-MM-DD, DD-MM-YYYY, MM-DD-YYYY formats: QDate d1 = 1985y / December / 8; QDate d2 = 8d / December / 1985; QDate d3 = December / 8d / 1985; // Indexed weekday: QDate d4 = 2000y / January / Monday[0]; QDate d5 = 2000y / January / Monday[last]; and so on. These are all implemented using the conversion from the std calendaring classes to sys_days. Conversions between sys_days and QDate are also added, since they're basically "for free". I don't expect "ordinary" users to stumble upon it, but it's worthy mentioning that std::chrono::year *does* have a year zero (hence, year_month_day in year 0 or below are offset by one with the corresponding QDate). I've left a note in the documentation. [ChangeLog][QtCore][QDate] QDate (and therefore QDateTime) is now constructible using the year/month/day/week classes available in the std::chrono library. Moreover, it now features conversions from and to std::chrono::sys_days. Change-Id: I2a4f56423ac7d1469541cbb6a278a65b48878b4a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp20
-rw-r--r--src/corelib/time/qdatetime.cpp48
-rw-r--r--src/corelib/time/qdatetime.h52
3 files changed, 120 insertions, 0 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp b/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
index a477e91548..265f46c067 100644
--- a/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_time_qdatetime.cpp
@@ -216,3 +216,23 @@ QString string = "Tuesday, 23 April 12 22:51:41";
QString format = "dddd, d MMMM yy hh:mm:ss";
QDateTime valid = QDateTime::fromString(string, format);
//! [21]
+
+//! [22]
+// 23 April 2012:
+QDate date = std::chrono::year_month_day(std::chrono::year(2012),
+ std::chrono::month(4),
+ std::chrono::day(23));
+
+// Same, under `using std::chrono` convenience:
+QDate dateWithLiterals1 = 23 / April / 2012y;
+QDate dateWithLiterals2 = 2012y / April / 23;
+
+// Last day of February 2000
+QDate lastDayFeb2020 = 2000y / February / last;
+
+// First Monday of January 2020:
+QDate firstMonday = 2020y / January / Monday[0];
+
+// Last Monday of January 2020:
+QDate lastMonday = 2020y / January / Monday[last];
+//! [22]
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index cea5623acf..09477612e4 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -449,6 +449,54 @@ QDate::QDate(int y, int m, int d, QCalendar cal)
}
/*!
+ \fn QDate::QDate(std::chrono::year_month_day ymd)
+ \fn QDate::QDate(std::chrono::year_month_day_last ymd)
+ \fn QDate::QDate(std::chrono::year_month_weekday ymd)
+ \fn QDate::QDate(std::chrono::year_month_weekday_last ymd)
+
+ \since 6.4
+
+ Constructs a QDate representing the same date as \a ymd. This allows for
+ easy interoperability between the Standard Library calendaring classes and
+ Qt datetime classes.
+
+ For example:
+
+ \snippet code/src_corelib_time_qdatetime.cpp 22
+
+ \note Unlike QDate, std::chrono::year and the related classes feature the
+ year zero. This means that if \a ymd is in the year zero or before, the
+ resulting QDate object will have an year one less than the one specified by
+ \a ymd.
+
+ \note This function requires C++20.
+*/
+
+/*!
+ \fn QDate QDate::fromStdSysDays(const std::chrono::sys_days &days)
+ \since 6.4
+
+ Returns a QDate \a days days after January 1st, 1970 (the UNIX epoch). If
+ \a days is negative, the returned date will be before the epoch.
+
+ \note This function requires C++20.
+
+ \sa toStdSysDays()
+*/
+
+/*!
+ \fn std::chrono::sys_days QDate::toStdSysDays() const
+
+ Returns the number of days between January 1st, 1970 (the UNIX epoch) and
+ this date, represented as a \c{std::chrono::sys_days} object. If this date
+ is before the epoch, the number of days will be negative.
+
+ \note This function requires C++20.
+
+ \sa fromStdSysDays(), daysTo()
+*/
+
+/*!
\fn bool QDate::isNull() const
Returns \c true if the date is null; otherwise returns \c false. A null
diff --git a/src/corelib/time/qdatetime.h b/src/corelib/time/qdatetime.h
index 839d0c2f28..f264a1e234 100644
--- a/src/corelib/time/qdatetime.h
+++ b/src/corelib/time/qdatetime.h
@@ -68,6 +68,57 @@ public:
constexpr QDate() : jd(nullJd()) {}
QDate(int y, int m, int d);
QDate(int y, int m, int d, QCalendar cal);
+#if __cpp_lib_chrono >= 201907L || defined(Q_QDOC)
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT QDate(std::chrono::year_month_day ymd)
+ {
+ if (!ymd.ok())
+ jd = nullJd();
+ else
+ *this = fromStdSysDays(ymd);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT QDate(std::chrono::year_month_day_last ymdl)
+ {
+ if (!ymdl.ok())
+ jd = nullJd();
+ else
+ *this = fromStdSysDays(ymdl);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT QDate(std::chrono::year_month_weekday ymw)
+ {
+ if (!ymw.ok())
+ jd = nullJd();
+ else
+ *this = fromStdSysDays(ymw);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ Q_IMPLICIT QDate(std::chrono::year_month_weekday_last ymwl)
+ {
+ if (!ymwl.ok())
+ jd = nullJd();
+ else
+ *this = fromStdSysDays(ymwl);
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ static QDate fromStdSysDays(const std::chrono::sys_days &days)
+ {
+ const QDate epoch(unixEpochJd());
+ return epoch.addDays(days.time_since_epoch().count());
+ }
+
+ QT_POST_CXX17_API_IN_EXPORTED_CLASS
+ std::chrono::sys_days toStdSysDays() const
+ {
+ const QDate epoch(unixEpochJd());
+ return std::chrono::sys_days(std::chrono::days(epoch.daysTo(*this)));
+ }
+#endif
constexpr bool isNull() const { return !isValid(); }
constexpr bool isValid() const { return jd >= minJd() && jd <= maxJd(); }
@@ -144,6 +195,7 @@ private:
static constexpr inline qint64 nullJd() { return (std::numeric_limits<qint64>::min)(); }
static constexpr inline qint64 minJd() { return Q_INT64_C(-784350574879); }
static constexpr inline qint64 maxJd() { return Q_INT64_C( 784354017364); }
+ static constexpr inline qint64 unixEpochJd() { return Q_INT64_C(2440588); }
qint64 jd;