web-dev-qa-db-ja.com

Java 8 Java.time api(標準版のみ)を使用してISOタイムスタンプを解析します

例の文字列からエポックからミリ秒を取得するのに問題があります。私はこれまでにこの3つの異なる方法を試しましたが、例は最新の試みを示しています。 TemporalAccessorChronoField をサポートしていないことに常になりそうです。 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

13
Travis Wellman

これは、jdk1.8.0_20b19を含む以前のすべてのテスト済みバージョンで見つかったバグのようですが、最終的なjdk1.8.0_20では見つかりませんでした。したがって、 最新のjdkバージョンをダウンロードする で問題が解決します。最新のjdk1.9でも解決されています。

古き良きJava7の方法は、すべてのバージョンで機能することに注意してください。

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();

ただし、前述のように、簡単な更新でJava8コードが機能します。

10
Holger

コードは機能します、現在Java 8 Update 51

Java 8 Mac OS X Mountain Lionのアップデート51)の時点で、コードは現在機能しています。 Answer by Holger 以前のバージョンの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, 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 ) ;
_

…これを行うには、2番目の引数を追加します。引数は メソッド参照in 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 ) ;
_

コンソールにダンプします。

_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]
_
11
Basil Bourque

Instant.from(creationAccessor).toEpochMili()は、少なくとも TemporalInstantのThreeTen javadoc に従ってソートする必要があります。 ThreeTen はjavax.timeのリファレンス実装です。コメントを残して、これがうまくいくかどうか教えてください。

0
hd1

インスタントはlongを使用して適切に表現できないため(longでは不十分な場合にY 2040の問題が発生しないようにAPIを設計している)、2つの方法を組み合わせて使用​​する必要があります

getEpochSecond()

そして

getNano()

前者はエポックからの秒数を取得し、後者は同じ秒から経過したナノ秒数を取得します。

0
Matt