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

使用apache.commons.lang3.time.DateUtils.parseDate解析日期时出现时区相关的时间偏差问题

使用apache.commons.lang3.time.DateUtils.parseDate解析日期时出现时区相关的时间偏差问题

嘿,我来帮你拆解下这个问题的核心原因和解决办法~

问题根源:CST时区标识的歧义性

你碰到的时间偏差本质是Date.toString()输出的CST时区缩写不是唯一的:

  • 你所在的中国标准时间(China Standard Time)是GMT+8
  • 但CST同时也代表美国中部标准时间(Central Standard Time,GMT-6)、澳大利亚中部标准时间(GMT+9:30)等

当DateUtils.parseDate解析这个字符串时,它默认把CST识别成了美国中部标准时间(GMT-6)。这样一来:
原字符串的Wed Jan 10 00:00:00 CST 2024(美国中部时间)转换为中国标准时间(GMT+8)时,需要加上8 - (-6) = 14小时,最终就变成了你看到的Wed Jan 10 14:00:00 CST 2024。

解决方案

方案1:避免用Date.toString()作为解析输入(推荐)

Date.toString()的输出格式本身就不适合用于日期解析,因为时区标识有歧义。如果一定要做字符串转换,建议用SimpleDateFormat明确指定时区和格式:

import java.util.Date;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class ClassTest {
    private static final String PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy";
    // 明确指定中国时区
    private static final TimeZone CHINA_TZ = TimeZone.getTimeZone("GMT+8");

    public void methodTest() throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.set(2024, Calendar.JANUARY, 10, 0, 0, 0);
        Date date = calendar.getTime();
        System.out.println(date); // Wed Jan 10 00:00:00 CST 2024

        // 用指定时区格式化日期为字符串
        SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
        sdf.setTimeZone(CHINA_TZ);
        String dateStr = sdf.format(date);

        // 解析时同样指定时区
        Date date2 = org.apache.commons.lang3.time.DateUtils.parseDate(dateStr, CHINA_TZ, PATTERN);
        System.out.println(date2); // Wed Jan 10 00:00:00 CST 2024
    }

    public static void main(String[] args) {
        ClassTest ct = new ClassTest();
        try {
            ct.methodTest();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案2:改用Java 8+的日期时间API(更推荐)

Java 8引入的java.time包(比如ZonedDateTime、DateTimeFormatter)专门解决了旧Date/Calendar的时区、格式化缺陷,用法更清晰:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class ClassTest {
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy");
    // 明确指定中国时区
    private static final ZoneId CHINA_ZONE = ZoneId.of("Asia/Shanghai");

    public void methodTest() {
        ZonedDateTime date = ZonedDateTime.of(2024, 1, 10, 0, 0, 0, 0, CHINA_ZONE);
        System.out.println(date); // 2024-01-10T00:00+08:00[Asia/Shanghai]

        // 格式化字符串
        String dateStr = date.format(FORMATTER);
        // 解析字符串,指定时区
        ZonedDateTime date2 = ZonedDateTime.parse(dateStr, FORMATTER.withZone(CHINA_ZONE));
        System.out.println(date2); // 2024-01-10T00:00+08:00[Asia/Shanghai]
    }

    public static void main(String[] args) {
        ClassTest ct = new ClassTest();
        ct.methodTest();
    }
}

方案3:直接跳过字符串转换(最简便)

如果你的需求只是复制一个Date对象,完全不需要转成字符串再解析,直接复制时间戳即可:

Date date2 = new Date(date.getTime()); // 直接复制时间戳,结果完全一致

备注:内容来源于stack exchange,提问作者dmjy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 08:40:30