【问题标题】:Format and parsing same date provides different result格式化和解析相同的日期会提供不同的结果
【发布时间】:2021-10-22 08:08:03
【问题描述】:

谁能告诉我为什么控制台上显示“10/09/2022”?

String sFecha = "10/21/2021";
try {
   SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
   System.out.println(sdf.format(sdf.parse(sFecha)));
} catch (java.text.ParseException e) {
   //Expected execution
}

注意:输入字符串是故意错误的 - 我期待异常!

【问题讨论】:

标签: java date exception simpledateformat date-parsing


【解决方案1】:

java.time

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

您在代码中观察到的问题是您在使用SimpleDateFormat 时遇到的奇怪问题之一。 SimpleDateFormat 不会因为格式错误而抛出异常,而是尝试错误地解析日期字符串。

使用现代日期时间 API java.time 的解决方案:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class Main {
    public static void main(String[] args) {
        String sFecha = "10/21/2021";
        try {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy");
            LocalDate date = LocalDate.parse(sFecha, dtf);
            System.out.println(date);
        } catch (DateTimeParseException e) {
            System.out.println("A problem occured while parsing the date string.");
            // ...Handle the exception
        }
    }
}

输出:

A problem occured while parsing the date string.

现在,把格式改成MM/dd/yyyy,就可以看到日期字符串解析成功了。

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

如果你想使用SimpleDateFormat:

false 传递给SimpleDateFormat#setLenienttrue 被默认设置。

演示:

import java.text.SimpleDateFormat;

public class Main {
    public static void main(String[] args) {
        String sFecha = "10/21/2021";
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
            sdf.setLenient(false);
            System.out.println(sdf.format(sdf.parse(sFecha)));
        } catch (java.text.ParseException e) {
            System.out.println("A problem occured while parsing the date string.");
            // ...Handle the exception
        }
    }
}

输出:

A problem occured while parsing the date string.

* 如果您正在为一个 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring。请注意,Android 8.0 Oreo 已经提供了support for java.time

【讨论】:

    【解决方案2】:

    当您使用sdf.parse() 时,您将文本转换为日期:

    10 -> days
    21 -> month
    2021 -> year
    

    21 作为月份被转换为 9(因为 21 % 12 = 9)。

    使用setLenient(false) 会抛出异常:

    通过宽松解析,解析器可能会使用启发式方法来解释不精确匹配此对象格式的输入。使用严格解析,输入必须匹配此对象的格式。

    【讨论】:

      【解决方案3】:

      您的格式是日/月/年。 21 不是有效月份,似乎减去 12 才能得到有效月份。

      【讨论】:

      • 在正确的轨道上,但不是全部真相。再说一次,接受使用SimpleDateFormat 永远不会走上正轨。
      猜你喜欢
      • 1970-01-01
      • 2022-11-07
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多