gpt4 book ai didi

使用点 "."而不是破折号 "-"时,Java 无法解析日期

转载 作者:行者123 更新时间:2023-12-04 14:58:41 26 4
gpt4 key购买 nike

我有一个令人困惑的问题,考虑这个工作代码:

package com.mycompany.mavenproject2;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");

Date date = formatter.parse("01-Jan-2017 00:47:13");
System.out.println(date);
}
}

按预期执行时打印 Sun Jan 01 00:47:13 CET 2017

但是,当我将每个 - 替换为 . 日期中的点时:

package com.mycompany.mavenproject2;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("dd.MMM.yyyy HH:mm:ss");

Date date = formatter.parse("01.Jan.2017 00:47:13");
System.out.println(date);
}
}

代码在执行时抛出异常:

Exception in thread "main" java.text.ParseException: Unparseable date: "01.Jan.2017 00:47:13"
at java.base/java.text.DateFormat.parse(DateFormat.java:395)
at com.mycompany.mavenproject2.Main.main(Main.java:11)

我使用的是 Java 版本 12 和德语语言环境。

有人有想法吗?

最佳答案

java.time

我非常同意为您的日期和时间工作推荐 java.time(现代 Java 日期和时间 API)的评论。

使用这个格式化程序:

private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("dd.MMMuuuu HH:mm:ss", Locale.GERMAN);

做:

    LocalDateTime dateTime = LocalDateTime.parse("01.Jan.2017 00:47:13", FORMATTER);
System.out.println(dateTime);

在具有德语语言环境的 Java 11 上运行时的输出:

2017-01-01T00:47:13

您可能想知道为什么与您的格式模式字符串相比我省略了第二个点?在 Java 11(可能也接近 Java 版本,可能从 Java 9 到 16)上,德语月份缩写带有一个点来表示缩写,所以 Jan. 代表 Januar(一月),等等。所以在我的格式 MMM 匹配 Jan. 然后 uuuu 匹配 2017.

为了更完整的故事,Java 从多达四个来源获取其区域设置数据,包括在不同区域设置中使用的月份缩写,并且并非所有来源都同意德语月份缩写的样子。自 Java 9 以来,默认值为 CLDR,COMPAT,这意味着来自 CLDR(Unicode 通用区域设置数据存储库)的区域设置数据是首选。这些包括我提到的点。通过将系统属性 java.locale-providers 设置为不以 CLDR 开头的值,您可以获得不同的结果。

你的代码出了什么问题?

我已经给了你一个提示:在一些 Java 版本中,德语月份缩写带有一个点。因此,在您使用点作为分隔符的示例中,您的 SimpleDateFormatdd.MMM (没有第二个点)匹配到 01.Jan. (有第二个点点)。根据格式,现在应该出现一个点,但由于该点已经被消耗,SimpleDateFOrmat 查看了 2017,确定它不是一个点并抛出异常你看到了。

真正令人惊讶的行为是在您的第一个示例中,其中 SimpleDateFormat 能够解析没有任何点的 01-Jan-2017 00:47:13,即使它认为月份缩写应以点结尾。我以前确实见过数百个 SimpleDateFormat 令人惊讶的行为示例,但从未见过与此类似的示例。

所有这些惊喜让我说:请务必避免使用 SimpleDateFormat

如果您持怀疑态度,我不会怪您。所以要证明:

    SimpleDateFormat formatter = new SimpleDateFormat("MMMyyyy", Locale.GERMAN);

System.out.println(formatter.format(0L));

System.out.println(formatter.parse("Jan2017"));
System.out.println(formatter.parse("Jan.2017"));

输出,仍然在 Java 11 上:

Jan.1970
Sun Jan 01 00:00:00 CET 2017
Sun Jan 01 00:00:00 CET 2017

我们看到 SimpleDateFormat 用点来格式化月份,并且能够解析带点和不带点的字符串。

这还不是全部。

    SimpleDateFormat formatter = new SimpleDateFormat("MMM", Locale.GERMAN);

System.out.println(formatter.format(0L));

输出:

Jan

这次月份缩写的格式没有点。我不知道发生了什么。我再说一遍,忘记令人困惑的 SimpleDateFormat 类。这是一个臭名昭著的麻烦制造者。

链接

关于使用点 "."而不是破折号 "-"时,Java 无法解析日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67372532/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com