简体   繁体   English

将字符串解析为 LocalDate object 的附加检查是否必要?

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

I was writing some tests for some legacy code that validates a user's date of birth.我正在为一些验证用户出生日期的遗留代码编写一些测试。 I encounter the following method in the class.我在class中遇到如下方法。 My doubt is that whether the if statement in the try block is necessary.我的疑问是 try 块中的 if 语句是否是必要的。 From my understanding, if the parse function returns a LocalDate object successfully, then date.toString() should always equal to the input dobstr, and there's no need to do an additional check.根据我的理解,如果解析 function 成功返回 LocalDate object,那么 date.toString() 应该总是等于输入的 dobstr,并且不需要做额外的检查。 Am I missing anything?我错过了什么吗? I could not think of any case that we need this extra check.我想不出我们需要这种额外检查的任何情况。 Please help.请帮忙。 Thanks!谢谢!

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;
}

this is what I found in the source code for DateTimeFormatter.ISO_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);
}

The only reason that I could see for doing a toString() check would be to avoid lenient issue: the parser may be lenient and try to interpret wrong values (for example: 2020-12-32 could be interpreted as 2021-01-01).我可以看到进行toString()检查的唯一原因是避免宽松问题:解析器可能是宽松的并尝试解释错误的值(例如:2020-12-32 可以解释为 2021-01-01 )。

If you want to remove it, you should check if DateTimeFormatter.ISO_DATE is ResolverStyle.STRICT by default or not.如果要删除它,则应检查DateTimeFormatter.ISO_DATE默认是否为ResolverStyle.STRICT Assuming it is not STRICT by default, your code could be:假设默认情况下它不是 STRICT,您的代码可能是:

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

TL;DR: The check makes a difference TL;DR:支票有所作为

If the string contains an unwanted offset ID, you will still be able to parse it using DateTimeFormatter.ISO_DATE .如果字符串包含不需要的偏移 ID,您仍然可以使用DateTimeFormatter.ISO_DATE对其进行解析。 But since a LocalDate cannot have an offset (this is what local in the name means), the result of toString() will never have that offset ID, so the strings will not be equal.但是由于LocalDate不能有偏移量(这就是名称中local的意思), toString()的结果将永远不会有偏移量 ID,因此字符串将不相等。

DateTimeFormatter.ISO_DATE accepts an optional offset ID after the date. DateTimeFormatter.ISO_DATE接受日期之后的可选偏移 ID。 So if you are parsing 2020-08-12z or 2020-08-12+01:02:03 , the custom exception would be thrown.因此,如果您正在解析2020-08-12z2020-08-12+01:02:03 ,则会抛出自定义异常。 Except for a detail: DateTimeParseException hasn't got a constructor that matches a single string argument, so the code doesn't compile.除了一个细节: DateTimeParseException没有与单个字符串参数匹配的构造函数,因此代码无法编译。 I reckon that this comes from sloppy copy-paste from the original code.我认为这来自原始代码的草率复制粘贴。

To demonstrate:展示:

    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));

Output is: Output 是:

Original string: 2020-08-12+01:02:03;原字符串:2020-08-12+01:02:03; result of toString(): 2020-08-12; toString() 的结果:2020-08-12; equal?平等的? false错误的

How to obviate the check如何避免检查

Unless you require a custom exception in the case of an unwanted offset, the method may be written much more simply:除非您在不需要的偏移量的情况下需要自定义异常,否则该方法可以更简单地编写:

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

DateTimeFormatter.ISO_LOCAL_DATE does not accept any offset in the string. DateTimeFormatter.ISO_LOCAL_DATE不接受字符串中的任何偏移量。 And it is strict just like DateTimeFormatter.ISO_DATE , so we know that toString() would create the same string again.它就像DateTimeFormatter.ISO_DATE一样严格,所以我们知道toString()会再次创建相同的字符串。

Furthermore you may declare the method static , and you may leave out throws Exception since DateTimeParseException is an unchecked exception.此外,您可以声明方法static ,并且您可以省略throws Exception因为DateTimeParseException是未经检查的异常。

Link关联

Documentation of DateTimeFormatter.ISO_DATE DateTimeFormatter.ISO_DATE的文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM