为什么你代码没写错却报java.time.format.DateTimeParseException: Text ‘2020-10-2‘ could not be parsed at index 8

本文分享作者在自定义SpringMVC框架中遇到的日期参数解析问题,揭示了`yyyy-MM-dd`格式下月份小于10导致的解析失败,强调了对日期格式理解的重要性,防止前端开发者踩坑。

我,一个从大一开始学习java,大学第一个假期学到servlet写web,下学期就开始调接口打比赛的,大二在校跟老师参加项目拿到软著的小辣鸡,自认为是算作大学期间才接触web的那批人里学的比较快的。
在这里插入图片描述

但这个bug,真的让我觉得真是越是简单的东西越是坑。
在这里插入图片描述
日期类这个东西,如果正儿八经的接过项目的人都应该碰见过接触过用过。

在这里插入图片描述

但你真的,了解它吗?
在这里插入图片描述

事情是这样的,我在手写一个springmvc框架,写到接收注入自定义方法的参数的日期类型这里:
在这里插入图片描述

可以看到,我分别定义了对“年月日”这种参数类型,接收参数的格式化,和“年月日时分秒”这种参数类型的格式化。

parse方法没有不熟悉的吧?前一个参数是字符串,后一个参数是格式化的格式。
我的格式: yyyy-MM-dd

然后写一个测试方法,开始测试debug
在这里插入图片描述
一开始测试:2022-1-1
在这里插入图片描述
啥也没接收到,可是为什么呢?代码没写错呀

检查了一番导包然后再次测试: 2022-10-10
在这里插入图片描述
嗯,传进去了。
在这里插入图片描述
原因是因为:
当month小于10时,’MM’ 解析失败,前面加上0则解析成功.

再次测试:
在这里插入图片描述
成功。
其实提示的也很清楚了,
Text ‘2020-10-2’ could not be parsed at index 8
第八位正好是2,改成02就对了。
在这里插入图片描述

所以如果对日期格式不了解
,那,你的前端就会踩坑。

在这里插入图片描述

