日期字符串转Date对象时日期倒退1天的技术求助
问题
实现了removeTime函数,用于将日期字符串(格式如2023-07-13)或日期时间字符串(格式如2023-07-13 03:03:03)转换为时间设置为00:00:00的Date对象(截断时间部分):
/** * @param dateString - can either be 2023-07-13 or 2023-07-13 03:03:03 */ const removeTime = (dateString: string): Date | undefined => { if (isValid(new Date(dateString))) { const timestamp = new Date(dateString); console.log('PARAM', dateString); console.log('NATIVE', timestamp); console.log('BEFORE TRUNCATE', format(timestamp, Constants.FORMAT_DATE)); console.log( 'AFTER TRUNCATE', format( new Date(timestamp.getFullYear(), timestamp.getMonth(), timestamp.getDate()), Constants.FORMAT_DATE ) ); return new Date(timestamp.getFullYear(), timestamp.getMonth(), timestamp.getDate()); } else { return undefined; } };
注:函数中使用的isValid和format方法均来自date-fns库,Constants.FORMAT_DATE格式为yyyy-MM-dd。
问题现象:传入不含时间部分的日期字符串时,new Date(dateString)会将日期倒退1天,日志示例:
PARAM: 2023-07-13 NATIVE: Wed Jul 12 2023 18:00:00 GMT-0600 (Mountain Daylight Time) BEFORE TRUNCATE: 2023-07-12 AFTER TRUNCATE: 2023-07-12
补充信息:传入含时间的字符串时函数运行正常,日志示例:
PARAM: 2023-07-13 11:26:11 NATIVE: Thu Jul 13 2023 11:26:11 GMT-0600 (Mountain Daylight Time) BEFORE TRUNCATE: 2023-07-13 AFTER TRUNCATE: 2023-07-13
解决方案
问题原因
- 当传入
YYYY-MM-DD格式的字符串时,new Date()会将其解析为UTC时间的00:00:00,结合本地时区(GMT-0600)转换后,就变成了前一天的18:00:00,最终显示的日期因此倒退一天。 - 传入带时间的字符串(如
YYYY-MM-DD HH:mm:ss)时,new Date()会直接按本地时区解析,不会出现偏移。
解决办法
利用date-fns库的parse方法精确控制解析规则,避免原生Date的解析歧义:
修改后的代码
import { isValid, format, parse } from 'date-fns'; /** * @param dateString - can either be 2023-07-13 or 2023-07-13 03:03:03 */ const removeTime = (dateString: string): Date | undefined => { // 定义支持的两种输入格式 const supportedFormats = ['yyyy-MM-dd', 'yyyy-MM-dd HH:mm:ss']; let parsedDate: Date | null = null; // 尝试用每种格式解析字符串,直到找到有效结果 for (const fmt of supportedFormats) { parsedDate = parse(dateString, fmt, new Date()); if (isValid(parsedDate)) break; } if (!parsedDate || !isValid(parsedDate)) { return undefined; } // 截断时间部分,得到本地时间的00:00:00 const truncatedDate = new Date(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()); console.log('PARAM', dateString); console.log('PARSED', parsedDate); console.log('BEFORE TRUNCATE', format(parsedDate, Constants.FORMAT_DATE)); console.log('AFTER TRUNCATE', format(truncatedDate, Constants.FORMAT_DATE)); return truncatedDate; };
额外说明
- date-fns的
parse方法可以明确指定解析格式,彻底避免原生Date在不同时区、不同输入格式下的解析不一致问题。 - 如果需要输出UTC时间的00:00:00,可以改用
parseISO方法或创建UTC日期对象,但根据需求场景,当前代码生成本地时间的00:00:00更符合预期。
内容的提问来源于stack exchange,提问作者dokgu
相关产品推荐
相关产品推荐

