使用Java 8 java.time api解析ISO时间戳(仅限标准版)

Tra*_*man 13 java datetime string-parsing java-8 java-time

我在例子中从字符串中获取毫秒数时遇到麻烦.到目前为止,我已经尝试了这三种不同的方式,示例显示了最新的尝试.似乎总是认为TemporalAccessor不支持ChronoField.如果我可以成功构建一个Instant实例,我可以使用toEpochMilli().

String dateStr = "2014-08-16T05:03:45-05:00"
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(dateStr);
Instant creationDate = Instant.from(creationAccessor);
Run Code Online (Sandbox Code Playgroud)

请提供简明的答案(不要从头开始构建格式化程序)并仅使用java 8标准发行版(我可以使用Joda,但希望避免依赖项).

编辑:上面代码中的Instant.from抛出:java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {OffsetSeconds=-18000},ISO resolved to 2014-08-16T05:03:45 of type java.time.format.Parsed

Hol*_*ger 10

这似乎是我在所有测试版本中发现的错误,包括jdk1.8.0_20b19但不包括在最终版本中jdk1.8.0_20.因此,下载最新的jdk版本可以解决问题.它也在最近的jdk1.9中得到了解决.

请注意,旧的Java 7方式适用于所有版本:

long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                  .parse(dateStr).getTime();
Run Code Online (Sandbox Code Playgroud)

它还支持获得Instant:

Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant();
long epochMillis = i.toEpochMilli();
Run Code Online (Sandbox Code Playgroud)

但是,如上所述,简单的更新使您的Java 8代码正常工作.


Bas*_*que 10

您的代码适用于Java 8 Update 51

从Mac OS X Mountain Lion上的Java 8 Update 51开始,您的代码现在正在运行.在回答霍尔格有可能已经在早期版本的Java中的错误.可以理解,因为java.time框架在Java 8中是全新的.

以下是代码的修改副本.

String dateStr = "2014-08-16T05:03:45-05:00";
TemporalAccessor creationAccessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse( dateStr );
Instant instant = Instant.from( creationAccessor );
long millisSinceEpoch = instant.toEpochMilli( );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant, ZoneOffset.of( "-05:00" ) );
Run Code Online (Sandbox Code Playgroud)

转储到控制台.

System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( "    zdt: " + zdt );
Run Code Online (Sandbox Code Playgroud)

跑步时

dateStr: 2014-08-16T05:03:45-05:00
instant: 2014-08-16T10:03:45Z
 millis: 1408183425000
    zdt: 2014-08-16T05:03:45-05:00
Run Code Online (Sandbox Code Playgroud)

规范方法:
parse(CharSequence text, TemporalQuery<T> query)

您可能希望使用备用方法完成解析.

类doc DateTimeFormatter提到通常的解析方法应该是调用DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query)而不是DateTimeFormatter::parse(CharSequence text).

所以不是这样的:

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse( input ) ;
Run Code Online (Sandbox Code Playgroud)

...执行此操作,我们添加第二个参数,该参数是Java 8语法中方法引用,以调用转换from方法(在此示例中ZonedDateTime :: from):

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
ZonedDateTime zdt = DateTimeFormatter.ISO_DATE_TIME.parse( input , ZonedDateTime :: from ) ;
Run Code Online (Sandbox Code Playgroud)

转储到控制台.

System.out.println("input: " + input );
System.out.println("  zdt: " + zdt );
Run Code Online (Sandbox Code Playgroud)

跑步时

input: 2007-12-03T10:15:30+01:00[Europe/Paris]
  zdt: 2007-12-03T10:15:30+01:00[Europe/Paris]
Run Code Online (Sandbox Code Playgroud)