如何将UTC偏移量dateformat字符串解析为以|分隔的结果日期符号

时间:2019-07-24 01:56:17

标签: java android datetime-format java-time java-date

我有一个非常特殊的问题,我想在哪里解析"2019-12-25T17:00:00-05:00" 这样它应该给我结果DEC 12 | Thursday | 5:00pm

我通过使用DateTimeFormatterLocalDate

尝试了以下代码
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssz", Locale.US);
                DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("MM d | E | hh:mm a", Locale.US);
                LocalDate date = LocalDate.parse("2019-12-25T17:00:00-05:00", inputFormatter);
                String formattedDate = outputFormatter.format(date);
                contentTextView.setText(formattedDate);

但它因DateTimeParseException: Text '2019-12-25T17:00:00-05:00' could not be parsed at index 19

而崩溃

有人知道它为什么崩溃以及我的输出是否可以提供预期的结果? 谢谢!

2 个答案:

答案 0 :(得分:7)

您的字符串2019-12-25T17:00:00-05:00代表具有偏移UTC offsetUTC时区,因此请使用OffsetDateTime来解析该字符串

OffsetDateTime odt = OffsetDateTime.parse("2019-12-25T17:00:00-05:00");

System.out.println(odt.format(DateTimeFormatter.ofPattern("MMM d | E | hh:mm a", Locale.US)));

如果您想设置特定的时区,则可以使用atZoneSameInstant传递ZoneId来进行扩展

ZoneId zone = ZoneId.of("America/Chicago");
ZonedDateTime zdt = odt.atZoneSameInstant(zone);

答案 1 :(得分:4)

格式化大写DEC和小写pm的方法

我只是对@Deadpool的良好回答进行一些补充。在所有DEC和小写的am / pm中使用大写形式的月份缩写的一种方法是DateTimeFormatterBuilder及其两个参数appendText​(TemporalField, Map<Long,String>)

    Locale userLocale = Locale.US;
    Map<Long, String> monthNames = new HashMap<>();
    for (Month m : Month.values()) {
        monthNames.put(Long.valueOf(m.getValue()),
                m.getDisplayName(TextStyle.SHORT, userLocale).toUpperCase(userLocale));
    }
    Map<Long, String> amPmNames = new HashMap<>(3);
    amPmNames.put(0L, "am");
    amPmNames.put(1L, "pm");
    DateTimeFormatter outputFormatter = new DateTimeFormatterBuilder()
            .appendText(ChronoField.MONTH_OF_YEAR, monthNames)
            .appendPattern(" d | E | hh:mm ")
            .appendText(ChronoField.AMPM_OF_DAY, amPmNames)
            .toFormatter(userLocale);

    OffsetDateTime odt = OffsetDateTime.parse("2019-12-25T17:00:00-05:00");
    String formattedDate = odt.format(outputFormatter);
    System.out.println(formattedDate);

输出:

  

DEC 25 |周三|下午05:00

我假设您正在使用API​​级别26在Android上进行编程并使用ThreeTenABP,所以我已经在具有ThreeTen Backport的台式机Java 7上进行了测试。从Java 8开始,在更新的API级别上,从Java 9甚至更多,都存在用于填充两个映射的更优雅的方法。

您的代码出了什么问题?

在格式模式字符串中排在最后的小写z时区名称匹配。该文档提供了太平洋标准时间和PST的示例。它与-05:00之类的偏移量不匹配。如果您需要格式字母,请使用xX或大写的Z(它们是不同的,并且都有据可查)。但是,正如Deadpool的答案中已经显示的那样,在这种情况下,您不需要显式的格式化程序,也不需要格式化模式字符串。

代码中的另一个问题:您在问题中使用的LocalDate类是没有时间的日期。您可以将字符串解析为LocalDate,但是一天中的时间和偏移量会丢失。因此,您无法将LocalDate格式化为包含一天中的时间的字符串。为此,您需要一个名称为DateTime的类,例如两个答案中使用的OffsetDateTime

链接

DateTimeFormatter documentation拼写所有可能的格式模式字母。