From ea31d346494790eeb596f90e590ae96644b980c5 Mon Sep 17 00:00:00 2001 From: ZoneMR Date: Tue, 30 Jun 2020 19:51:25 +0100 Subject: [PATCH] Fix #2030 - Clock can be off by a minute Set minute/second in our model based on the actual time from moment() rather than our own attempt to track the time - which can drift or fail to respond to time changes. Also, schedule time refreshes to happen 50ms after the minute/second is expected to change - preventing premature fires and rapid re-firings of notifications due to accuracy limits in setTimeout --- modules/default/clock/clock.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 08dcced0..293ff93b 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -51,10 +51,12 @@ Module.register("clock",{ //Calculate how many ms should pass until next update depending on if seconds is displayed or not var delayCalculator = function(reducedSeconds) { + var EXTRA_DELAY = 50; //Deliberate imperceptable delay to prevent off-by-one timekeeping errors + if (self.config.displaySeconds) { - return 1000 - moment().milliseconds(); + return 1000 - moment().milliseconds() + EXTRA_DELAY; } else { - return ((60 - reducedSeconds) * 1000) - moment().milliseconds(); + return ((60 - reducedSeconds) * 1000) - moment().milliseconds() + EXTRA_DELAY; } }; @@ -64,7 +66,7 @@ Module.register("clock",{ //If seconds is displayed CLOCK_SECOND-notification should be sent (but not when CLOCK_MINUTE-notification is sent) if (self.config.displaySeconds) { - self.second = (self.second + 1) % 60; + self.second = moment().second(); if (self.second !== 0) { self.sendNotification("CLOCK_SECOND", self.second); setTimeout(notificationTimer, delayCalculator(0)); @@ -73,7 +75,7 @@ Module.register("clock",{ } //If minute changed or seconds isn't displayed send CLOCK_MINUTE-notification - self.minute = (self.minute + 1) % 60; + self.minute = moment().minute(); self.sendNotification("CLOCK_MINUTE", self.minute); setTimeout(notificationTimer, delayCalculator(0)); };