为何yyyy-mm-dd格式字符串转Date异常,yyyy/mm/dd却正常?
我有一个日期字符串2022-04-01,想要转换成Date对象,写了如下代码:
const startDate0Hours = new Date(new Date(startDate.value).setHours(0, 0, 0, 0)); console.log('this is the date (string):', startDate.value); console.log('this is without replace:', new Date(startDate.value)); console.log('this is with replace (/-/g, "/"):', new Date((startDate.value).replace(/-/g,'/'))); console.log('this is with setHours(0,0,0,0):', startDate0Hours)
执行后输出:
this is the date (string): 2022-04-01 this is without replace: Thu Mar 31 2022 21:00:00 GMT-0300 (Brasilia Standard Time) this is with replace (/-/g, "/"): Fri Apr 01 2022 00:00:00 GMT-0300 (Brasilia Standard Time) this is with setHours(0,0,0,0): Thu Mar 31 2022 00:00:00 GMT-0300 (Brasilia Standard Time)
为什么用连字符-的日期字符串转换后日期提前一天且时间为21点,而用斜杠/的却能正确转换?
这本质是JavaScript对不同日期字符串格式的解析规则差异:
yyyy-mm-dd格式(ISO 8601标准格式):
当你用new Date("2022-04-01")时,JS会默认把这个日期解析为UTC时区的00:00:00。你的本地时区是GMT-0300(巴西利亚时间),UTC的4月1日0点减去3小时,就是本地时间3月31日21点,这就是第一个输出的由来。yyyy/mm/dd格式:
这种非ISO格式的日期字符串,JS会直接按照本地时区的00:00:00来解析,所以得到的就是本地时间4月1日0点,和你预期一致。关于
setHours(0,0,0,0)的问题:
你先通过new Date(startDate.value)得到了本地时间3月31日21点的Date对象,然后调用setHours(0,0,0,0)是设置本地时区的0点,所以这个对象就变成了本地时间3月31日0点,这就是第三个输出的结果——不是你想要的4月1日0点。
如果想要把yyyy-mm-dd格式的字符串转成本地时区的0点Date对象,有几种可靠的方式:
方式1:手动构造日期(最稳妥,无时区歧义)
直接拆分日期字符串,用new Date(year, monthIndex, day)构造(注意月份是0基的,4月对应3):
const dateStr = "2022-04-01"; const [year, month, day] = dateStr.split("-").map(Number); const localMidnight = new Date(year, month - 1, day); // 输出:Fri Apr 01 2022 00:00:00 GMT-0300 (Brasilia Standard Time)
方式2:先转UTC再转本地时区
先解析为UTC的0点,再设置本地时区的0点:
const dateStr = "2022-04-01"; const utcDate = new Date(dateStr + "T00:00:00Z"); // 明确指定UTC时间 const localMidnight = new Date(utcDate.getTime()); localMidnight.setHours(0, 0, 0, 0); // 或者更简洁: const localMidnight = new Date(new Date(dateStr).setUTCHours(0,0,0,0));
方式3:使用日期处理库(推荐)
如果项目中经常处理日期,建议用Day.js、Luxon这类轻量库,避免手动处理时区和格式的坑:
// Day.js示例 const dayjs = require('dayjs'); const localMidnight = dayjs("2022-04-01").startOf('day').toDate();
内容的提问来源于stack exchange,提问作者JRCast

