我在例子中从字符串中获取毫秒数时遇到了麻烦。到目前为止,我已尝试过这三种不同的方法,示例显示了最新的尝试。似乎总是归结为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);
请提供简明的答案(不要从头开始构建格式化程序)并仅使用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
答案 0 :(得分:10)
这似乎是我在所有测试版本中发现的错误,包括jdk1.8.0_20b19
,但不包括在最终的jdk1.8.0_20
中。所以downloading an up-to-date jdk version可以解决问题。它也在最近的jdk1.9中得到了解决。
请注意,旧的Java 7方式适用于所有版本:
long epochMillis = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
.parse(dateStr).getTime();
它还支持获取Instant
:
Instant i=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(dateStr).toInstant();
long epochMillis = i.toEpochMilli();
但是,如上所述,一个简单的更新使您的Java 8代码正常工作。
答案 1 :(得分:7)
您的代码现在正在运行,从Mac OS X Mountain Lion上的Java 8 Update 51开始。 Answer Holger DateTimeFormatter::parse(CharSequence text, TemporalQuery<T> query)
早期版本的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" ) );
转储到控制台。
System.out.println( "dateStr: " + dateStr );
System.out.println( "instant: " + instant );
System.out.println( " millis: " + millisSinceEpoch );
System.out.println( " zdt: " + zdt );
跑步时。
dateStr: 2014-08-16T05:03:45-05:00
instant: 2014-08-16T10:03:45Z
millis: 1408183425000
zdt: 2014-08-16T05:03:45-05:00
parse(CharSequence text, TemporalQuery<T> query)
您可能希望使用其他方法完成解析。
DateTimeFormatter
的班级文档提到,通常的解析方法应该是调用DateTimeFormatter::parse(CharSequence text)
而不是method reference in Java 8 syntax。
所以不要这样:
String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_DATE_TIME.parse( input ) ;
...这样做,我们添加第二个参数,参数为tutorial,以调用转换from
方法(在此示例中为ZonedDateTime :: from
):
String input = "2007-12-03T10:15:30+01:00[Europe/Paris]" ;
ZonedDateTime zdt = DateTimeFormatter.ISO_DATE_TIME.parse( input , ZonedDateTime :: from ) ;
转储到控制台。
System.out.println("input: " + input );
System.out.println(" zdt: " + zdt );
跑步时。
input: 2007-12-03T10:15:30+01:00[Europe/Paris]
zdt: 2007-12-03T10:15:30+01:00[Europe/Paris]
答案 2 :(得分:0)
由于即时无法使用long来表示(他们设计的API没有Y 2040问题,当长度不再足够时),你必须使用两种方法的组合
getEpochSecond()
和
getNano()
前者从epoch获得秒数,后者为您提供自同一秒后经过的纳秒数。
答案 3 :(得分:0)
Instant.from(creationAccessor).toEpochMili()应该排序你,至少根据ThreeTen javadoc for TemporalInstant。 ThreeTen是javax.time的参考实现。通过发表评论,让我知道这是否适合你。