Java String to DateTime 解析问题

问题描述

我有一条记录,它有一个异常的 DateTime String '20170-09-17',我试图将它解析成 DateTime 但它没有抛出任何异常,并且这条记录也不能放入 MysqL ......

        DateFormat fmt =new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(fmt.parse("20170-09-17"));

如何处理这些数据?

解决方法

java.time

我总是建议使用 java.time,现代 Java 日期和时间 API,用于日期工作。在这种情况下,它使您的任务变得非常简单。

    String abnormalInput = "20170-09-17";
    LocalDate date = LocalDate.parse(abnormalInput);
    System.out.println(date);

这会引发您预期的异常:

线程“main”中的异常java.time.format.DateTimeParseException: 无法在索引 0 处解析文本“20170-09-17”

我们甚至不需要指定任何格式化程序。您的预期输入采用 ISO 8601 格式(底部链接),LocalDate 将 ISO 8601 解析为默认格式。如果要解析的文本不符合格式,则抛出异常。它可以接受超过四位数字的年份,但只能接受一个符号(减号或加号)。因为标准是这么说的。

Andreas 在他的回答中建议的范围检查仍然是一个好主意。我建议您设置的限制不是 MySQL 可以处理的内容,而是您的域中可以被认为是正确的内容。举个例子:

    LocalDate today = LocalDate.now(ZoneId.of("Asia/Shanghai"));
    if (date.getYear() < today.getYear() - 5 || date.isAfter(today)) {
        throw new IllegalStateException("Date is out of range: " + date);
    }

链接

,

SimpleDateFormat 不知道支持的日期存储年份范围,因此需要验证日期。

既然您提到了 MySQL,并且 DATETIME 数据类型支持 1000-9999 范围内的年份,那么您应该这样做:

static Date parseDate(String dateStr) throws ParseException {
    // Parse the string (strict)
    DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
    fmt.setLenient(false); // Reject invalid month and day values
    Date date = fmt.parse(dateStr);
    
    // Validate year
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    int year = cal.get(Calendar.YEAR);
    if (year < 1000 || year > 9999)
        throw new IllegalArgumentException("Invalid year: \"" + dateStr + "\"");
    
    return date;
}

重要的部分是:

  • 开启严格解析模式,以确保 monthday 值在有效范围内。

  • 自定义检查以确保 year 值在有效范围内。


如果您可以使用较新的 Java 8+ Time API 可能会更好,在这种情况下,代码将是:

static LocalDate parseDate(String dateStr) {
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd")
            .withResolverStyle(ResolverStyle.STRICT);
    LocalDate date = LocalDate.parse(dateStr,fmt);
    if (date.getYear() < 1000 || date.getYear() > 9999)
        throw new DateTimeException("Invalid value for Year (valid values 1000 - 9999): " + date.getYear());
    return date;
}

和以前一样:严格解析和自定义年份范围检查。

,

SimpleDateFormat 和 Date 是过时的类。如果您使用 java 8 或更高版本,请切换到 DateTimeFormatter 类和类 LocalDate LocalDateTime 或其任何“兄弟”