<think>我们遇到了一个 `java.time.format.DateTimeParseException` 异常,具体信息是解析字符串 `'2020-11-26'` 时在索引 10 处出错。索引 10 意味着解析器在尝试读取第11个字符(索引从0开始)时遇到了问题。 ### 异常分析 - 输入字符串:`"2020-11-26"` - 字符串长度:10(索引范围0到9) - 索引10:**超出字符串末尾**(因为最大索引是9) ### 原因推断 这个异常通常发生在以下情况: 1. **格式模式要求比实际字符串更长的内容**:例如,模式中指定了时区或时间部分,但输入字符串只有日期部分。 2. **输入字符串长度不足**:模式期望的字符数多于输入字符串实际提供的。 ### 验证步骤 1. **检查字符串长度**: ```java String input = "2020-11-26"; System.out.println(input.length()); // 输出 10 ``` 索引10对应第11个字符,显然超出了字符串边界。 2. **检查模式(Pattern)**: - 如果使用的是 `DateTimeFormatter.ISO_LOCAL_DATE_TIME` 等标准格式,它要求完整的时间部分(`THH:mm:ss`),而输入只有日期。 - 自定义模式如 `yyyy-MM-dd HH:mm:ss` 也会要求时间部分,导致索引10超出范围。 ### 解决方案 #### 情况1:本意是解析纯日期(无时间) **正确做法**:使用 `LocalDate` 和对应的格式器(如 `DateTimeFormatter.ISO_LOCAL_DATE` 或模式 `"yyyy-MM-dd"`)。 ```java import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class FixDateParse { public static void main(String[] args) { String input = "2020-11-26"; DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; // 或 DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate date = LocalDate.parse(input, formatter); System.out.println(date); // 输出: 2020-11-26 } } ``` #### 情况2:输入字符串本应包含时间但缺失 如果字符串应该是完整的日期时间(如 `2020-11-26T00:00:00`),但实际只提供了日期部分,则需要: - **补全时间部分**(如果逻辑允许): ```java String fullDateTimeString = input + "T00:00:00"; LocalDateTime dateTime = LocalDateTime.parse(fullDateTimeString); ``` - **修改格式模式**(如果时间部分可选): 使用 `DateTimeFormatterBuilder` 灵活处理: ```java DateTimeFormatter formatter = new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE) .optionalStart() // 时间部分可选 .appendLiteral('T') .append(DateTimeFormatter.ISO_LOCAL_TIME) .toFormatter(); ``` ### 常见错误场景 #### 错误示例:用 `LocalDateTime` 解析纯日期 ```java // 错误:尝试将纯日期字符串解析为 LocalDateTime LocalDateTime.parse("2020-11-26"); // 抛出异常 ``` `LocalDateTime` 需要完整的日期和时间(ISO格式如 `2020-11-26T00:00`),否则会在索引10处失败。 #### 错误示例:模式包含多余内容 ```java // 错误:模式中包含了时间部分,但输入有 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDate.parse("2020-11-26", formatter); // 同样会失败 ``` ### 总结步骤 1. **确认目标类型**: - 纯日期 → `LocalDate` - 日期时间 → `LocalDateTime` - 带时区 → `ZonedDateTime` 或 `OffsetDateTime` 2. **选择匹配的格式器**: - 标准格式:优先使用 `DateTimeFormatter` 的预定义常量(如 `ISO_LOCAL_DATE`)。 - 自定义格式:确保模式与输入字符串完全匹配。 3. **处理可选部分**: 使用 `DateTimeFormatterBuilder` 构建灵活格式器。 > **关键原则**:解析器的模式必须与输入字符串的结构和长度完全一致。 ### 相关问题扩展 1. 如何解析带时区的日期时间字符串(如 `2020-11-26-05:00`)? 2.Spring Boot中如何全局配置日期时间格式? 3. `Instant` 解析日期字符串有什么特殊要求?</think>### 解析 `DateTimeParseException`:解析 '2020-11-26' 时在索引 10 出错 #### 问题分析 当出现 `Text '2020-11-26' could not be parsed at index 10` 异常时,核心原因是**解析器的模式与输入字符串不匹配**: 1. **索引 10 超出字符串范围**: - 字符串 `"2020-11-26"` 长度为 10(索引范围 0~9) - 索引 10 表示解析器尝试读取第 11 个字符(超出边界) 2. **根本原因**:您使用了需要**日期+时间**的解析器(如 `LocalDateTime`),但输入只有**日期部分**(缺少时间)。 #### 解决方案 根据使用场景选择以下方法: ##### 方法 1:解析为纯日期(无时间) ```java import java.time.LocalDate; import java.time.format.DateTimeFormatter; public class FixDateParse { public static void main(String[] args) { String input = "2020-11-26"; // ✅ 正确:使用 LocalDate + 日期格式器 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate date = LocalDate.parse(input, formatter); // 成功解析 System.out.println(date); // 输出: 2020-11-26 } } ``` ##### 方法 2:补全时间部分(如果需要日期时间) ```java import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class FixDateTimeParse { public static void main(String[] args) { String input = "2020-11-26"; // 补全默认时间部分 String fullDateTime = input + "T00:00:00"; // 添加时间 // ✅ 使用 LocalDateTime 解析 LocalDateTime dateTime = LocalDateTime.parse(fullDateTime); System.out.println(dateTime); // 输出: 2020-11-26T00:00 } } ``` ##### 方法 3:使用灵活的格式器(兼容日期/日期时间) ```java import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; public class FlexibleParser { public static void main(String[] args) { String input = "2020-11-26"; DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM-dd") .optionalStart() // 时间部分可选 .appendLiteral('T') .appendPattern("HH:mm:ss") .optionalEnd() .toFormatter(); // ✅ 可解析纯日期或完整日期时间 LocalDateTime dateTime = LocalDateTime.parse(input, formatter); System.out.println(dateTime); // 输出: 2020-11-26T00:00 } } ``` #### 关键错误场景分析 ```java // ❌ 错误示例:尝试用 LocalDateTime 解析纯日期 LocalDateTime.parse("2020-11-26"); // 抛出索引 10 异常 // ❌ 错误示例:格式器包含时间部分 DateTimeFormatter wrongFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDate.parse("2020-11-26", wrongFormatter); // 同样会失败 ``` #### 最佳实践 1. **明确数据类型**: - 纯日期 → `LocalDate` - 日期+时间 → `LocalDateTime` 2. **验证字符串长度**: ```java System.out.println("2020-11-26".length()); // 输出 10(最大索引=9) ``` 3. **在 Spring Boot 中处理 JSON 解析**: 配置全局格式(解决引用[3]的问题): ```java @Configuration public class DateTimeConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> { builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss"); builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ISO_DATE_TIME)); builder.deserializers(new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)); }; } } ``` > **关键原则**:解析器的预期格式必须与输入字符串的**结构和长度**完全匹配。 ### 相关问题 1. 如何在 Java 中解析带时区的日期字符串(如 `2023-12-27T15:30:00-05:00`)? 2. `LocalDate` 和 `LocalDateTime` 在 JSON 序列化时有何不同? 3. 为什么 `Instant.parse()` 对 ISO 8601 格式要求更严格? 4. 如何自定义 Spring Boot 的全局日期时间格式?
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值