core/clock: fix behavior with odd time changes

This commit is contained in:
outfoxxed 2024-08-16 02:32:46 -07:00
parent 815867c178
commit 1d2bf5d7b4
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
2 changed files with 29 additions and 25 deletions

View file

@ -31,20 +31,25 @@ void SystemClock::setPrecision(SystemClock::Enum precision) {
} }
void SystemClock::onTimeout() { void SystemClock::onTimeout() {
this->setTime(this->nextTime); this->setTime(this->targetTime);
this->schedule(this->nextTime); this->schedule(this->targetTime);
} }
void SystemClock::update() { void SystemClock::update() {
if (this->mEnabled) { if (this->mEnabled) {
this->setTime(QTime::currentTime()); this->setTime(QDateTime::fromMSecsSinceEpoch(0));
this->schedule(QTime::currentTime()); this->schedule(QDateTime::fromMSecsSinceEpoch(0));
} else { } else {
this->timer.stop(); this->timer.stop();
} }
} }
void SystemClock::setTime(QTime time) { void SystemClock::setTime(const QDateTime& targetTime) {
auto currentTime = QDateTime::currentDateTime();
auto offset = currentTime.msecsTo(targetTime);
auto dtime = offset > -500 && offset < 500 ? targetTime : currentTime;
auto time = dtime.time();
auto secondPrecision = this->mPrecision >= SystemClock::Seconds; auto secondPrecision = this->mPrecision >= SystemClock::Seconds;
auto secondChanged = this->setSeconds(secondPrecision ? time.second() : 0); auto secondChanged = this->setSeconds(secondPrecision ? time.second() : 0);
@ -57,34 +62,33 @@ void SystemClock::setTime(QTime time) {
DropEmitter::call(secondChanged, minuteChanged, hourChanged); DropEmitter::call(secondChanged, minuteChanged, hourChanged);
} }
void SystemClock::schedule(QTime floor) { void SystemClock::schedule(const QDateTime& targetTime) {
auto secondPrecision = this->mPrecision >= SystemClock::Seconds; auto secondPrecision = this->mPrecision >= SystemClock::Seconds;
auto minutePrecision = this->mPrecision >= SystemClock::Minutes; auto minutePrecision = this->mPrecision >= SystemClock::Minutes;
auto hourPrecision = this->mPrecision >= SystemClock::Hours; auto hourPrecision = this->mPrecision >= SystemClock::Hours;
setnext: auto currentTime = QDateTime::currentDateTime();
auto nextTime = QTime(
hourPrecision ? floor.hour() : 0, auto offset = currentTime.msecsTo(targetTime);
minutePrecision ? floor.minute() : 0,
secondPrecision ? floor.second() : 0 // timer skew
auto nextTime = offset > 0 && offset < 500 ? targetTime : currentTime;
auto baseTimeT = nextTime.time();
nextTime.setTime(
{hourPrecision ? baseTimeT.hour() : 0,
minutePrecision ? baseTimeT.minute() : 0,
secondPrecision ? baseTimeT.second() : 0}
); );
if (secondPrecision) nextTime = nextTime.addSecs(1); if (secondPrecision) nextTime = nextTime.addSecs(1);
else if (minutePrecision) nextTime = nextTime.addSecs(60); else if (minutePrecision) nextTime = nextTime.addSecs(60);
else if (hourPrecision) nextTime = nextTime.addSecs(3600); else if (hourPrecision) nextTime = nextTime.addSecs(3600);
auto delay = QTime::currentTime().msecsTo(nextTime); auto delay = currentTime.msecsTo(nextTime);
// If off by more than 2 hours we likely wrapped around midnight. this->timer.start(static_cast<qint32>(delay));
if (delay < -7200000) delay += 86400000; this->targetTime = nextTime;
else if (delay < 0) {
// Otherwise its just the timer being unstable.
floor = QTime::currentTime();
goto setnext;
}
this->timer.start(delay);
this->nextTime = nextTime;
} }
DEFINE_MEMBER_GETSET(SystemClock, hours, setHours); DEFINE_MEMBER_GETSET(SystemClock, hours, setHours);

View file

@ -59,11 +59,11 @@ private:
quint32 mMinutes = 0; quint32 mMinutes = 0;
quint32 mSeconds = 0; quint32 mSeconds = 0;
QTimer timer; QTimer timer;
QTime nextTime; QDateTime targetTime;
void update(); void update();
void setTime(QTime time); void setTime(const QDateTime& targetTime);
void schedule(QTime floor); void schedule(const QDateTime& targetTime);
DECLARE_PRIVATE_MEMBER(SystemClock, hours, setHours, mHours, hoursChanged); DECLARE_PRIVATE_MEMBER(SystemClock, hours, setHours, mHours, hoursChanged);
DECLARE_PRIVATE_MEMBER(SystemClock, minutes, setMinutes, mMinutes, minutesChanged); DECLARE_PRIVATE_MEMBER(SystemClock, minutes, setMinutes, mMinutes, minutesChanged);