【问题标题】:Why is the expected exception not thrown on parsing invalid date? [duplicate]为什么在解析无效日期时没有抛出预期的异常? [复制]
【发布时间】:2021-12-11 07:56:13
【问题描述】:

我得到两个字符串,我必须将它们转换为日期并显示它们之间的天数差异。但如果两个日期之一无效,我必须抛出异常。

这是我目前完成这项任务的代码:

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String d1 = sc.next();
        String d2 = sc.next();

        SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");

        try {
            Date date1 = formatter.parse(d1);
            Date date2 = formatter.parse(d2);

            long dt = (date1.getTime() - date2.getTime()) + 3600000;
            long days = (dt / 86400000L);

            System.out.println(days);
        } catch (ParseException e) {
            System.out.println("Data inválida");
            e.printStackTrace();
        }
    }
}

但是如果我输入了一个无效的日期,比如02/29/2021,它会转换为03/01/2021,而不是抛出异常。

【问题讨论】:

  • 试试formatter.setLenient(false);
  • 你不应该使用DateSimpleDateFormat,它们都已经过时了。请改用 java.time 包中的类。在你的情况下可能是LocalDate。然后使用ChronoUnit.DAYS.between(date1, date2),您就有了介于两者之间的时间。
  • @shmosel 成功了,谢谢
  • @MCEmperor 我如何更改格式化程序以使用 LocalDate?

标签: java string date simpledateformat localdatetime


【解决方案1】:

java.time

@MCEmperor 我如何更改格式化程序以使用 LocalDate?

与 MCEmperor 一样,我建议您使用现代 Java 日期和时间 API java.time 进行日期工作。

public class Main {
    private static final DateTimeFormatter FORMATTER
            = DateTimeFormatter.ofPattern("dd/MM/uuuu", Locale.ROOT)
                    .withResolverStyle(ResolverStyle.STRICT);

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String d1 = sc.next();
        String d2 = sc.next();
        
        try {
            LocalDate date1 = LocalDate.parse(d1, FORMATTER);
            LocalDate date2 = LocalDate.parse(d2, FORMATTER);
            
            long days = ChronoUnit.DAYS.between(date2, date1);
            
            System.out.println(days);
        } catch (DateTimeParseException dtpe) {
            System.out.println("Data inválida");
            dtpe.printStackTrace();
        }
    }
}

示例会话:

03/02/2021
02/29/2021
Data inválida
java.time.format.DateTimeParseException: Text '02/29/2021' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 29
    at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)
    at Main.main(Main.java:18)

您可能还会在代码中注意到计算两个日期之间的天数更加自然和简单。

你的代码出了什么问题?

但是如果我输入了一个无效的日期,比如02/29/2021,它会转换为 03/01/2021 而不是抛出异常。

这是设计的。我同意你的看法,这是一个令人困惑、令人惊讶和不幸的设计。当您将非闰年的 2 月 29 日传递给具有默认设置的 SimpleDateFormat 时,它只会将其视为 2 月 28 日之后的一天,即 3 月 1 日。这只是不使用该类的众多原因之一。

链接

Oracle tutorial: Date Time 解释如何使用 java.time。

【讨论】:

  • 好建议!但是,我会使用Scanner#nextLine 而不是Scanner#next。尽管此特定模式不需要,但想象一下处理MM dd yyyyEEE dd MMM 等模式的需求会发生变化。
  • 是的,@ArvindKumarAvinash,我也是。 :-) 在这种情况下,我不加批判地接管了这个问题,以便更容易区分哪些更改对于迁移到 java.time 是必要的
猜你喜欢
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 2018-04-18
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
相关资源
最近更新 更多