【问题标题】:What is wrong with this java date formatter?这个 java 日期格式化程序有什么问题?
【发布时间】:2021-12-29 20:29:43
【问题描述】:

我正在尝试将您在下面的代码中看到的日期格式化为字符串,以便能够将其作为 LocalDateTime 对象,但我遇到了一个异常,我正在遵循本指南https://mkyong.com/java8/java-8-how-to-convert-string-to-localdate/,但不幸的是,它没有像我下面的日期这样的例子,有人可以帮我看看吗?我真的很感激:)

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE MMM d hh:mm:ss zzz yyyy",   Locale.US);
String date = "Wed Nov 18 00:00:00 COT 2020";
LocalDateTime localDateTime = LocalDateTime.parse(date, formatter);
System.out.println(localDateTime);
System.out.println(formatter.format(localDateTime));

我得到:

java.time.format.DateTimeParseException: Text 'Wed Nov 18 00:00:00 COT 2020' 无法在索引 0 处解析

【问题讨论】:

  • @user16632363 已编辑问题,删除日期前的 5 后仍然无法正常工作
  • 请给出比“不工作”更详细的问题描述。
  • DateTimeFormatter 的 Javadoc 对模式字母的数量有什么说法?
  • 如果你有DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US );,那么你可以解析它。但是 LocalDateTime 不包含 TimeZone
  • 提示:生成此类本地化字符串仅用于向用户展示。所以你不应该需要解析这些值。特别是,您使用的不是唯一的 2-4 个字符伪区域!因此解析只能猜测您打算在多个时区中的哪个时区。相反,要以文本方式序列化日期时间值,请仅使用标准 ISO 8601 格式。

标签: java java-time datetime-parsing localdatetime datetimeformatter


【解决方案1】:

要回答标题中提出的问题,这个 Java 日期格式化程序有什么问题?

  • EEEE 是星期几的全名,例如 Monday。对于像Mon 这样的缩写,您需要EEEEEE
  • 正如其他人所说,小写hh 是上午或下午从0112 的时钟时间,因此无法解析您的00 时间。即使可以,它也无法在一天中的时间提供足够的信息。对于从0023 的一天中的一个小时,您需要大写HH
  • Basil Bourque 在评论中已经提到了一个更基本的问题:解析像 COT 这样的时区缩写的结果通常是未定义的。虽然COT 可能只有一个定义,但我不知道,大多数最常见的缩写都是模棱两可的,你不知道解析它们会得到什么。
  • 如前所述,您的格式化程序不能用于格式化LocalDateTimeLocalDateTime 没有任何时区。格式化程序需要时区的缩写名称 zzz。您可以格式化 ZonedDateTime,也可以使用其 withZone 方法修改格式化程序以具有覆盖区域。

提示:当您不知道为什么 解析 失败时,请尝试使用相同的格式化程序格式化预期值,并将结果与​​您尝试的字符串进行比较解析。大多数情况下,差异会引导您走上正确的道路。像这样:

    ZonedDateTime val = ZonedDateTime.of(
            2020, 11, 18, 0, 0, 0, 0, ZoneId.of("America/Bogota"));
    DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("EEEE MMM d hh:mm:ss zzz yyyy", Locale.US);
    String toBeParsed = "Wed Nov 18 00:00:00 COT 2020";
    String formatted = val.format(formatter);
    System.out.println("String to be parsed: " + toBeParsed);
    System.out.println("Formatted string:    " + formatted);

输出:

String to be parsed: Wed Nov 18 00:00:00 COT 2020
Formatted string:    Wednesday Nov 18 12:00:00 COT 2020

区别是Wednesday12,所以看起来模式中的错误在EEEEhh

您的字符串似乎来自过时的java.util.Date 类的toString 方法。要从那里解析字符串,请参阅底部链接的答案之一。或者更好的是,获取Date 对象,使用其toInstant 方法将其转换为现代Instant,然后从那里执行任何进一步的转换。或者更好的是,完全停止使用Date

链接

如何解析来自Date.toString()的结果:

【讨论】:

    【解决方案2】:

    如果您想使用 Zones 进行往返解析/格式化,请尝试

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy",   Locale.US);
        String date = "Wed Nov 18 00:00:00 COT 2020";
        ZonedDateTime localDateTime = ZonedDateTime.parse(date, formatter);
        System.out.println(localDateTime);
        System.out.println(formatter.format(localDateTime));
    

    【讨论】:

    • 谢谢,所以我的错误是我没有使用小时格式的 HH,而且还需要使用 ZonedDateTime?
    • 除非你指定上午/下午
    猜你喜欢
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多