是否需要将字符串解析为 LocalDate 对象的附加检查?

Is this additional check for parsing a string to LocalDate object necessary?

提问人:LycheeSojuYYDS 提问时间:8/12/2020 最后编辑:LycheeSojuYYDS 更新时间:8/13/2020 访问量:336

问:

我正在为一些验证用户出生日期的遗留代码编写一些测试。我在课堂上遇到了以下方法。我的疑问是 try 块中的 if 语句是否必要。根据我的理解,如果解析函数成功返回 LocalDate 对象,则 date.toString() 应始终等于输入 dobstr,无需进行额外检查。我错过了什么吗?我想不出任何我们需要这种额外检查的情况。请帮忙。谢谢!

private LocalDate format(String dobStr) throws Exception {
        LocalDate date = null;
        try {
            date = LocalDate.parse(dobStr, DateTimeFormatter.ISO_DATE);
            if (!dobStr.equals(date.toString())) {
                 throw new DateTimeParseException("some message");
            }
        }
        catch (DateTimeParseException ex) {
            throw ex;
        }
        return date;
}

这是我在 DateTimeFormatter.ISO_DATE 的源代码中找到的

public static final DateTimeFormatter ISO_DATE;
static {
    ISO_DATE = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(ISO_LOCAL_DATE)
            .optionalStart()
            .appendOffsetId()
            .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
}
java 异常 localdate isodate 防御性编程

评论


答:

5赞 NoDataFound 8/12/2020 #1

我能看到进行检查的唯一原因是避免宽松问题:解析器可能很宽松并试图解释错误的值(例如:2020-12-32 可以解释为 2021-01-01)。toString()

如果要删除它,则应检查是否默认。假设默认情况下它不是 STRICT,您的代码可能是:DateTimeFormatter.ISO_DATEResolverStyle.STRICT

private LocalDate format(String dobStr) throws Exception {
  return LocalDate.parse(dobStr, DateTimeFormatter.ISO_DATE.withResolverStyle(ResolverStyle.STRICT));
}

评论

1赞 LycheeSojuYYDS 8/12/2020
嗨,我编辑了问题。从源代码来看,我相信它的默认值设置为 ResolverStyle.STRICT。我认为删除该检查应该是安全的。
2赞 Anonymous 8/13/2020 #2

TL;DR:检查会有所作为

如果字符串包含不需要的偏移 ID,您仍然可以使用 .但是由于 a 不能有偏移量(这是名称中 local 的意思),因此 的结果永远不会有该偏移量 ID,因此字符串将不相等。DateTimeFormatter.ISO_DATELocalDatetoString()

DateTimeFormatter.ISO_DATE在日期之后接受可选的偏移 ID。因此,如果您正在解析 or ,则会抛出自定义异常。除了细节:没有与单个字符串参数匹配的构造函数,因此代码不会编译。我认为这来自原始代码的草率复制粘贴。2020-08-12z2020-08-12+01:02:03DateTimeParseException

演示:

    String dobStr = "2020-08-12+01:02:03";
    LocalDate date = LocalDate.parse(dobStr, DateTimeFormatter.ISO_DATE);
    String asStringAgain = date.toString();
    System.out.format("Original string: %s; result of toString(): %s; equal? %s%n",
            dobStr, asStringAgain, dobStr.equals(asStringAgain));

输出为:

原始字符串: 2020-08-12+01:02:03;toString() 的结果: 2020-08-12;平等?假

如何避免检查

除非在不需要的偏移量的情况下需要自定义异常,否则该方法可以编写得更简单:

private LocalDate format(String dobStr) throws Exception {
    return LocalDate.parse(dobStr, DateTimeFormatter.ISO_LOCAL_DATE);
}

DateTimeFormatter.ISO_LOCAL_DATE不接受字符串中的任何偏移量。它就像 一样严格,所以我们知道这将再次创建相同的字符串。DateTimeFormatter.ISO_DATEtoString()

此外,您可以声明方法,并且可以省略,因为这是一个未经检查的异常。staticthrows ExceptionDateTimeParseException

链接

DateTimeFormatter.ISO_DATE 的文档