前端营业时间判断代码Bug排查:CES时区16:00-16:10误显闭店状态
问题排查:中欧夏令时16:00-16:10期间错误显示闭店状态
问题描述
这段代码整体运行正常,但存在一个Bug:在中欧夏令时(CES)时区的每日16:00至16:10期间,无论当日是否为工作日,都会固定显示闭店文本(most nem érhető el.)。仅在此时间段发现该问题。
原代码
var a = document.getElementById("online"); var d = new Date(); var n = d.getDay(); var now = d.getHours() + "." + d.getMinutes(); var onlineweekdays = { 0: null, //Vasárnap 1: [6.30, 16.30], //hétfő 2: [6.30, 16.30], //kedd 3: [6.30, 16.30], //szerda 4: [6.30, 16.30], //csütörtök 5: [6.30, 15.30], //péntek 6: null //Szombat }; var onlinedayWorkingHours = onlineweekdays[n]; //Today working hours. if null we are close if (onlinedayWorkingHours && (now > onlinedayWorkingHours[0] && now < onlinedayWorkingHours[1])) { // check if current time is during or beyond 15 minutes before closing time if (isFifteenMinBeforeOut2(now, onlinedayWorkingHours[1])) { a.innerHTML = "rövidesen zárunk."; a.style.backgroundColor = '#fee599'; a.style.color = '#7f6000'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; } else { a.innerHTML = "most elérhető."; a.style.backgroundColor = '#e2efd9'; a.style.color = '#538135'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; } } else { a.innerHTML = "most nem érhető el."; a.style.backgroundColor = '#efd9df'; a.style.color = '#c91f41'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; } function isFifteenMinBeforeOut2(current, clockout) { return current >= clockout - 0.10; }
核心问题分析
1. 时间格式逻辑完全错误
代码将时间拼接为小时.分钟的字符串(如16:10写成"16.10"),并直接与6.30这类数字比较,但:
6.30作为数字实际代表6小时18分钟(0.3×60=18),而非代码注释里的6小时30分钟(正确应为6.5)16.10作为数字实际代表16小时6分钟(0.1×60=6),而非实际时间16小时10分钟(正确应为16.1667)
这种错误的时间换算逻辑,导致时间比较完全偏离实际需求。
2. 字符串与数字比较的隐式转换异常
当now是字符串(如"16.10")与数字16.30比较时,虽然JS会尝试将字符串转为数字,但存在边缘问题:
- 分钟数为10及以上时,字符串格式为
"小时.两位数字",转为数字后会丢失分钟的真实占比(如"16.10"转成16.1,对应16小时6分钟) - 若触发字符串直接比较(如变量类型异常),
"16.10"与"16.3"(数字16.3转字符串)会因字符顺序判断"16.10" > "16.3"为false,但实际时间16:10早于16:18,应该返回true,隐式转换的不确定性直接导致判断反转,触发闭店逻辑。
修复方案
将所有时间统一转换为当日累计分钟数进行比较,彻底避免字符串拼接和小数换算错误:
var a = document.getElementById("online"); var d = new Date(); var n = d.getDay(); // 转换为当日累计分钟数(0点至今的分钟数) var nowMinutes = d.getHours() * 60 + d.getMinutes(); // 工作时间同样用分钟数定义 var onlineweekdays = { 0: null, // Vasárnap(周日) 1: [6*60+30, 16*60+30], // hétfő(周一):6:30-16:30 2: [6*60+30, 16*60+30], // kedd(周二) 3: [6*60+30, 16*60+30], // szerda(周三) 4: [6*60+30, 16*60+30], // csütörtök(周四) 5: [6*60+30, 15*60+30], // péntek(周五):6:30-15:30 6: null // Szombat(周六) }; var onlinedayWorkingHours = onlineweekdays[n]; if (onlinedayWorkingHours && (nowMinutes > onlinedayWorkingHours[0] && nowMinutes < onlinedayWorkingHours[1])) { // 判断是否距离闭店不足15分钟 if (nowMinutes >= onlinedayWorkingHours[1] - 15) { a.innerHTML = "rövidesen zárunk."; a.style.backgroundColor = '#fee599'; a.style.color = '#7f6000'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; } else { a.innerHTML = "most elérhető."; a.style.backgroundColor = '#e2efd9'; a.style.color = '#538135'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; } } else { a.innerHTML = "most nem érhető el."; a.style.backgroundColor = '#efd9df'; a.style.color = '#c91f41'; a.style.textTransform = 'uppercase'; a.style.fontWeight = 'bold'; a.style.padding = '0 4px'; a.style.borderRadius = '3px'; a.style.marginLeft ='5px'; }
修复说明
- 用分钟数统一时间单位,彻底消除小数换算错误和隐式类型转换问题
- 闭店前15分钟的判断逻辑直接用分钟数计算,符合实际业务需求
- 时间比较逻辑清晰准确,不会再出现时区相关的异常判断
内容的提问来源于stack exchange,提问作者userZolika
相关产品推荐
相关产品推荐

