You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

日期字符串转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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 13:50:12