【问题标题】:Problem with convert String to LocalDateTime将字符串转换为 LocalDateTime 的问题
【发布时间】:2021-05-28 05:45:18
【问题描述】:

当我运行它时,我得到了异常: 线程“主”java.time.format.DateTimeParseException 中的异常:无法解析文本“2020-12-15 13:48:52”:ClockHourOfAmPm 的值无效(有效值

我写信给控制台:2020-12-15 13:48:52

public class Main {
    public static void main(String[] args) {


        Scanner scanner = new Scanner(System.in);
        System.out.println("Podaj datę:");
        String input = scanner.nextLine();


        if (input.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
            DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
            LocalDateTime localDateTime = LocalDateTime.parse(input, dateTimeFormatter1);
            printDateTime(localDateTime);
        } else if (input.matches("\\d{2}.\\d{2}.\\d{4} \\d{2}:\\d{2}:\\d{2}")) {
            DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm:ss");
            LocalDateTime localDateTime2 = LocalDateTime.parse(input, dateTimeFormatter2);
            printDateTime(localDateTime2);
        } else if (input.matches("\\d{4}-\\d{2}-\\d{2}")) {
            DateTimeFormatter dateTimeFormatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDateTime localDateTime3 = LocalDateTime.parse(input, dateTimeFormatter3);
            printDateTime(localDateTime3);
        } else {
            System.out.println("Zły format");
        }
    }

    private static void printDateTime(LocalDateTime localDateTime) {
        System.out.println("Czas lokalny: " + ZonedDateTime.now());
        System.out.println("UTC: " + ZonedDateTime.of(localDateTime, ZoneId.of("UTC")));
        System.out.println("Londyn: " + ZonedDateTime.of(localDateTime, ZoneId.of("London")));
        System.out.println("Los Angeles: " + ZonedDateTime.of(localDateTime, ZoneId.of("Los Angeles")));
        System.out.println("Sydney: " + ZonedDateTime.of(localDateTime, ZoneId.of("Sydney")));
    }
}

【问题讨论】:

  • 使用 HH 代替 hh。此外,伦敦不是有效的 ZondId
  • 或者:LocalDateTime.parse( "2020-12-15 13:48:52".replace( " " , "T" ) ) 将中间的空格替换为T,以符合 java.time 中默认使用的标准 ISO 8601 格式。

标签: java datetime java-time zoneddatetime datetimeformatter


【解决方案1】:

DateTimeFormatter 中的 DateTime 模式会导致您在此处看到的问题。您需要使用HH 而不是hh

  • hh:这是一个小时模式,使用 12 小时制,带有 AM/PM 指示。
  • HH:这是一个使用 24 小时制的小时模式。接受 0-23 之间的输入

旁注,您使用的区域似乎无效。 相应的区域将是

Europe/London
America/Los_Angeles
Australia/Sydney

【讨论】:

    【解决方案2】:

    对于这个要求,不要使用正则表达式,因为它会使你的程序变得不必要的复杂和容易出错。您可以将方括号中的可选模式与DateTimeFormatter 一起使用。除此之外,

    1. 使用DateTimeFormatterBuilder#parseDefaulting 将字段的默认值(例如HOUR_OF_DAY)附加到格式化程序以用于解析。
    2. 使用ZonedDateTime#withZoneSameInstant 以不同的时区返回此日期时间的副本,保留瞬间。
    3. 使用时区的标准命名约定(地区/城市),例如Europe/London
    4. 使用HH 而不是hh 来表示HOUR_OF_DAY(即24 小时格式的时间)。符号 hh 与指定 am/pma 一起使用(即 12 小时格式的时间)。

    演示:

    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.time.temporal.ChronoField;
    import java.util.Locale;
    import java.util.Scanner;
    
    class Main {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                    .appendPattern("[uuuu-MM-dd HH:mm:ss][dd.MM.uuuu HH:mm:ss][uuuu-MM-dd]")
                    .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
                    .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
                    .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
                    .toFormatter(Locale.ENGLISH);
    
            System.out.print("Podaj datę:");
            String input = scanner.nextLine();
            LocalDateTime localDateTime = LocalDateTime.parse(input, dtf);
            System.out.println(localDateTime);
    
            printDateTime(LocalDateTime.parse(input, dtf));
        }
    
        private static void printDateTime(LocalDateTime localDateTime) {
            // Default timezone
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zdtDefaultTimeZone = localDateTime.atZone(zoneId);
    
            System.out
                    .println("Date-time at " + zoneId + ": " + zdtDefaultTimeZone);
            System.out.println("At UTC: " + zdtDefaultTimeZone.withZoneSameInstant(ZoneId.of("Etc/UTC")));
            System.out.println("In London: " + zdtDefaultTimeZone.withZoneSameInstant(ZoneId.of("Europe/London")));
            System.out
                    .println("In Los Angeles: " + zdtDefaultTimeZone.withZoneSameInstant(ZoneId.of("America/Los_Angeles")));
            System.out.println("In Sydney: " + zdtDefaultTimeZone.withZoneSameInstant(ZoneId.of("Australia/Sydney")));
        }
    }
    

    示例运行:

    Podaj datę:2020-02-23 10:15:20
    2020-02-23T10:15:20
    Date-time at Europe/London: 2020-02-23T10:15:20Z[Europe/London]
    At UTC: 2020-02-23T10:15:20Z[Etc/UTC]
    In London: 2020-02-23T10:15:20Z[Europe/London]
    In Los Angeles: 2020-02-23T02:15:20-08:00[America/Los_Angeles]
    In Sydney: 2020-02-23T21:15:20+11:00[Australia/Sydney]
    

    另一个示例运行:

    Podaj datę:23.02.2020 10:15:20
    2020-02-23T10:15:20
    Date-time at Europe/London: 2020-02-23T10:15:20Z[Europe/London]
    At UTC: 2020-02-23T10:15:20Z[Etc/UTC]
    In London: 2020-02-23T10:15:20Z[Europe/London]
    In Los Angeles: 2020-02-23T02:15:20-08:00[America/Los_Angeles]
    In Sydney: 2020-02-23T21:15:20+11:00[Australia/Sydney]
    

    另一个示例运行:

    Podaj datę:2020-02-23
    2020-02-23T00:00
    Date-time at Europe/London: 2020-02-23T00:00Z[Europe/London]
    At UTC: 2020-02-23T00:00Z[Etc/UTC]
    In London: 2020-02-23T00:00Z[Europe/London]
    In Los Angeles: 2020-02-22T16:00-08:00[America/Los_Angeles]
    In Sydney: 2020-02-23T11:00+11:00[Australia/Sydney]
    

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

    【讨论】:

      猜你喜欢
      • 2019-11-27
      • 2019-08-07
      • 1970-01-01
      • 2021-01-20
      • 2017-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多