DateTimeFormatter日期格式问题

4

我有一个用以下格式表示的日期:2020年1月1日 上午3:4:7。我想使用DateTimeFormatter对其进行格式化。

我有以下代码以及一个格式化程序来解析它,但它不起作用。

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

我遇到了以下异常:

java.time.format.DateTimeParseException: 在索引0处无法解析文本“1/1/2020 3:4:7 AM”

有人能帮我吗?

1
你尝试过使用 "M/d/uuuu h:m:s a" 作为格式模式吗? - deHaar
4个回答

7

两个不同的问题:

计数错误

你使用了例如MM这样的显式格式:总是全数字,前导零。但是你的字符串并不是这样的,它只是一个数字。因此,请使用 M/d/uuuu h:m:s a

编辑: 感谢@deHaar,将yyyy更改为uuuu。原因:yyyy或uuuu很少有区别,但请注意,这意味着需要4位数字。这个区别在0年之前的年份上会发生变化:uuuu会变成负数,而yyyy则不会,并期望您使用例如GG,以便您得到44 BC而不是-44。因此,uuuu更加正确,即使通常情况下不会出现差异。

缺失地区设置

第二个问题是,你几乎永远不应该使用ofPattern的这个版本 - 它有一个无法通过单元测试捕获的错误,这使得这个错误重复出现成千上万次,从而成为一个真正的问题。

你需要指定地区设置。如果没有地区设置,'AM'将无法解析,除非你的平台默认地区设置是英语。

总体思路

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM",
  DateTimeFormatter.ofPattern("M/d/uuuu h:m:s a", Locale.ENGLISH));

非常好用。


谢谢,我已将您的回答标记为已接受,因为您指出还需要 Local.ENGLISH。 - user2254180
1
我会使用 uuuu 表示年份(没有特定的纪元),否则这个答案就得到了应有的认可... - deHaar

4
在你的代码片段中:
LocalDateTime
    .parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
  • 1 - 与 MM 不匹配
  • 1 - 与 dd不匹配
  • 3 - 与 hh 不匹配
  • 4 - 与 mm 不匹配
  • 7 - 与 ss 不匹配

即,格式化程序模式(例如MM)的长度和它们在字符串文本(例如1)中的相应部分的长度不匹配。

您可以通过几种方式来匹配它们,例如您可以将 string text 更改为与 formatter pattern 匹配,或者反过来。

您可以尝试这个方法:

LocalDateTime
    .parse("01/01/2020 03:04:07 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

此外,请查看模式字母和符号

4
  1. Use single letters for date and time components (month, day, year, hour, minute, and second).

  2. You can also make the formatter handle the pattern in a case insensitive way (e.g. am, AM, Am) as shown below:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
             // Formatter to handle the pattern in case insensitive way (e.g. am, AM, Am)
            DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                                .parseCaseInsensitive()
                                                .appendPattern("M/d/u h:m:s a")
                                                .toFormatter(Locale.ENGLISH);
            LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", formatter);
            System.out.println(date);
        }
    }
    

输出:

2020-01-01T03:04:07

2
太棒了,这里有人介绍了一个DateTimeFormatterBuilder;-) - deHaar

2
根据DateTimeFormatter的文档

数字:如果字母数量为,则输出的值使用最小数量的数字且不填充。否则,数字的数量用作输出字段的宽度,必要时进行零填充。

通过反向推理,您可以尝试使用此格式化程序:
DateTimeFormatter.ofPattern("M/d/yyyy h:m:s a")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接