如何在 Java 中格式化 ISO-8601 字符串?
How to format an ISO-8601 string in Java?
如何将 ISO-8601 字符串 2020-02-10T22:55:13-08:00
格式化为 1:30pm
等自定义格式?我一直收到 unparseable date 异常。我的代码片段如下:
String string = "2020-02-10T22:55:13-08:00";
SimpleDateFormat sdfSource = new SimpleDateFormat("YYYY-MM-DD'T'HH:mm:ss'Z'", Locale.getDefault());
SimpleDateFormat sdfTarget = new SimpleDateFormat("h:mma", Locale.getDefault());
try {
Date date = sdfSource.parse(string);
String createdAt = sdfTarget.format(date);
System.out.println(createdAt);
} catch (ParseException e) {
e.printStackTrace();
}
在 sdfSource
中使用 X(不带引号)代替 'Z'(带引号)。这将解决问题。由于您使用的是引号,因此输入中应包含文字 Z。其次,您需要使用 X 而不是 Z,因为 X 表示 RFC822 时区,这意味着小时和分钟之间没有冒号。您的示例值在小时和分钟之间有冒号。
顺便说一句:您可以切换到 Java 8 中引入的新日期和时间 类,包括它的 parser/formatter。它比 SimpleDateFormat 更通用。它还使用预定义格式处理更多开箱即用的用例,因此您不必创建自己的解析器。 ...就像你现在做的那样。
private String getZonedDateTime(String startTime,String inExpectedTimeZone){
return ZonedDateTime
.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"))
.withZoneSameInstant(ZoneId.of(inExpectedTimeZone)).format(DateTimeFormatter.ofPattern("hh:mm a"));
}
在上面的方法中,只需传递 zulu 字符串和预期时间,您希望在其中使用 java 8 ZonedDateTime 和 DateTimeFormatter 解析它的值。
如果您的 Java 8 或以上,您可以使用 LocalDateTime
,如下所示。
编辑
根据@Andreas 和@OleV.V. 的评论,我想到了4种编译方式,方便参考。其中 2 个使用 OffsetDateTime
,2 个使用 @Sriram 的 ZonedDateTime
答案。另外,根据一个人的开头是字符串还是 LocalDateTime
。
String string = "2020-02-10T22:55:13-08:00";
DateTimeFormatter inF = DateTimeFormatter.ISO_DATE_TIME;
String desiredZoneId = "Z";
int desiredOffset = 0;
DateTimeFormatter toF = DateTimeFormatter.ofPattern( "h:mm a" );
LocalDateTime ldt = LocalDateTime.parse(string.trim(), inF );
/* Prints -> "ldt.atOffset: 6:55 AM" */
/* 1. If one already has a LocalDateTime. Drawback: One needs to know the offset in the time string. */
System.out.println( "ldt.atOffset: " + ldt.atOffset( ZoneOffset.ofHours( -8 ) ).withOffsetSameInstant( ZoneOffset.ofHours( desiredOffset ) ).format( toF ) );
/* Prints -> "ldt.atZone: 6:55 AM" */
/* 2. If one already has a LocalDateTime. Drawback: One needs to know the offset in the time string. */
System.out.println( "ldt.atZone: " + ldt.atZone( ZoneId.of( "-08:00" ) ).withZoneSameInstant( ZoneId.of( desiredZoneId ) ).format( toF ) );
/* Prints -> "odt: 6:55 AM" */
/* 3. Using OffsetDateTime. */
OffsetDateTime odt = OffsetDateTime.parse( string, inF );
System.out.println( "odt: " + odt.withOffsetSameInstant( ZoneOffset.ofHours( desiredOffset ) ).format( toF ) );
/* Prints -> "zdt: 6:55 AM" */
/* 4. Using ZonedDateTime. */
String zdt = ZonedDateTime.parse( string, DateTimeFormatter.ISO_DATE_TIME )
.withZoneSameInstant( ZoneId.of( desiredZoneId ) ).format( toF );
System.out.println( "zdt: " + zdt );
如何将 ISO-8601 字符串 2020-02-10T22:55:13-08:00
格式化为 1:30pm
等自定义格式?我一直收到 unparseable date 异常。我的代码片段如下:
String string = "2020-02-10T22:55:13-08:00";
SimpleDateFormat sdfSource = new SimpleDateFormat("YYYY-MM-DD'T'HH:mm:ss'Z'", Locale.getDefault());
SimpleDateFormat sdfTarget = new SimpleDateFormat("h:mma", Locale.getDefault());
try {
Date date = sdfSource.parse(string);
String createdAt = sdfTarget.format(date);
System.out.println(createdAt);
} catch (ParseException e) {
e.printStackTrace();
}
在 sdfSource
中使用 X(不带引号)代替 'Z'(带引号)。这将解决问题。由于您使用的是引号,因此输入中应包含文字 Z。其次,您需要使用 X 而不是 Z,因为 X 表示 RFC822 时区,这意味着小时和分钟之间没有冒号。您的示例值在小时和分钟之间有冒号。
顺便说一句:您可以切换到 Java 8 中引入的新日期和时间 类,包括它的 parser/formatter。它比 SimpleDateFormat 更通用。它还使用预定义格式处理更多开箱即用的用例,因此您不必创建自己的解析器。 ...就像你现在做的那样。
private String getZonedDateTime(String startTime,String inExpectedTimeZone){
return ZonedDateTime
.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"))
.withZoneSameInstant(ZoneId.of(inExpectedTimeZone)).format(DateTimeFormatter.ofPattern("hh:mm a"));
}
在上面的方法中,只需传递 zulu 字符串和预期时间,您希望在其中使用 java 8 ZonedDateTime 和 DateTimeFormatter 解析它的值。
如果您的 Java 8 或以上,您可以使用 LocalDateTime
,如下所示。
编辑
根据@Andreas 和@OleV.V. 的评论,我想到了4种编译方式,方便参考。其中 2 个使用 OffsetDateTime
,2 个使用 @Sriram 的 ZonedDateTime
答案。另外,根据一个人的开头是字符串还是 LocalDateTime
。
String string = "2020-02-10T22:55:13-08:00";
DateTimeFormatter inF = DateTimeFormatter.ISO_DATE_TIME;
String desiredZoneId = "Z";
int desiredOffset = 0;
DateTimeFormatter toF = DateTimeFormatter.ofPattern( "h:mm a" );
LocalDateTime ldt = LocalDateTime.parse(string.trim(), inF );
/* Prints -> "ldt.atOffset: 6:55 AM" */
/* 1. If one already has a LocalDateTime. Drawback: One needs to know the offset in the time string. */
System.out.println( "ldt.atOffset: " + ldt.atOffset( ZoneOffset.ofHours( -8 ) ).withOffsetSameInstant( ZoneOffset.ofHours( desiredOffset ) ).format( toF ) );
/* Prints -> "ldt.atZone: 6:55 AM" */
/* 2. If one already has a LocalDateTime. Drawback: One needs to know the offset in the time string. */
System.out.println( "ldt.atZone: " + ldt.atZone( ZoneId.of( "-08:00" ) ).withZoneSameInstant( ZoneId.of( desiredZoneId ) ).format( toF ) );
/* Prints -> "odt: 6:55 AM" */
/* 3. Using OffsetDateTime. */
OffsetDateTime odt = OffsetDateTime.parse( string, inF );
System.out.println( "odt: " + odt.withOffsetSameInstant( ZoneOffset.ofHours( desiredOffset ) ).format( toF ) );
/* Prints -> "zdt: 6:55 AM" */
/* 4. Using ZonedDateTime. */
String zdt = ZonedDateTime.parse( string, DateTimeFormatter.ISO_DATE_TIME )
.withZoneSameInstant( ZoneId.of( desiredZoneId ) ).format( toF );
System.out.println( "zdt: " + zdt );