【问题标题】:Is this additional check for parsing a string to LocalDate object necessary?是否需要额外检查将字符串解析为 LocalDate 对象?
【发布时间】:2020-08-11 22:37:10
【问题描述】:

我正在为一些验证用户出生日期的遗留代码编写一些测试。我在课堂上遇到以下方法。我的疑问是 try 块中的 if 语句是否是必要的。据我了解,如果 parse 函数成功返回一个 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 exception localdate isodate defensive-programming


    【解决方案1】:

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

    如果你想删除它,你应该检查DateTimeFormatter.ISO_DATE是否默认为ResolverStyle.STRICT。假设默认情况下它不是 STRICT,您的代码可能是:

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

    【讨论】:

    • 您好,我编辑了这个问题。从源代码来看,我相信它的默认值设置为 ResolverStyle.STRICT。我认为删除该检查应该是安全的。
    【解决方案2】:

    TL;DR:检查有所作为

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

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

    演示:

        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_DATE 一样严格,所以我们知道toString() 会再次创建相同的字符串。

    此外,您可以声明方法static,并且您可以省略throws Exception,因为DateTimeParseException 是一个未经检查的异常。

    链接

    Documentation of DateTimeFormatter.ISO_DATE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 2019-07-24
      • 1970-01-01
      • 2017-03-22
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多