简体   繁体   English

除了 SimpleDateFormat.parse 之外,是否还需要使用 Regex 来检查日期完整性?

[英]Is it ncessary to use Regex to check date sanity in addition to SimpleDateFormat.parse?

I've seen the following code and I'm confused about the use of Regex here.我看过下面的代码,我对这里使用 Regex 感到困惑。 The requirement of this checkDateSanity method is:这个 checkDateSanity 方法的要求是:

The DATE format is dd.MM.yyyy. DATE 格式为 dd.MM.yyyy。 (WARNING: the DATE must exist!!) (警告:日期必须存在!!)

   private boolean checkDateSanity(String dateString) {
    if (Pattern.matches("[0-3][0-9].[0-1][0-9].[0-9]{4}", dateString)) {
        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(dateString);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    return false;
}

I've read this post on a similar topic How to sanity check a date in Java , where the answer simply uses我已经阅读了有关类似主题的这篇文章How to sanity check a date in Java ,其中答案只是使用

        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(dateString);
            return true;
        } catch (ParseException e) {
            return false;
        }

I did some random tests and the Regex doesn't make any difference with or without it.我做了一些随机测试,无论有没有它,Regex 都没有任何区别。 Is there any deeper reason to have the Regex check here?有没有更深层次的理由让 Regex 在这里检查? Like to reduce the computation cost?想降低计算成本? If that's the case, is it really worth it?如果是这样的话,真的值得吗?

Define 'valid'.定义“有效”。

The regex, for example, allows For the 39th day of the 19th month, as well as the 0th day of the 0th month: 39-19-0000 is a valid date according to it, but 1-1-2020 is not (only 01-01-2020 would be).例如,正则表达式允许在第 19 个月的第 39 天以及第 0 个月的第 0 天:根据它, 39-19-0000是有效日期,但1-1-2020不是(仅01-01-2020将是)。

The SDF is old API that you shouldn't use (use java.time ), but as far as this code goes, lenience is turned off, so it does not accept 39-19-0000 , though it would accept 1-1-2020 . SDF 是旧的 API ,您不应该使用(使用java.time ),但就这段代码而言,宽大已关闭,因此它不接受39-19-0000 ,尽管它会接受1-1-2020

Combining the two gets you the strictest take, but it sure feels convoluted.将两者结合起来会让你得到最严格的要求,但它确实让人感到复杂。 Is there a particular heinous issue with accepting 1-1-2020 ?接受1-1-2020是否有特别令人发指的问题?

But note this gigantic problem : Year confusion.但请注意这个巨大的问题:年份混乱。 1-1-99 WILL parse with a .setLenient(false) SDF with pattern dd.MM.yyyy , and is interpreted as jan 1st during the year 99, sometime during the days of the roman empire (not like the prince song). 1-1-99使用带有模式dd.MM.yyyy.setLenient(false) SDF 进行解析,并被解释为 99 年的 1 月 1 日,即罗马帝国时期的某个时候(不像王子歌)。

For that purpose alone, that regex is quite useful;仅出于这个目的,该正则表达式就非常有用; you can use the regexp to error out if a 2-digit year is passed, as SDF can't reject that kind of input.如果通过了 2 位数年份,您可以使用正则表达式出错,因为 SDF 不能拒绝这种输入。

Thus, the real advice!因此,真正的建议!

Those old date apis are so incredibly bad.那些旧的日期 API 非常糟糕。 They suck.他们很烂。 Do not use them.不要使用它们。 Update your IDE, mark down SimpleDateFormat as illegal.更新您的 IDE,将SimpleDateFormat标记为非法。 Here is the java time package, doing precisely what you want.这是 java 时间 package,做你想做的事。 Note that SDF returns a java.util.Date which is a lying liar who lies: That represent an instant in time and has no business representing dates.请注意,SDF 返回一个java.util.Date ,这是一个撒谎的骗子:它代表时间的瞬间并且没有代表日期的业务。 It really doesn't - that's why all the various .getYear() etc methods are deprecated.它真的没有 - 这就是所有各种.getYear()等方法都被弃用的原因。

LocalDate x = LocalDate.parse("01.01.1999", DateTimeFormatter.ofPattern("dd.MM.yyyy"));
System.out.println(x);
> 1999-01-01

// Awesome. It's an actual _DATE_ and not a timestamp where timezones
// can mess everything up.

LocalDate x = LocalDate.parse("01.01.99", DateTimeFormatter.ofPattern("dd.MM.yyyy"));
> Exception in thread "main" java.time.format.DateTimeParseException: Text '01.01.1999' could not be parsed

// perfect. it crashes, as it should.

LocalDate x = LocalDate.parse("1.1.1999", DateTimeFormatter.ofPattern("dd.MM.yyyy"));
> Exception in thread "main" java.time.format.DateTimeParseException: Text '01.01.1999' could not be parsed

// if you want `1.1.1999` to crash, well, you can.

LocalDate x = LocalDate.parse("1.1.1999", DateTimeFormatter.ofPattern("d.M.yyyy"));
System.out.println(x);
> 1999-01-01

// but you don't have to. with just `d`, 1 parses as 1, so does 01.

You can go with yy too, which FORCES that you only use 2 digits;您也可以使用yy go ,这迫使您只使用 2 位数字; they are all interpreted as 20xx.它们都被解释为 20xx。 (1.1.99 is 2099-01-01). (1.1.99 是 2099-01-01)。

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

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