web-dev-qa-db-ja.com

JSR 310 :: System.currentTimeMillis()とInstant.toEpochMilli():: TimeZone

デフォルトのシステムタイムゾーンと指定されたタイムゾーンの正しいエポック時間(ミリ秒単位)を取得する方法について少し説明してください。

与えられた

1. TimeZone:GMT + 3

2.次のコードスニペット:

_import Java.time.*;

public class Main {        
    public static void main(String[] args) {
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.UTC)
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(LocalDateTime
            .now()
            .atZone(ZoneOffset.of("+3"))
            .toInstant()
            .toEpochMilli()
        );
        System.out.println(System.currentTimeMillis());
    }
}
_

3.出力:

_1444158955508
1444148155508
1444148155508
_

4. JavaDoc System.currentTimeMillis() は、現在の時刻と1970年1月1日の午前0時との差(ミリ秒単位)を返します UTC。

なぜ

  1. _GMT+3_でのLocalDateTimeの出力はSystem.currentTimeMillis()と同じですが、System.currentTimeMillis()のドキュメントではUTCについて言及していますか?
  2. LocalDateTimeでのUTCの出力はSystem.currentTimeMillis()とは異なりますが、System.currentTimeMillis()のドキュメントではUTC
21
szhem

System.currentTimeMillis()Instant.toEpochMilli()はどちらもUnixエポックからのミリ秒数を返します。 Unixエポックは通常「1970年1月1日の真夜中、UTC」と表現されますが、それは特定のタイムゾーンではありません。ただし、インスタントは単なる瞬間であり、どのタイムゾーンにいても同じですが、現地時間は異なります。

LocalDateTime.atZone(UTC)の出力が異なるのは、「ローカルの日付と時刻を取得して、インスタントに変換するまるでUTCタイムゾーンにあるかのように "-そのLocalDateTimeを作成したとき、UTC + 3タイムゾーンで暗黙的にそうしたのです...それが "間違った"理由です。

LocalDateTime.now()はローカルの日付と時刻を使用しますシステムのデフォルトのタイムゾーン。したがって、タイムゾーンがUTC + 3の場合、現在の時刻は2015-10-06T16:57:00Zであり、LocalDateTime.now()は_.2015-10-06T19:57:00_を返します。それをlocalNowと呼びましょう...

したがって、localNow.atZone(ZoneOffset.of("+3"))は、2015-10-06T19:57:00 + 03を表すZonedDateTimeを返します-つまり、同じローカル日付/時刻ですが、3時間進んでいることを「知っています」 UTCの...したがって、toInstant()は2015-10-06T16:57:00Zを表すInstantを返します。すばらしい-現在の日付/時刻はまだ残っています。

ただし、localNow.atZone(ZoneOffset.UTC)は2015-10-06T19:57:00Zを表すZonedDateTimeを返します。つまり、同じローカル日付/時刻ですが、すでにUTCにあると「考えています」。 。so toInstant()は2015-10-06T19:57:00Z ..を表すInstantを返します。これは現在の時刻ではありません(3時間後)。

39
Jon Skeet

ショートバージョン

_LocalDateTime -> Instant_を計算する方法はありません。タイムゾーンを指定する必要があります。タイムゾーンを使用すると、ZonedDateTimeを取得し、_ZonedDateTime -> Instant_を計算できます

Instant == System.currentTimeMillis() ZonedDateTimeのタイムゾーンがシステムのデフォルトのタイムゾーンと等しい場合。

長いバージョン

LocalDateTimeは、時計の時刻(および日付情報)です。現在のタイムゾーンを指定しないと、これだけでは不十分です。東京の13:00は、パリの13:00と同じインスタントではありません。

LocalDateTimeにタイムゾーンを追加すると、ZonedDateTimeが取得され、実際の時間を確認できます。例えば。東京かパリの13時ですか?

正しいインスタントを取得するには、ZonedDateTimeのタイムゾーンが正しい必要があります。東京が13:00であるが、パリが13:00であると主張した場合、間違ったインスタントを取得します。

LocalDateTime

オフセットやタイムゾーンなどの追加情報がないと、タイムライン上のインスタントを表すことはできません。

ZonedDateTime

このクラスは、LocalDateTimeのローカルタイムラインからInstantのインスタントタイムラインへの変換を処理します。 2つのタイムラインの違いは、UTC /グリニッジからのオフセットであり、ZoneOffsetで表されます。

Instant を取得するには、まずLocalDateTimeをZonedDateTimeに変換する必要があります。これを正しく行った場合(正しいタイムゾーンを示すことにより)、インスタントはSystem.currentTimeMillis()に同意します。

System.currentTimeMillis()

現在時刻と1970年1月1日UTCの午前0時との差(ミリ秒単位)。

  1. gMT + 3でのLocalDateTimeの出力はSystem.currentTimeMillis()と同じですが、System.currentTimeMillis()のドキュメントではUTCについて言及していますか?

タイムゾーンがGMT + 3の場合、 ZonedDateTime.toInstant() は正しいインスタントを提供するため、 System.currentTimeMillis() に同意します

  1. system.currentTimeMillis()のドキュメントでUTCについて言及していますが、UTCでのLocalDateTimeの出力はSystem.currentTimeMillis()とは異なりますか?

タイムゾーンがUTCではない場合、 ZonedDateTime.toInstant()が正しくないインスタントを提供します。

1
Roland
System.out.println("Output 1 : " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("Output 2 : " + System.currentTimeMillis());

出力1:1576047664910

出力2:1576047664911

0
StinkyMadness