2016-06-26 33 views
7

日時管理に関するさまざまなコードの組み合わせをJava 8 java.time名前空間にクリーンアップしようとしています。今私はInstantのデフォルトDateTimeFormatterの小さな問題があります。 DateTimeFormatter.ISO_INSTANTフォーマッタは、ゼロに等しくない場合にのみミリ秒を表示します。java.time.DateTimeFormatter:常にミリ秒をレンダリングするISO_INSTANTが必要です

エポックは、1970-01-01T00:00:00.000Zの代わりに1970-01-01T00:00:00Zと表示されます。

私は問題を説明するためにユニットテストを行い、最終的な日付をどのようにして相互に比較する必要があるのですか。

@Test 
public void java8Date() { 
    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; 
    String epoch, almostEpoch, afterEpoch; 

    { // before epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(-1); 
     almostEpoch = formatter.format(instant); 
     assertEquals("1969-12-31T23:59:59.999Z", almostEpoch); 
    } 

    { // epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(0); 
     epoch = formatter.format(instant); 
     // This fails, I get 1970-01-01T00:00:00Z instead 
     assertEquals("1970-01-01T00:00:00.000Z", epoch); 
    } 

    { // after epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(1); 
     afterEpoch = formatter.format(instant); 
     assertEquals("1970-01-01T00:00:00.001Z", afterEpoch); 
    } 

    // The end game is to make sure this rule is respected (this is how we order things in dynamo): 
    assertTrue(epoch.compareTo(almostEpoch) > 0); 
    assertTrue(afterEpoch.compareTo(epoch) > 0); // <-- This assert would also fail if the second assert fails 

    { // to confirm we're not showing nanos 
     assertEquals("1970-01-01T00:00:00.000Z", formatter.format(Instant.EPOCH.plusNanos(1))); 
     assertEquals("1970-01-01T00:00:00.001Z", formatter.format(Instant.EPOCH.plusNanos(1000000))); 
    } 
} 
+3

デフォルトの書式は、ゼロと異なる場合にのみナノ秒をレンダリングします。なぜなら、常にミリ秒(ナノセコンドではない)を使いたいのであれば、 'DateTimeFormatter formatter = DateTimeFormatter.ofPattern(" yyyy-MM-dd'T'HH:mm:ss.SSSX ")のようなカスタムフォーマッタを使わないだけです.Zone(ZoneId ( "UTC"));? – mihi

+0

私は 'Instant :: toString()'で使われたフォーマッタに可能な限り近づきたいと思っていました。たぶん、文字列パターンを使っているはずです。 – Florent

答えて

7

OK、私はソースコードを見て、それは非常に簡単です:

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter(); 

私はそれがすべてのシナリオのために働く期待し、それが他の誰かを助けることができます。もっと良い/きれいな答えを加えるのをためらってください。

ちょうどそれがどこから来るかを説明するには、in the JDK's code

ISO_INSTANTはこのように定義されています

public static final DateTimeFormatter ISO_INSTANT; 
static { 
    ISO_INSTANT = new DateTimeFormatterBuilder() 
      .parseCaseInsensitive() 
      .appendInstant() 
      .toFormatter(ResolverStyle.STRICT, null); 
} 

そしてDateTimeFormatterBuilder::appendInstantのように宣言されています。

public DateTimeFormatterBuilder appendInstant() { 
    appendInternal(new InstantPrinterParser(-2)); 
    return this; 
} 

そしてコンストラクタInstantPrinterParser署名があります:

InstantPrinterParser(int fractionalDigits) 
+1

調べたソースコードにリンクしているといいでしょう。 –

+0

これを変更してナノを含まないmsだけを含むようにする方法 – user1172490

+0

@BasilBourqueソースコードへの参照を追加しました – Florent

0

accepted Answer by Florentは正しくて良いです。

説明を追加したいだけです。

上記のフォーマッタDateTimeFormatter.ISO_INSTANTは、Instantクラスの場合にのみデフォルトです。 OffsetDateTimeおよびZonedDateTimeなどの他のクラスでは、デフォルトで他のフォーマッタを使用することがあります。

java.timeクラスは、nanosecondまでの解像度を提供します。これは、millisecondsよりはるかに細かい粒度です。これは、単に3桁ではなく、小数点以下9桁までを意味します。

DateTimeFormatter.ISO_INSTANTの動作は、小数点以下の桁数によって異なります。ドクターが言うように:

フォーマット時には、2分目が常に出力されます。 nano-of-second は必要に応じて0、3、6、9桁の数字を出力します

のでInstantオブジェクト内に含まれるデータの値に応じて、あなたは、これらの出力のいずれか表示されることがあります。

2011-12-03T10:15:30Z

2011-12-03T10を15:30.100Z

2011-12-03T10:15:30120Z

2011-12-03T10:15:30.123Z

2011-12-03T10:15:30.123400Z

2011-12-03T10:15:30.123456Z

2011-12 -03T10:15:30.123456780Z

2011-12-03T10:15:30.123456789Z

Instantクラスがあることを意味しますjava.timeの基本ビルディングブロック。データの受け渡し、データの格納、データ交換には頻繁に使用してください。ユーザーに提示するためにデータの文字列表現を生成するときは、OffsetDateTimeまたはZonedDateTimeを使用します。

関連する問題