Created
June 22, 2025 02:19
-
-
Save cho45/a20e8713bb57173a2617dd3bb5c4c7c7 to your computer and use it in GitHub Desktop.
システム時刻の調整が入ったことを検出する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ClockMonitor: システム時計の大幅な変更(NTP補正・手動変更等)を検知し、イベントを発行するクラス | |
// WebAudioやperformance.now()はmonotonicな経過時間だが、絶対時刻(Date.now())はシステム時計依存でジャンプすることがある | |
// そのため、performance.timeOrigin+performance.now()で絶対時刻を計算している場合、 | |
// システム時計が変化しても自動で補正されない(ズレたままになる) | |
// このクラスは、定期的にDate.now()とperformance.timeOrigin+performance.now()の差分を監視し、 | |
// 一定以上の差分が発生した場合に"clockchange"イベントを発行することで、 | |
// 利用側がoffset等を補正できるようにする | |
class ClockMonitor extends EventTarget { | |
constructor({ threshold = 2000, interval = 1000 } = {}) { | |
super(); | |
this.threshold = threshold; // 何ms以上の差分で検知するか | |
this.interval = interval; // 監視間隔(ms) | |
this.offset = performance.timeOrigin || 0; // performance.now()の起点(初期化時の絶対時刻) | |
this._timer = null; | |
} | |
start() { | |
if (this._timer) return; | |
this._timer = setInterval(() => { | |
const perfNow = performance.now(); | |
const now = Date.now(); | |
// 現在の絶対時刻の期待値(初期offset+経過時間) | |
const expected = this.offset + perfNow; | |
const diff = now - expected; | |
// threshold以上の差分が出たらシステム時計変更とみなす | |
if (Math.abs(diff) > this.threshold) { | |
// offsetを補正し、イベント発行 | |
this.offset += diff; | |
this.dispatchEvent(new CustomEvent("clockchange", { | |
detail: { offset: this.offset, diff } | |
})); | |
} | |
}, this.interval); | |
} | |
stop() { | |
if (this._timer) { | |
clearInterval(this._timer); | |
this._timer = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment