为什么使用SimpleDateFormat解析无效日期未抛出预期异常?
问题原因
SimpleDateFormat默认开启了*宽松解析(lenient parsing)*模式,这种模式下会自动调整逻辑上不合法的日期为合法值,不会抛出解析异常,这就是你输入02/29/2021会被自动转为03/01/2021的核心原因。
修复方案
方案1:调整SimpleDateFormat的解析模式
只需要在初始化SimpleDateFormat后,调用setLenient(false)关闭宽松解析即可,代码修改如下:
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); // 新增下面这行,关闭宽松解析 formatter.setLenient(false);
注意:
SimpleDateFormat是线程不安全的类,如果是多线程环境下使用要注意加锁或者用线程本地变量存储,避免出现并发问题。
方案2(更推荐):使用Java 8+提供的java.time新时间API
Java 8之后推出的java.time包彻底解决了旧日期API的线程安全、解析逻辑不严谨的问题,默认就是严格解析模式,不需要额外配置,实现代码参考:
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Scanner; import java.time.temporal.ChronoUnit; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String d1 = sc.next(); String d2 = sc.next(); // 定义日期格式,默认就是严格解析 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); try { LocalDate date1 = LocalDate.parse(d1, formatter); LocalDate date2 = LocalDate.parse(d2, formatter); // 直接计算天数差,不需要手动处理时间戳 long days = ChronoUnit.DAYS.between(date2, date1); System.out.println(days); } catch (DateTimeParseException e) { System.out.println("Data inválida"); e.printStackTrace(); } } }
这个方案不需要额外配置严格解析,遇到02/29/2021这类无效日期会直接抛出DateTimeParseException,而且API设计更清晰,不存在线程安全问题。
内容的提问来源于stack exchange,提问作者Robson Fischer
相关产品推荐
相关产品推荐

