Java String to DateTime解析问题



我有一个记录,其中有一个异常的日期时间字符串'20170-09-17',我试图将其解析为日期时间,但它没有抛出任何异常,这个记录也不能放入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:文本'20170-09-17'无法在索引0处解析

我们甚至不需要指定任何格式化器。您期望的输入是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);
}

链接
  • Oracle教程:日期时间说明如何使用java.time.
  • 维基百科条目:ISO 8601
  • 问题:插入&从SQL数据库(如H2
  • )中获取java.time.LocalDate对象

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之类的类或它们的任何"兄弟">

最新更新