使用 Java 8 java.time api 解析 ISO 时间戳(仅限标准版)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25735583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Parse ISO timestamp using Java 8 java.time api (standard edition only)
提问by Travis Wellman
I'm having trouble getting milliseconds from the epoch out of the string in the example. I have tried this three different ways so far, and the example shows the latest attempt. It always seems to come down to that the TemporalAccessordoes not support ChronoField. If I could successfully construct an instance of Instant, I could use toEpochMilli().
我无法从示例中的字符串中获取纪元的毫秒数。到目前为止,我已经尝试了这三种不同的方法,示例显示了最新的尝试。似乎总是归结为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);
Please give concise answers (don't construct a formatter from scratch) and use only the java 8 standard distribution (I can do it with Joda, but want to avoid dependencies).
请给出简洁的答案(不要从头开始构建格式化程序)并仅使用 java 8 标准发行版(我可以使用 Joda 来完成,但想避免依赖)。
Edit:Instant.from in the code above throws: 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
编辑:上面代码中的 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
采纳答案by Holger
This seems to be a bug which I found in all tested versions before and including jdk1.8.0_20b19
but not in the final jdk1.8.0_20
. So downloading an up-to-date jdk versionwould solve the problem. It's also solved in the most recent jdk1.9.
这似乎是我在之前所有测试过的版本中发现的一个错误,包括jdk1.8.0_20b19
但不是在最终的jdk1.8.0_20
. 所以下载一个最新的jdk版本就可以解决这个问题。最近的jdk1.9也解决了。
Note that the good old Java?7 way works in all versions:
请注意,旧的 Java?7 方式适用于所有版本:
long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
.parse(dateStr).getTime();
It also supports getting an Instant
:
它还支持获取Instant
:
Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant();
long epochMillis = i.toEpochMilli();
But, as said, a simple update makes your Java?8 code working.
但是,如上所述,一个简单的更新就可以使您的 Java?8 代码正常工作。
回答by Basil Bourque
Your Code Works, As Of Java 8 Update 51
从 Java 8 Update 51 开始,您的代码有效
Your code is working now, as of Java 8 Update 51 on Mac OS X Mountain Lion. The Answerby Holgerthat there may have been a bug in earlier versions of Java. Understandable as the java.time framework is brand-new in Java 8.
从 Mac OS X Mountain Lion 上的 Java 8 Update 51 开始,您的代码现在正在运行。Holger的回答,即早期版本的 Java 中可能存在错误。可以理解,因为 java.time 框架在 Java 8 中是全新的。
Here is a modified copy of your code.
这是您的代码的修改副本。
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" ) );
Dump to console.
转储到控制台。
System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( " zdt: " + zdt );
When run.
跑的时候。
dateStr: 2014-08-16T05:03:45-05:00
instant: 2014-08-16T10:03:45Z
millis: 1408183425000
zdt: 2014-08-16T05:03:45-05:00
Canonical Method:
parse(CharSequence text, TemporalQuery<T> query)
规范方法:
parse(CharSequence text, TemporalQuery<T> query)
You may want to accomplish your parsing using an alternate method.
您可能希望使用替代方法完成解析。
The class doc for DateTimeFormatter
mentions that the usual way to parse should be a call to DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query)
rather than DateTimeFormatter::parse(CharSequence text)
.
类文档 forDateTimeFormatter
提到通常的解析方法应该是调用DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query)
而不是DateTimeFormatter::parse(CharSequence text)
.
So instead of this:
所以而不是这个:
String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse( input ) ;
…do this, where we add a second argument, the argument being a method reference in Java 8 syntax, to call the conversion from
method (in this example, ZonedDateTime :: from
):
...这样做,我们添加第二个参数,该参数是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 ) ;
Dump to console.
转储到控制台。
System.out.println("input: " + input );
System.out.println(" zdt: " + zdt );
When run.
跑的时候。
input: 2007-12-03T10:15:30+01:00[Europe/Paris]
zdt: 2007-12-03T10:15:30+01:00[Europe/Paris]
回答by Matt
Since instant can't properly be represented using a long (they've designed the API to not have Y 2040 issues, when a long is no longer sufficient), you have to use a combination of two methods
由于无法使用 long 正确表示即时(他们将 API 设计为没有 Y 2040 问题,当 long 不再足够时),您必须使用两种方法的组合
getEpochSecond()
getEpochSecond()
and
和
getNano()
获取纳米()
The former gets you the # of seconds from epoch, and the latter gives you the # of nanoseconds that have passed since that same second.
前者为您提供从 epoch 开始的秒数,后者为您提供自同一秒以来经过的纳秒数。
回答by hd1
Instant.from(creationAccessor).toEpochMili() should sort you, at least according to the ThreeTen javadoc for TemporalInstant. ThreeTenis the reference implementation of javax.time. Let me know if this works for you or not by leaving a comment.
Instant.from(creationAccessor).toEpochMili() 应该对你进行排序,至少根据TemporalInstant的ThreeTen javadoc。ThreeTen是javax.time的参考实现。通过发表评论让我知道这是否适合您。