QDate: enable {start,end}OfDay() to make second-adjustments
Previously it only got the answer correct to the minute. That's good enough for most transitions, but those involving local solar mean time (LMT) may have second deviations. So check the second before or after, that'll usually be the other side of the transition; if it isn't, do a further binary chop on seconds to hit the correct value. Most zones' canonical locations are only specified to the size of a city, so second precision is all anyone cares about; a few hundred metres difference in location would change that. The one exception is Europe/Amsterdam, which had its own Royal Observatory and time standard, hence had an offset known to greater precision; but the IANA DB duly approximates that, too, so we won't have data with millisecond precision even in that case, so don't try to refine beyond second. Change-Id: I20fb355f8113c32387ed8a84fbf5a41004273978 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
This commit is contained in:
parent
b906796af6
commit
76075aa3a9
@ -864,8 +864,8 @@ static QDateTime toEarliest(QDate day, const QTimeZone &zone)
|
||||
int low = 0;
|
||||
// Binary chop to the right minute
|
||||
while (high > low + 1) {
|
||||
int mid = (high + low) / 2;
|
||||
QDateTime probe = moment(QTime(mid / 60, mid % 60));
|
||||
const int mid = (high + low) / 2;
|
||||
const QDateTime probe = moment(QTime(mid / 60, mid % 60));
|
||||
if (probe.isValid() && probe.date() == day) {
|
||||
high = mid;
|
||||
when = probe;
|
||||
@ -873,6 +873,24 @@ static QDateTime toEarliest(QDate day, const QTimeZone &zone)
|
||||
low = mid;
|
||||
}
|
||||
}
|
||||
// Transitions out of local solar mean time, and the few international
|
||||
// date-line crossings before that (Alaska, Philippines), may have happened
|
||||
// between minute boundaries. Don't try to fix milliseconds.
|
||||
if (QDateTime p = moment(when.time().addSecs(-1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
|
||||
high *= 60;
|
||||
low *= 60;
|
||||
while (high > low + 1) {
|
||||
const int mid = (high + low) / 2;
|
||||
const int min = mid / 60;
|
||||
const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60));
|
||||
if (probe.isValid() && probe.date() == day) {
|
||||
high = mid;
|
||||
when = probe;
|
||||
} else {
|
||||
low = mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return when.isValid() ? when : QDateTime();
|
||||
}
|
||||
|
||||
@ -910,7 +928,7 @@ QDateTime QDate::startOfDay(const QTimeZone &zone) const
|
||||
return QDateTime();
|
||||
|
||||
QDateTime when(*this, QTime(0, 0), zone);
|
||||
if (when.isValid())
|
||||
if (Q_LIKELY(when.isValid()))
|
||||
return when;
|
||||
|
||||
#if QT_CONFIG(timezone)
|
||||
@ -995,8 +1013,8 @@ static QDateTime toLatest(QDate day, const QTimeZone &zone)
|
||||
int low = when.time().msecsSinceStartOfDay() / 60000;
|
||||
// Binary chop to the right minute
|
||||
while (high > low + 1) {
|
||||
int mid = (high + low) / 2;
|
||||
QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
|
||||
const int mid = (high + low) / 2;
|
||||
const QDateTime probe = moment(QTime(mid / 60, mid % 60, 59, 999));
|
||||
if (probe.isValid() && probe.date() == day) {
|
||||
low = mid;
|
||||
when = probe;
|
||||
@ -1004,6 +1022,24 @@ static QDateTime toLatest(QDate day, const QTimeZone &zone)
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
// Transitions out of local solar mean time, and the few international
|
||||
// date-line crossings before that (Alaska, Philippines), may have happened
|
||||
// between minute boundaries. Don't try to fix milliseconds.
|
||||
if (QDateTime p = moment(when.time().addSecs(1)); Q_UNLIKELY(p.isValid() && p.date() == day)) {
|
||||
high *= 60;
|
||||
low *= 60;
|
||||
while (high > low + 1) {
|
||||
const int mid = (high + low) / 2;
|
||||
const int min = mid / 60;
|
||||
const QDateTime probe = moment(QTime(min / 60, min % 60, mid % 60, 999));
|
||||
if (probe.isValid() && probe.date() == day) {
|
||||
low = mid;
|
||||
when = probe;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return when.isValid() ? when : QDateTime();
|
||||
}
|
||||
|
||||
@ -1042,7 +1078,7 @@ QDateTime QDate::endOfDay(const QTimeZone &zone) const
|
||||
return QDateTime();
|
||||
|
||||
QDateTime when(*this, QTime(23, 59, 59, 999), zone);
|
||||
if (when.isValid())
|
||||
if (Q_LIKELY(when.isValid()))
|
||||
return when;
|
||||
|
||||
#if QT_CONFIG(timezone)
|
||||
|
Loading…
Reference in New Issue
Block a user