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

标签 java

我看过下面的代码,但我对这里正则表达式的使用感到困惑。这个checkDateSanity方法的要求是:

The DATE format is 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;
}

我读过这篇关于类似主题的文章 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;
        }

我做了一些随机测试,无论有没有正则表达式都没有任何区别。是否有更深层的原因需要在这里进行正则表达式检查?想要降低计算成本?如果是这样的话,真的值得吗?

最佳答案

定义“有效”。

例如,正则表达式允许第 19 个月的第 39 天以及第 0 个月的第 0 天:39-19-0000 是根据它的有效日期,但 1-1-2020 不是(只有 01-01-2020 会)。

SDF 是您不应该使用的旧 API(使用 java.time),但就这段代码而言,宽松已关闭,因此它不接受 39 -19-0000,尽管它会接受1-1-2020

将两者结合起来可以得到最严格的要求,但确实感觉很复杂。接受 1-1-2020 是否存在特别令人发指的问题?

但请注意这个巨大的问题:年份混淆。 1-1-99 WILL 使用具有模式 dd.MM.yyyy.setLenient(false) SDF 进行解析,并被解释为 99 年的 1 月 1 日,即罗马帝国时期的某个时间(不像王子之歌)。

仅出于这个目的,该正则表达式就非常有用;如果传递了 2 位数字的年份,您可以使用正则表达式来出错,因为 SDF 无法拒绝此类输入。

因此,这是真正的建议!

那些旧的日期 API 非常糟糕。他们很糟糕。不要使用它们。更新您的 IDE,将 SimpleDateFormat 标记为非法。这是 java time 包,它正是你想要的。请注意,SDF 返回一个 java.util.Date,它是一个说谎的骗子:它代表时间上的一个瞬间,与代表日期无关。事实并非如此 - 这就是为什么所有各种 .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.

您也可以使用 yy,这会强制您只能使用 2 位数字;它们都被解释为 20xx。 (99 年 1 月 1 日为 2099 年 1 月 1 日)。

关于java - 除了 SimpleDateFormat.parse 之外,是否还需要使用 Regex 来检查日期完整性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65755554/

相关文章:

java - 将数据从 eclipse 存储到 neo4j

java - Jersey REST 查询参数组合验证

java - Selenium webdriver-获取性能日志-未知日期时间戳(12345.12345)

java - 将变量传递给Java线程(run()方法)

java - 方法的递归实现

java - Oracle 日期的无效年份异常

java - 在 java 中使用 Formatter 写入和读取文件时遇到问题

java - 将字母映射到数字的最佳方法

javascript - GWT 编译器不允许 'default' 作为我的 JSNI block 中的 javascript 对象属性

java - 什么是NullPointerException,我该如何解决?