【问题标题】:After i added throws ParseException, the parse excception still occured, why?我添加 throws ParseException 后,仍然出现解析异常,为什么?
【发布时间】:2021-06-12 13:51:34
【问题描述】:

问题是计算两个日期之间的天数。这是我的代码

public static void main(String[] args) throws ParseException  {
    // TODO Auto-generated method stub
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-mm-dd)");
    Scanner input=new Scanner(System.in);
    String date1=input.nextLine();
    String date2=input.nextLine();
    Date d1 =sdf.parse(date1);
    Date d2= sdf.parse(date2);
    if(d1.getTime()>d2.getTime()) {
        System.out.println(d2.getTime()-d1.getTime()/(24*60*60*1000));
    }
    else
        System.out.println(d1.getTime()-d2.getTime()/(24*60*60*1000));

输出是

2010/05/29
2010/01/01
Exception in thread "main" java.text.ParseException: Unparseable date: "2010/05/29"
        at java.base/java.text.DateFormat.parse(DateFormat.java:396)
        at HW10_09156136_1092.HW10_Ex01.main(HW10_Ex01.java:15)

【问题讨论】:

  • 因为将 throws 子句添加到方法并不会阻止抛出该异常。恰恰相反。它只是将该方法标记为可能抛出该异常,以便调用者可以根据需要在 try-catch-block 中处理它。但由于 main 方法是入口点,所以没有特殊处理。
  • 解决您的问题的方法是不要尝试以任何方式处理异常。相反,您需要查看异常发生的原因并修改您的代码,使其不会被抛出。在您的情况下,您尝试解析年、月和日由/ 分隔的日期,但在您的日期格式中,您使用的格式是使用-
  • (1) 不要使用SimpleDateFormatDate。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APILocalDateDateTimeFormatter。 (2) 不要自己计算时间。你的也是不正确的。将日期和时间数学留给库方法。 (3) 在方法中输入自己的代码时,去掉注释// TODO Auto-generated method stub

标签: java date time days parseexception


【解决方案1】:

? 你已经用m [Minute in hour] 代替了M [month in year]。

? 您的输入以/ 作为分隔符,而您在解析器中为其指定了-。输入应与解析器指定的模式匹配。

除此之外,java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用,改用modern Date-Time API*

使用现代日期时间 API java.time 的演示:

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

public class Main {
    public static void main(String[] args) {
        String strDateStart = "2021-06-09";
        String strDateEnd = "2021-06-12";
        LocalDate dateStart = LocalDate.parse(strDateStart);
        LocalDate dateEnd = LocalDate.parse(strDateEnd);
        long days = ChronoUnit.DAYS.between(dateStart, dateEnd);
        System.out.println(days);
    }
}

输出:

3

ONLINE DEMO

现代日期时间 API 基于 ISO 8601,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用 DateTimeFormatter 对象。

Trail: Date Time 了解有关现代日期时间 API 的更多信息。

使用旧版 API:

如果已经存在相同的 API,请避免自己执行计算,例如以下代码使用Math#absTimeUnit#convert 来避免容易出错的if-else 和计算。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) throws ParseException {
        String strDateStart = "2021-06-09";
        String strDateEnd = "2021-06-12";
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        Date dateStart = sdf.parse(strDateStart);
        Date dateEnd = sdf.parse(strDateEnd);
        
        long millisInOneDay = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
        long days = Math.abs((dateEnd.getTime() - dateStart.getTime()) / millisInOneDay);
        
        System.out.println(days);
    }
}

ONLINE DEMO

在我添加 throws ParseException 之后,解析异常仍然存在 发生了,为什么?

throws 子句添加到方法会强制方法的调用者使用try-catch 处理异常或重新抛出它。这不是防止抛出异常的方法。从 Oracle 的 this excellent tutorial 了解更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    相关资源
    最近更新 更多