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

Joda DateTimeFormatter含字面量0的格式解析失败,报输入过短异常

问题分析

你的代码抛出异常的核心原因是:当使用"yyyy0MMdd"格式解析"201800101"时,Joda Time会按以下逻辑拆分输入字符串:

  • 前4位2018 → 年份(正确匹配)
  • 第5位0 → 匹配格式中的普通字符0(正确匹配)
  • 第6-7位00 → 作为月份(MM要求有效值为01-12,00属于无效月份)
  • 第8-9位01 → 日期(未被解析到,因为前面的月份已触发无效校验)

你看到的"too short"异常信息应该是被截断了,完整的异常会明确指出无效的月份值。而你的期望是把"201800101"解析为2018-01-01,说明输入字符串中多了一个多余的0(本该是"20180101"却写成了"201800101"),或者月份部分被错误地添加了前置0(比如001代表1月)。

解决方法

根据你的需求,这里提供三种可行的解决方案:

方案1:精准匹配固定结构的解析器

如果输入字符串的固定结构是4位年份 + 多余的0 + 2位月份 + 2位日期,可以用DateTimeFormatterBuilder来精准匹配这种结构:

import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

public class DateTest {
    public static void main(String[] args) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendYear(4, 4)       // 匹配4位年份
                .appendLiteral('0')     // 跳过那个多余的0
                .appendMonthOfYear(2)   // 匹配两位月份
                .appendDayOfMonth(2)    // 匹配两位日期
                .toFormatter();
        
        LocalDate date = formatter.parseLocalDate("201800101");
        System.out.println(date); // 输出:2018-01-01
    }
}

方案2:支持可变长度的月份解析

如果输入中的月份可能是1-3位(比如001代表1月),可以允许月份字段匹配1到3位数字:

import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormatterBuilder;

public class DateTest {
    public static void main(String[] args) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendYear(4, 4)           // 4位年份
                .appendMonthOfYear(1, 3)    // 允许1-3位的月份(001会被解析为1月)
                .appendDayOfMonth(2)        // 两位日期
                .toFormatter();
        
        LocalDate date = formatter.parseLocalDate("201800101");
        System.out.println(date); // 输出:2018-01-01
    }
}

方案3:预处理字符串(简单高效)

如果输入字符串的多余0位置不固定,可以先用正则表达式清理掉多余的0,再用标准格式解析:

import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class DateTest {
    public static void main(String[] args) {
        String input = "201800101";
        // 把年份后多余的0去掉,保留4位年份+2位月份+2位日期的结构
        String cleanedInput = input.replaceAll("(\\d{4})0*(\\d{2})(\\d{2})", "$1$2$3");
        
        DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd");
        LocalDate date = formatter.parseLocalDate(cleanedInput);
        System.out.println(date); // 输出:2018-01-01
    }
}

额外提示

  • 如果你确实需要解析00这类无效月份,可以使用宽松解析模式.withResolverStyle(ResolverStyle.LENIENT),但注意00会被解析为上一年的12月,这可能不符合你的期望。
  • 建议使用较新的Joda Time版本(比如2.10+),避免旧版本的解析bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:28:20