如何用JavaScript获取指定日期和时区的当日零点Unix时间戳?
如何实现指定日期与时区下当日零点的Unix时间戳函数?
问题描述
需要创建一个JavaScript函数,返回指定日期和时区下当日零点的Unix时间戳(需考虑时区因素,不能单纯转换日期字符串)。示例调用:
getMidnightTimestamp('2023-04-10','Australia/Sydney');
尝试了以下代码,但返回无效时间戳:
function getMidnightTimestamp(date, timezone) { // Parse the input date const inputDate = new Date(date); // Set the input date to midnight inputDate.setHours(0, 0, 0, 0); // Create an Intl.DateTimeFormat object with the given timezone const dateTimeFormat = new Intl.DateTimeFormat('en-US', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit', }); // Format the input date to a string in the specified timezone const dateString = dateTimeFormat.format(inputDate); // Parse the formatted date string back to a Date object const midnightDate = new Date(dateString); // Return the timestamp in milliseconds return midnightDate.getTime()/1000; } console.log(getMidnightTimestamp('2023-04-10','Australia/Sydney'));
原代码问题分析
你的代码存在两个核心错误:
- 初始解析时区错误:
new Date(date)解析YYYY-MM-DD格式字符串时,默认按UTC时区处理(部分浏览器可能用本地时区),但后续setHours(0,0,0,0)是基于本地时区设置零点,导致基准时间偏离目标时区。 - 二次解析时区偏差:格式化后的日期字符串再用
new Date解析时,依然按本地时区处理,完全没用到目标时区信息,最终时间戳自然错误。
正确实现方案
下面提供两种可靠的实现方式,均能准确处理时区(包括夏令时):
方式一:通过formatToParts提取时区日期信息计算
function getMidnightTimestamp(dateStr, timezone) { // 构造初始Date对象(YYYY-MM-DD格式默认按UTC解析) const baseDate = new Date(dateStr); // 获取目标时区下的年、月、日信息 const dateParts = new Intl.DateTimeFormat('en-US', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' }).formatToParts(baseDate); // 提取数值(月份转为0基,符合Date构造函数要求) const year = parseInt(dateParts.find(p => p.type === 'year').value, 10); const month = parseInt(dateParts.find(p => p.type === 'month').value, 10) - 1; const day = parseInt(dateParts.find(p => p.type === 'day').value, 10); // 计算目标时区的偏移量(处理夏令时) const testDate = new Date(Date.UTC(year, month, day)); const tzOffsetStr = new Intl.DateTimeFormat('en-US', { timeZone: timezone, timeZoneName: 'short' }).formatToParts(testDate).find(p => p.type === 'timeZoneName').value; // 解析偏移为毫秒 const offsetHours = parseInt(tzOffsetStr.match(/([+-]\d{2})/)[0], 10); const offsetMinutes = parseInt(tzOffsetStr.match(/\d{2}$/)[0], 10); const totalOffsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000; // 目标时区零点对应的UTC时间 = 目标日期UTC时间 - 时区偏移 const timestampMs = Date.UTC(year, month, day) - totalOffsetMs; return Math.floor(timestampMs / 1000); }
方式二:构造带时区的日期字符串解析(简洁版)
function getMidnightTimestamp(dateStr, timezone) { const baseDate = new Date(dateStr); // 获取目标时区下的年、月、日 const [year, month, day] = new Intl.DateTimeFormat('en-US', { timeZone: timezone, year: 'numeric', month: '2-digit', day: '2-digit' }).format(baseDate).split('/'); // 构造目标时区零点的完整时间字符串(主流浏览器支持直接解析时区名称) const midnightTimeStr = `${year}-${month}-${day}T00:00:00 ${timezone}`; const timestampMs = new Date(midnightTimeStr).getTime(); return Math.floor(timestampMs / 1000); }
验证结果
调用getMidnightTimestamp('2023-04-10','Australia/Sydney')时,悉尼处于夏令时(UTC+11),当日零点对应的UTC时间是2023-04-09T13:00:00,对应的Unix时间戳为1681064400,可自行验证正确性。
内容的提问来源于stack exchange,提问作者M_R_K
相关产品推荐
相关产品推荐

