使用 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:33:50  来源:igfitidea点击:

Parse ISO timestamp using Java 8 java.time api (standard edition only)

javadatetimejava-8string-parsingjava-time

提问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_20b19but 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 DateTimeFormattermentions 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 frommethod (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() 应该对你进行排序,至少根据TemporalInstantThreeTen javadocThreeTenjavax.time的参考实现。通过发表评论让我知道这是否适合您。