インスタントを文字列にフォーマット


227

新しいjava 8 time-apiとパターンを使用して、インスタントを文字列にフォーマットしようとしています:

Instant instant = ...;
String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(instant);

上記のコードを使用すると、サポートされていないフィールドに問題があるという例外が発生します。

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
    at java.time.Instant.getLong(Instant.java:608)
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
    ...

回答:


310

タイムゾーン

タイムゾーンをフォーマットするにInstant必要です。タイムゾーンがないと、フォーマッタはインスタントを人間の日時フィールドに変換する方法がわからないため、例外がスローされます。

を使用して、タイムゾーンを直接フォーマッタに追加できますwithZone()

DateTimeFormatter formatter =
    DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT )
                     .withLocale( Locale.UK )
                     .withZone( ZoneId.systemDefault() );

文字列の生成

次に、そのフォーマッターを使用して、インスタントの文字列表現を生成します。

Instant instant = Instant.now();
String output = formatter.format( instant );

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

System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );

実行すると。

formatter: Localized(SHORT,SHORT) with zone: US/Pacific and Locale: en_GB
instant: 2015-06-02T21:34:33.616Z
output: 02/06/15 14:34

51
ありがとうございました!!ところで、たとえば年を指す「サポートされていないフィールド」という例外は、目を見張るほど鈍いものです。たぶんこの状況が検出され、インスタントで欠落しているゾーンIDを直接指している例外がスローされるはずです!
davidbak 2015年

1
さらに奇妙なことに、.withZone(たとえば、.withZone(ZoneId.of( "Z")))を含めてLocalDateTimeをフォーマットすると、ゾーンは無視されます。そのため、.withZone()が含まれている限り、インスタントとLocalDateTimeの両方に同じフォーマッタを使用でき、後者の表示時間に影響を与えません。
Glenn

1
InstantがGMTであるTimeZoneを持っているという事実を受け入れることがなぜそれほど難しいのですか?
Koray Tugay

1
@KorayTugay詳細な「インスタントはすでにGMT」のコメントは真実かもしれないが、タイムゾーンを指定せずにインスタントフォーマットすると機能しないため、スローされる例外トレースに直面した場合、コメントは役に立ちません。フォーマッタがデフォルトでGMTに設定されていれば良かったのですが、まあ。
Ti Strga

さて、これはあなたに与えられるyyyy-MM-dd hh:mm:ss形式を:DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss").withZone(ZoneId.of("Europe/Paris"));
WesternGun

39
public static void main(String[] args) {

    DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            .withZone(ZoneId.systemDefault());

    System.out.println(DATE_TIME_FORMATTER.format(new Date().toInstant()));

}

3
このコードは質問に答えることがありますが、問題を解決する方法理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
アレクサンダー

1
このコードスニペットは問題を解決する可能性がありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
ロザリオペレイラフェルナンデス

23
DateTimeFormatter.ISO_INSTANT.format(Instant.now())

これにより、UTCに変換する必要がなくなります。ただし、他の一部の言語の時間フレームワークではミリ秒がサポートされていない場合があるので、

DateTimeFormatter.ISO_INSTANT.format(Instant.now().truncatedTo(ChronoUnit.SECONDS))

「他の言語の時間フレームワーク」とはどういう意味ですか?ISO_INSTANT.format()は自動的に秒に切り捨てられますか?
Guangtong Shen

一部のフレームワークは、ISOの完全な規則に従っていないため、秒までの時間しか期待せず、入力文字列の一部としてミリ秒がある場合は中断します。
アルキメデストラハノ

21

このInstantクラスにはゾーン情報が含まれていません。UNIXエポックからのミリ秒単位のタイムスタンプ(つまり、UTCからの1070年1月1日)のみが格納されています。したがって、日付は常に具体的なタイムゾーンで出力されるため、フォーマッタは日付を出力できません。タイムゾーンをフォーマッタに設定する必要があります。すべて、次のように問題ありません。

Instant instant = Instant.ofEpochMilli(92554380000L);
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.UK).withZone(ZoneOffset.UTC);
assert formatter.format(instant).equals("07/12/72 05:33");
assert instant.toString().equals("1972-12-07T05:33:00Z");

4

または、パターンから作成されたフォーマッタを引き続き使用する場合は、Instantの代わりにLocalDateTimeを使用できます。

LocalDateTime datetime = LocalDateTime.now();
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(datetime)

4

インスタントはすでにUTCであり、デフォルトの日付形式はyyyy-MM-ddです。これに満足していて、タイムゾーンやフォーマットを変更したくない場合は、次のようにすることもできますtoString()

Instant instant = Instant.now();
instant.toString()
output: 2020-02-06T18:01:55.648475Z


TとZが必要ですか?(Zはこの日付がUTCであることを示します。Zは「Zulu」または「ゼロ時間オフセット」またはUTCを表します):

instant.toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.663763


ナノ秒ではなくミリ秒が必要ですか?(そのため、それをSQLクエリに含めることができます):

instant.truncatedTo(ChronoUnit.MILLIS).toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.664


-3
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
String text = date.toString(formatter);
LocalDate date = LocalDate.parse(text, formatter);

私はこれが役立つかもしれないと信じています、あなたはインスタントの代わりにある種のlocaldateのバリエーションを使う必要があるかもしれません

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.