为何带倍率加速的JavaScript时钟无法从2104年正确启动?
问题分析与解决方案
核心问题
- 起始日期设置错误:
new Date(2104, 0, 0)中的日期参数为0时,JavaScript会返回上月最后一天,也就是2103年12月31日,并非你期望的2104年1月1日。 - 时间差逻辑完全颠倒:当前真实时间(2025年前后)早于2104年,
_now - yr2104.getTime()得到的是负数,乘以52.1429后再加到2104年的时间上,会让游戏时间直接倒退到2104年之前,完全不符合“从2104年启动加速时钟”的需求。
正确实现思路
应该记录游戏时钟启动瞬间的真实时间点,每次更新时计算从启动到现在流逝的真实毫秒数,将这个时长乘以加速倍数后,加到2104年的起始时间上。这样就能保证游戏时间从2104年开始,按设定倍数加速推进。
修正后的代码
var clock = {}; // 正确设置2104年1月1日0点0分0秒(月份为0-based,0代表1月) var gameStartTime = new Date(2104, 0, 1, 0, 0, 0, 0); // 记录游戏时钟启动时的真实时间戳 var realStartTimestamp = Date.now(); var week = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']; var timerID = setInterval(updateTime, 10); updateTime(); function updateTime() { // 计算从时钟启动到现在流逝的真实毫秒数 var elapsedRealMs = Date.now() - realStartTimestamp; // 游戏时间加速倍数:原代码的52.1429,可根据需求调整 var speedMultiplier = 52.1429; // 计算当前游戏时间:起始时间 + 真实流逝时间 × 加速倍数 var currentGameTime = new Date(gameStartTime.getTime() + elapsedRealMs * speedMultiplier); // 修复原代码中秒数格式化的错误,改为标准时分秒.毫秒格式 clock.time = zeroPadding(currentGameTime.getHours(), 2) + ':' + zeroPadding(currentGameTime.getMinutes(), 2) + ':' + zeroPadding(currentGameTime.getSeconds(), 2) + '.' + zeroPadding(currentGameTime.getMilliseconds(), 3); // 格式化日期 clock.date = zeroPadding(currentGameTime.getFullYear(), 4) + '-' + zeroPadding(currentGameTime.getMonth() + 1, 2) + '-' + zeroPadding(currentGameTime.getDate(), 2) + ' ' + week[currentGameTime.getDay()]; console.log(clock); }; function zeroPadding(num, digit) { var zero = ''; for (var i = 0; i < digit; i++) { zero += '0'; } return (zero + num).slice(-digit); }
额外说明
- 原代码中
zeroPadding(cd.getSeconds() + "s", 3)是错误写法,会导致字符串与数字拼接后再补零,修正为单独处理秒和毫秒,更符合时间格式规范。 - 如果你的52.1429是想实现“真实1天对应游戏1年”,可以调整加速倍数为365(1年≈31536000000毫秒,1天≈86400000毫秒,31536000000/86400000=365),根据实际需求灵活修改即可。
内容的提问来源于stack exchange,提问作者IIcloudBob
相关产品推荐
相关产品推荐

