diff options
| author | Edward Welbourne <edward.welbourne@qt.io> | 2023-09-26 14:38:16 +0200 |
|---|---|---|
| committer | Edward Welbourne <edward.welbourne@qt.io> | 2023-09-28 14:51:33 +0200 |
| commit | 02d8dc5f8c346e7ce0656511c75c3d7c70538536 (patch) | |
| tree | 96490bddbc78983a9b9113e05403dfbed4ff022c /src/corelib/time/qlocaltime.cpp | |
| parent | 44cbd4c31520017188257bff14f3f1820d8fdf8c (diff) | |
Rework getting normalized dates adjacent to a given one
I originally wrote dateNormalize() because I expected to need it more,
but it turns out to only be needed for two cases of getting the days
before and after a given one. So rename to adjacentDay(), pass the +1
or -1 step and simplify a little.
In the process, fix a mistake in the winding backwards across a year
boundary, where I'd incremented the year instead of decrementing it.
Change-Id: I1bb0a8323fec7c1caffa7f20879f08d3526ba7ea
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/time/qlocaltime.cpp')
| -rw-r--r-- | src/corelib/time/qlocaltime.cpp | 57 |
1 files changed, 29 insertions, 28 deletions
diff --git a/src/corelib/time/qlocaltime.cpp b/src/corelib/time/qlocaltime.cpp index a5cb75ab896..3e134fd1802 100644 --- a/src/corelib/time/qlocaltime.cpp +++ b/src/corelib/time/qlocaltime.cpp @@ -195,36 +195,41 @@ struct tm matchYearMonth(struct tm when, const struct tm &base) } Q_DECL_COLD_FUNCTION -struct tm dateNormalize(struct tm when) +struct tm adjacentDay(struct tm when, int dayStep) { - int daysInMonth = 28; - // We have to wind through months one at a time, since their lengths vary. - while (when.tm_mday < 1) { - // Month before's day-count; but tm_mon's value is one less than Qt's - // month numbering so, before we decrement it, it has the value we need, - // unless it's 0. - daysInMonth = when.tm_mon - ? QGregorianCalendar::monthLength(when.tm_mon, qYearFromTmYear(when.tm_year)) - : QGregorianCalendar::monthLength(12, qYearFromTmYear(when.tm_year - 1)); - when.tm_mday += daysInMonth; - if (--when.tm_mon < 0) { - ++when.tm_year; - when.tm_mon = 11; + // Before we adjust it, when is a return from timeToTm(), so in normal form. + Q_ASSERT(dayStep * dayStep == 1); + when.tm_mday += dayStep; + // That may have bumped us across a month boundary or even a year one. + // So now we normalize it. + + if (dayStep < 0) { + if (when.tm_mday <= 0) { + // Month before's day-count; but tm_mon's value is one less than Qt's + // month numbering so, before we decrement it, it has the value we need, + // unless it's 0. + int daysInMonth = when.tm_mon + ? QGregorianCalendar::monthLength(when.tm_mon, qYearFromTmYear(when.tm_year)) + : QGregorianCalendar::monthLength(12, qYearFromTmYear(when.tm_year - 1)); + when.tm_mday += daysInMonth; + if (--when.tm_mon < 0) { + --when.tm_year; + when.tm_mon = 11; + } + Q_ASSERT(when.tm_mday >= 1); } - } - // If we came via that loop, we have set daysInMonth and when.tm_mday is <= it. - // Otherwise, daysInMonth is 28, so this serves as a cheap pre-test: - if (when.tm_mday > daysInMonth) { - daysInMonth = QGregorianCalendar::monthLength( + } else if (when.tm_mday > 28) { + // We have to wind through months one at a time, since their lengths vary. + int daysInMonth = QGregorianCalendar::monthLength( when.tm_mon + 1, qYearFromTmYear(when.tm_year)); - while (when.tm_mday > daysInMonth) { + if (when.tm_mday > daysInMonth) { when.tm_mday -= daysInMonth; if (++when.tm_mon > 11) { ++when.tm_year; when.tm_mon = 0; } - daysInMonth = QGregorianCalendar::monthLength( - when.tm_mon + 1, qYearFromTmYear(when.tm_year)); + Q_ASSERT(when.tm_mday <= QGregorianCalendar::monthLength( + when.tm_mon + 1, qYearFromTmYear(when.tm_year))); } } return when; @@ -278,12 +283,8 @@ MkTimeResult resolveRejected(struct tm base, MkTimeResult result, constexpr time_t twoDaysInSeconds = 2 * 24 * 60 * 60; // Bracket base, one day each side (in case the zone skipped a whole day): - struct tm adjust = base; - --adjust.tm_mday; - MkTimeResult early(dateNormalize(adjust)); - adjust = base; - ++adjust.tm_mday; - MkTimeResult later(dateNormalize(adjust)); + MkTimeResult early(adjacentDay(base, -1)); + MkTimeResult later(adjacentDay(base, +1)); if (!early.good || !later.good) // Assume out of range, rather than gap. return {}; |
