客户端时区差导致JS Date比较逻辑与日期格式化异常如何解决
问题根源
YYYY-MM-DD格式的纯日期字符串在被Date.parse()或new Date()直接解析时,会被ECMAScript规范默认判定为UTC时区的0点整,而非客户端本地时区的0点。当客户端时区晚于UTC(比如你使用的太平洋夏令时为UTC-7),UTC 6月21日0点会被转换为本地6月20日17点,直接导致日期判定偏移、显示错误两个问题。
修复方案
根据你的业务需求二选一即可:
方案1:按客户端本地时区判定活动状态+显示日期
如果活动的开始/结束日期是按用户所在地的本地日期判定,手动拆分日期字符串构造本地时区的Date对象,避免默认UTC解析:
const ongoingEvents = [], upcomingEvents = [] for (const event of allEvents) { // 拆分年月日,JS月份从0开始计数所以要减1 const [sYear, sMonth, sDay] = event.start_date.split('-').map(Number) const startDate = new Date(sYear, sMonth - 1, sDay) const nowDate = new Date() // 只比较日期的话可以把当前时间也转换为本地0点,避免当天时间未到0点就判定为已开始 const nowLocalStart = new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate()) if (startDate < nowLocalStart) { ongoingEvents.push(event) } else { upcomingEvents.push(event) } // 格式化显示,此时得到的就是本地时区的正确日期 const startString = startDate.toLocaleString('en-US', { month: 'short', day: 'numeric' }) }
方案2:按统一时区(服务器时区)判定活动状态+显示日期
如果活动的开始/结束日期是全局统一(比如不管用户在哪都按UTC日期判定),解析和比较、格式化全程指定UTC时区即可:
const ongoingEvents = [], upcomingEvents = [] for (const event of allEvents) { const [sYear, sMonth, sDay] = event.start_date.split('-').map(Number) // 构造UTC时区的日期对象 const startDate = new Date(Date.UTC(sYear, sMonth - 1, sDay)) const nowDate = new Date() // 取当前时间的UTC日期零点 const nowUTCStart = new Date(Date.UTC(nowDate.getUTCFullYear(), nowDate.getUTCMonth(), nowDate.getUTCDate())) if (startDate < nowUTCStart) { ongoingEvents.push(event) } else { upcomingEvents.push(event) } // 格式化时指定UTC时区,保证所有用户看到的日期和服务器下发一致 const startString = startDate.toLocaleString('en-US', { month: 'short', day: 'numeric', timeZone: 'UTC' }) }
内容的提问来源于stack exchange,提问作者Alvaro Bataller
相关产品推荐
相关产品推荐

