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

FastDateFormat解析"2018-09-31"得异常结果的原因及解决方法

问题解析与解决方案

我来帮你拆解这个日期解析的问题,以及给出对应的解决办法:

为什么会出现不符合预期的结果?

你的核心问题出在FastDateFormat的默认行为上:

  1. 宽松解析模式:FastDateFormat默认启用了「宽松模式(Lenient Mode)」,这种模式下解析器不会直接拒绝无效日期,而是自动调整为合法日期。比如9月只有30天,输入的2018-09-31会被当作「9月30日再加1天」,也就是10月1日。
  2. 时区差异:你看到的两个输出其实是同一个时刻的不同时区展示:date.toString()用的是你的本地AEST时区(UTC+10),显示为Mon Oct 01 00:00:00 AEST 2018;而date.toInstant()是UTC标准时间,对应的就是2018-09-30T14:00:00Z(因为UTC+10的0点等于UTC的前一天14点)。

如何让解析仅匹配合法的输入日期?

要让解析器严格校验日期合法性,拒绝无效输入,你需要把FastDateFormat切换为严格模式。FastDateFormat可以通过Builder来构建并关闭宽松模式:

修改后的测试代码

import org.apache.commons.lang3.time.FastDateFormat;
import java.text.ParseException;
import org.junit.Test;

public class DateParseTest {
    // 用Builder创建严格模式的日期格式化器
    private static final FastDateFormat dateOnlyFormat = new FastDateFormat.Builder()
            .setPattern("yyyy-MM-dd")
            .setLenient(false) // 关键:关闭宽松解析
            .build();

    @Test
    public void getSQLDateWithOnlyDate() {
        java.util.Date date = null;
        try {
            String dateString = "2018-09-31";
            date = dateOnlyFormat.parse(dateString);
            System.out.println("input date : " + dateString);
            System.out.println("date.toInstant() : " + date.toInstant());
            System.out.println("date.toString() : " + date.toString());
        } catch (ParseException e) {
            // 无效日期会触发异常,这里可以捕获并处理
            System.err.println("输入的日期无效:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

运行结果

现在输入2018-09-31时,代码会直接抛出ParseException,拒绝解析无效日期,而不是自动修正:

输入的日期无效:Unparseable date: "2018-09-31"
java.text.ParseException: Unparseable date: "2018-09-31"
    at org.apache.commons.lang3.time.FastDateFormat.parse(FastDateFormat.java:497)
    ...

额外推荐:使用Java 8+的现代日期API

如果你项目使用的是Java 8及以上版本,非常建议换成原生的java.time API(比如LocalDate和DateTimeFormatter),它的设计更合理,默认就是严格模式,而且专门处理日期/时间的类型更清晰:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import org.junit.Test;

public class ModernDateParseTest {
    private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Test
    public void parseStrictDate() {
        try {
            String dateString = "2018-09-31";
            LocalDate date = LocalDate.parse(dateString, dateFormatter);
            System.out.println("输入日期有效:" + date);
        } catch (DateTimeParseException e) {
            System.err.println("无效日期:" + e.getMessage());
        }
    }
}

这个代码同样会抛出异常拒绝无效日期,而且LocalDate是无时区的纯日期类型,能避免时区带来的混淆,更适合你只处理日期的场景。


内容的提问来源于stack exchange,提问作者Valath

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:14:13