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

使用Java 8 Java.time api解析ISO时间戳(仅标准版),java,datetime,java-8,string-parsing,java-time,Java,Datetime,Java 8,String Parsing,Java Time,在示例中,我无法从字符串中提取历元的毫秒数。到目前为止,我已经尝试了这三种不同的方法,示例显示了最新的尝试。这似乎总是归结为政府不支持。如果我能成功构建Instant的实例,我可以使用 请给出简洁的答案(不要从头开始构造格式化程序),并且只使用Java8标准发行版(我可以用Joda来做,但希望避免依赖性) 编辑:Instant.from在上面的代码中抛出:java.time.DateTimeException:无法从TemporalAccessor获取即时:{OffsetSeconds=-180

在示例中,我无法从字符串中提取历元的毫秒数。到目前为止,我已经尝试了这三种不同的方法,示例显示了最新的尝试。这似乎总是归结为政府不支持。如果我能成功构建Instant的实例,我可以使用

请给出简洁的答案(不要从头开始构造格式化程序),并且只使用Java8标准发行版(我可以用Joda来做,但希望避免依赖性)


编辑:Instant.from在上面的代码中抛出:
java.time.DateTimeException:无法从TemporalAccessor获取即时:{OffsetSeconds=-18000},ISO解析为2014-08-16T05:03:45类型java.time.format.Parsed

,因为无法使用长字符串正确表示即时(他们将API设计为不存在Y 2040问题,当一个long不再足够时),您必须使用两种方法的组合

getEpochSecond()

getNano()


前者得到的是从新纪元开始的秒数,后者得到的是从同一秒开始经过的纳秒数。

Instant.from(creationAccessor).toEpochMili()至少应该根据.is javax.time的参考实现对您进行分类。请留下评论,让我知道这是否对您有效。

这似乎是我在之前的所有测试版本中发现的一个bug,包括
jdk1.8.020b19
,但在最终的
jdk1.8.0_20
中没有发现。这样可以解决问题。我在最新的jdk1.9中也解决了这个问题

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

long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                  .parse(dateStr).getTime();
它还支持获取
即时消息

Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant();
long epochMillis = i.toEpochMilli();
但是,如前所述,一个简单的更新就可以使Java 8代码正常工作。

从Java 8 update 51开始,您的代码正常工作 从Mac OS X Mountain Lion上的Java 8 Update 51开始,您的代码现在就可以正常工作了。您可能已经知道,Java的早期版本中可能存在错误。可以理解,因为Java 8中的Java.time框架是全新的

这是您的代码的修改副本

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" ) );
转储到控制台

System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( "    zdt: " + zdt );
System.out.println("input: " + input );
System.out.println("  zdt: " + zdt );
跑步的时候

dateStr:2014-08-16T05:03:45-05:00
瞬间:2014-08-16T10:03:45Z
米利斯:1408183425000
zdt:2014-08-16T05:03:45-05:00
规范方法:
parse(字符序列文本,临时查询)
您可能希望使用另一种方法完成解析

DateTimeFormatter
的类doc提到通常的解析方法应该是调用而不是调用

因此,与此相反:

String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse( input ) ;
…这样做,我们添加第二个参数,该参数是a,以调用转换
from
方法(在本例中,
ZonedDateTime::from
):

转储到控制台

System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( "    zdt: " + zdt );
System.out.println("input: " + input );
System.out.println("  zdt: " + zdt );
跑步的时候

输入:2007-12-03T10:15:30+01:00[欧洲/巴黎]
zdt:2007-12-03T10:15:30+01:00[欧洲/巴黎]

取决于您希望的准确度。toEpochMillis将起作用,但如文件所述,在未来的某个时候(2040年),这将引发一个异常。让我们希望java仍然存在。到2040年ish,它将有望被javax.DateTimeTwentyThirty8所取代。我越看给定的时间,越怀疑这是一个JDK错误…这两个方法都是Instant上的,我无法获得实例。如果可以,那么Instant#toEpochMilli()答案就是这样。长毫秒值将持续2040年以后。您将其与2038年到期的整数秒值混淆。您发布的代码编译并运行良好。您使用的是什么版本的Java 8?