561

Java 8 には、日付と時刻用のまったく新しい API があります。この API で最も便利なクラスの 1 つはLocalDateTime、タイムゾーンに依存しない日付と時刻の値を保持するための です。

java.util.Dateこの目的でレガシー クラスを使用するコードは、おそらく何百万行にもなります。そのため、古いコードと新しいコードを接続する場合、2 つのコードを変換する必要があります。これを達成するための直接的な方法はないようですが、どのように行うことができますか?

4

9 に答える 9

822

簡潔な答え:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

説明:(についてのこの質問LocalDateに基づいて)

その名前にもかかわらずjava.util.Date、「日付」ではなく、タイムライン上の瞬間を表します。オブジェクト内に格納されている実際のデータは、long1970-01-01T00:00Z (1970 GMT/UTC 開始時の午前 0 時) からのミリ秒数です。

java.util.DateJSR-310の と同等のクラスは ですInstant。したがって、前後の変換を提供する便利なメソッドがあります。

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

java.util.Dateインスタンスにはタイムゾーンの概念がありません。はタイムゾーンに関連しているため、を呼び出すと奇妙に思えるかもしれませんtoString()。ただし、そのメソッドは実際にはJavaのデフォルトのタイムゾーンをオンザフライで使用して文字列を提供します。タイムゾーンは の実際の状態の一部ではありません。java.util.DatetoStringjava.util.Date

には、タイムゾーンに関するInstant情報も含まれていません。したがって、 からInstantローカル日付/時間に変換するには、タイムゾーンを指定する必要があります。これは、デフォルト ゾーンである場合ZoneId.systemDefault()もあれば、アプリケーションが制御するタイム ゾーン (ユーザー設定のタイム ゾーンなど) である場合もあります。LocalDateTimeインスタントとタイムゾーンの両方を取る便利なファクトリ メソッドがあります。

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

逆に、メソッドLocalDateTimeを呼び出してタイムゾーンを指定しますatZone(ZoneId)。は、次のZonedDateTimeように直接変換できますInstant

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

LocalDateTimeからへの変換ZonedDateTimeは、予期しない動作を引き起こす可能性があることに注意してください。これは、夏時間のため、すべてのローカル日付/時間が存在するわけではないためです。秋/秋には、ローカル タイムラインに重複があり、同じローカル日時が 2 回発生します。春になると、1時間がなくなる隙間があります。atZone(ZoneId)変換が行うことの定義の詳細については、の Javadoc を参照してください。

要約すると、aとjava.util.Datea を往復すると、夏時間のために別の瞬間になる可能性があります。LocalDateTimejava.util.Date

追加情報: 非常に古い日付に影響する別の違いがあります。java.util.Date1582 年 10 月 15 日に変更されるカレンダーを使用し、それより前の日付はグレゴリオ暦ではなくユリウス暦を使用します。対照的に、java.time.*は常に ISO 暦体系 (グレゴリオ暦に相当) を使用します。ほとんどの場合、ISO 暦体系が必要ですが、1582 年より前の日付を比較すると、奇妙な結果が生じる場合があります。

于 2014-05-27T09:36:14.943 に答える
151

これが私が思いついたものです(そして、すべての日時の難問と同様に、奇妙なタイムゾーン-うるう年-夏時間の調整に基づいておそらく反証されるでしょう:D )

往復: Date<<->>LocalDateTime

与えられた:Date date = [some date]

(1) LocalDateTime<< Instant<<Date

    Instant instant = Instant.ofEpochMilli(date.getTime());
    LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

(2) Date<< Instant<<LocalDateTime

    Instant instant = ldt.toInstant(ZoneOffset.UTC);
    Date date = Date.from(instant);

例:

与えられた:

Date date = new Date();
System.out.println(date + " long: " + date.getTime());

(1) LocalDateTime<< Instant<< Date:

Instantから作成Date:

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);

以下から作成DateしますInstant(必須ではありませんが、説明のため):

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

LocalDateTimeから作成Instant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);

(2) Date<< Instant<<LocalDateTime

Instantから作成LocalDateTime:

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);

Dateから作成Instant:

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

出力は次のとおりです。

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

Instant from Date:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

LocalDateTime from Instant:
2013-11-01T14:13:04.574

Instant from LocalDateTime:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
于 2013-11-01T12:31:19.260 に答える
26

デフォルトのタイムゾーンが必要であることが確実な場合は、はるかに便利な方法:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
于 2015-05-08T21:22:38.940 に答える
5

すべてがここにあります: http://blog.progs.be/542/date-to-Java-time

「往復」の答えは正確ではありません。

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

システムのタイムゾーンが UTC/GMT でない場合は、時刻を変更してください。

于 2014-05-07T19:03:16.163 に答える
3

これが最も簡単な方法か最善の方法か、または落とし穴があるかどうかはわかりませんが、機能します。

static public LocalDateTime toLdt(Date date) {
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(date);
    ZonedDateTime zdt = cal.toZonedDateTime();
    return zdt.toLocalDateTime();
}

static public Date fromLdt(LocalDateTime ldt) {
    ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
    GregorianCalendar cal = GregorianCalendar.from(zdt);
    return cal.getTime();
}
于 2013-10-17T15:40:54.290 に答える