如何将 UTC 偏移日期格式字符串解析为由 | 分隔的结果日期象征
How to parse a UTC offset dateformat string into the resulting date separated by | symbol
我有一个非常奇怪的问题,我正在尝试解析 "2019-12-25T17:00:00-05:00"
这样它应该给我结果 DEC 12 | Thursday | 5:00pm
我使用 DateTimeFormatter
和 LocalDate
尝试了以下代码
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
时崩溃
知道它崩溃的原因以及我的输出是否会呈现预期的结果吗?
谢谢!
您的字符串 2019-12-25T17:00:00-05:00
表示 UTC
时区偏移量 UTC offset,因此使用 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
for eaxmple
ZoneId zone = ZoneId.of("America/Chicago");
ZonedDateTime zdt = odt.atZoneSameInstant(zone);
一种格式化大写 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 | Wed | 05:00 pm
我假设您在 API 级别 26 下为 Android 编程并使用 ThreeTenABP,所以我已经在我的桌面 Java 7 上使用 ThreeTen Backport 进行了测试。从 Java 8 级到更新的 API 级,甚至从 Java 级开始,存在 9 种更优雅的填充两张地图的方法。
你的代码出了什么问题?
格式模式字符串中最后出现的小写 z
与 时区名称 匹配。该文档提供了太平洋标准时间和太平洋标准时间的示例。它不匹配 -05:00
这样的偏移量。如果您为此需要格式模式字母,请使用 x
、X
或大写 Z
(它们不同并且都有详细记录)。但是,正如 Deadpool 的回答中所示,在这种情况下您不需要显式格式化程序和格式模式字符串。
您的代码中的另一个问题:您在问题中使用的 LocalDate
class 是没有时间的日期。您可以将字符串解析为 LocalDate
,但时间和偏移量会丢失。因此,您不能将 LocalDate
格式化为包含一天中的时间的字符串。为此,您需要一个名称中包含 DateTime
的 class,例如两个答案中使用的 OffsetDateTime
。
Link
DateTimeFormatter
documentation 拼出所有可能的格式模式字母。
我有一个非常奇怪的问题,我正在尝试解析 "2019-12-25T17:00:00-05:00"
这样它应该给我结果 DEC 12 | Thursday | 5:00pm
我使用 DateTimeFormatter
和 LocalDate
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
知道它崩溃的原因以及我的输出是否会呈现预期的结果吗? 谢谢!
您的字符串 2019-12-25T17:00:00-05:00
表示 UTC
时区偏移量 UTC offset,因此使用 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
for eaxmple
ZoneId zone = ZoneId.of("America/Chicago");
ZonedDateTime zdt = odt.atZoneSameInstant(zone);
一种格式化大写 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 | Wed | 05:00 pm
我假设您在 API 级别 26 下为 Android 编程并使用 ThreeTenABP,所以我已经在我的桌面 Java 7 上使用 ThreeTen Backport 进行了测试。从 Java 8 级到更新的 API 级,甚至从 Java 级开始,存在 9 种更优雅的填充两张地图的方法。
你的代码出了什么问题?
格式模式字符串中最后出现的小写 z
与 时区名称 匹配。该文档提供了太平洋标准时间和太平洋标准时间的示例。它不匹配 -05:00
这样的偏移量。如果您为此需要格式模式字母,请使用 x
、X
或大写 Z
(它们不同并且都有详细记录)。但是,正如 Deadpool 的回答中所示,在这种情况下您不需要显式格式化程序和格式模式字符串。
您的代码中的另一个问题:您在问题中使用的 LocalDate
class 是没有时间的日期。您可以将字符串解析为 LocalDate
,但时间和偏移量会丢失。因此,您不能将 LocalDate
格式化为包含一天中的时间的字符串。为此,您需要一个名称中包含 DateTime
的 class,例如两个答案中使用的 OffsetDateTime
。
Link
DateTimeFormatter
documentation 拼出所有可能的格式模式字母。