Java 8でLocalDateTimeからミリ秒を取得する方法


285

Java 8の新しいLocalDateLocalTimeまたはLocalDateTimeクラスを使用して、1〜1970(エポック)以降の現在のミリ秒を取得する方法があるかどうか疑問に思っています。

既知の方法は以下のとおりです。

long currentMilliseconds = new Date().getTime();

または

long currentMilliseconds = System.currentTimeMillis();

6
何が問題になっていSystem.currentTimeMillis()ますか?
Dawood ibnカリーム2014年

16
@DavidWallace彼は現在の時刻ではなく、日付の時刻を取得しようとしていますか?
Anubian Noob、2014

2
「...現在のミリ秒を取得する方法...」
Dawood ibnカリーム

1〜1970から数えたミリ秒。Java 8 LocalDate、LocalTime、LocalDateTimeの新しいクラスを使用してそれらを取得する方法があるかどうか迷っていました。原因が見つかりませんでした。
George Siggouroglou 2014年

1
それらのクラスの目的についての私の理解は、それが時間の「人間に焦点を合わせた」理解でありcurrentTimeMillis、その文脈とは無関係であるということです。カレンダー+壁時計を非常に正確に考えてください。タイムゾーンや場所についての心配はありません。そのため、LocalTimeから「UTC Time」に戻す方法はありません
Gus

回答:


325

「現在のミリ秒」が何を意味するのかは完全にはわかりませんが、「エポック」からのミリ秒数、つまりUTC 1970年1月1日の午前0時であると想定します。

現在のエポックからのミリ秒数を知りたい場合はSystem.currentTimeMillis()Anubian Noobが指摘したように使用してください。その場合、新しいjava.time APIのいずれかを使用してこれを行う理由はありません。

ただし、多分すでにLocalDateTimeどこかからまたは類似のオブジェクトがあり、それをエポックからミリ秒に変換したい場合があります。LocalDateTimeオブジェクトのファミリには現在のタイムゾーンの概念がないため、これを直接実行することはできません。したがって、タイムゾーン情報を提供して、エポック(UTC)に対応する時間を見つける必要があります。

次のLocalDateTimeようなものがあるとします。

LocalDateTime ldt = LocalDateTime.of(2014, 5, 29, 18, 41, 16);

タイムゾーン情報を適用する必要がありますZonedDateTime。私はロサンゼルスと同じタイムゾーンにいるので、次のようにします。

ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/Los_Angeles"));

もちろん、これはタイムゾーンについての仮定を行います。また、たとえば、現地時間が夏時間(夏時間)の遷移に近い時間に名前を付けた場合など、発生する可能性のあるエッジケースがあります。これらは脇に置いておきましょうが、これらのケースが存在することに注意してください。

とにかく、有効なを取得できる場合はZonedDateTime、次のように、これをエポックからのミリ秒数に変換できます。

long millis = zdt.toInstant().toEpochMilli();

5
ZonedDateTimeにはすでにメソッドあることに注意してくださいgetEpochSecondChronoZonedDateTime defaultを使用)。の必要はありませんInstant
mabi 2014年

13
もちろん、必要なのがミリ秒ではなく、秒だけの場合は。
スチュアートマークス

18
zdt.get(ChronoField.MILLI_OF_SECOND)を使用して、nanosでの数学を回避します。zdt.toInstant()。toEpochMilli()を使用してすべての数学を回避する
JodaStephen

2
は、ゾーン化された日付時刻ではなく、対応するUTC値のzdt.toInstant().toEpochMilli();ミリ秒提供することに注意してください。私はこれを難しい方法で見つけました。toInstant()あなたにUTCインスタントを与えます。ミリ秒単位の現地時間が必要な場合、これでは期待どおりの結果が得られません。したがって、たとえば+02:00ゾーンの時間を使用している場合、返される時間は、予想よりも3600 * 2 * 1000ミリ秒短くなります。
Lundbergによる

2
@PerLundberg Iちょうど比べZonedDateTime.now().toInstant().toEpochMilli()LocalDateTime.now().toInstant(OffsetDateTime.now().getOffset()).toEpochMilli()LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()Calendar.getInstance().getTime().getTime()new Date().getTime()System.currentTimeMillis()。"オフ"と思われる唯一の方法は、提案しLocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli()た方法です。つまり、ローカル日付がUTC 日付であるかのようにミリ秒を与えます。つまり、ローカル日付がUTC + 2の場合、メソッドは将来2時間ミリ秒を与えます
ワレン

81

タイムゾーンを指定しないので、

System.out.println("ldt " + LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
System.out.println("ctm " + System.currentTimeMillis());

与える

ldt 1424812121078 
ctm 1424812121281

ご覧のとおり、実行時間が短いことを除いて、数値は同じです。

System.currentTimeMillisが気に入らない場合に備えて、 Instant.now().toEpochMilli()


3
いいえ、エポックはUTCを基準にしていますが、ローカルゾーンから現在の時刻を取得します。
Rafael Membrives 2017

2
@ChristofferHammarströmエポックから経過したミリ秒数は、タイムゾーンとは無関係です。これは、どの時刻に呼び出しても同じミリ秒です。ブライアンのマシンが2番目のコマンドを実行するのに203ミリ秒かかったため、2つの結果は異なります。
Fletch

ユーザーが別のタイムゾーンにいる場合にUTCを使用しても大丈夫ですか
GilbertS

2
@GilbertSあなたはおそらくこの正確なコードを決して使用すべきではなく、意図したとおりにAPIを使用します。日時は、コンピューターに格納するとき、または別のユーザーに送信するときは常にUTCにする必要があります。通常は、独自のタイムゾーン設定を使用してローカルの日付時刻としてユーザーに提示する必要があります。
ブライアン

20

ZoneIdを回避するには、次のようにします。

LocalDateTime date = LocalDateTime.of(1970, 1, 1, 0, 0);

System.out.println("Initial Epoch (TimeInMillis): " + date.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli());

値として0を取得すると、そうです!


8
ZoneOffset.ofTotalSeconds(0)それは同じですZoneOffset.UTC
アントンノボパシン2017年

1
はい、@ AntonNovopashinのコメントに賛成してくれました。UTCが必要だったので、問題ありません(回答でそれを言及したい場合があります)。BTWはのZoneOffsetサブクラスなZoneIdので、あなたがそれを避けたとは正確には言えませんが、満足している限りは…
Ole VV

私の最初のコメントは少々厳しいものでしたが、不快感を与えるものではありませんでした。あなたは怒った。ごめんなさい。削除しました。逆の質問をさせてください:回避したい理由は何でしょうZoneIdか?
Ole VV

@ OleV.V UTCを使用しても問題ありませんか。UTCタイムゾーンに住んでいる人だけのものではありません。
GilbertS

1
@GilbertS誰もがUTCタイムゾーンに住んでいるとは思わない。タイムゾーン全体で使用される時間にUTCを使用することをお勧めします。たとえば、地理的に多様なユーザー向けの日付の操作/保存に関するJavaのベストプラクティスを参照してください。それとも、あなたの質問が理解できなかったのでしょうか?
Ole VV

15

Java 8以降はを呼び出すことができますjava.time.Instant.toEpochMilli()

たとえば、呼び出し

final long currentTimeJava8 = Instant.now().toEpochMilli();

と同じ結果が得られます

final long currentTimeJava1 = System.currentTimeMillis();

1
「同じ結果が得られます」...しかし、CPUパワーが高くなり、ガベージコレクタの負荷が大きくなります。
VasiliNovikov

上記を定量化してほしい(特に通常の使用-たとえば、パフォーマンスが重要なリアルタイムアプリケーションではない...)
Brian Agnew

11

java.sql.Timestampミリ秒を取得するためにも使用できます。

LocalDateTime now = LocalDateTime.now();
long milliSeconds = Timestamp.valueOf(now).getTime();
System.out.println("MilliSeconds: "+milliSeconds);

あなたはタイムゾーンの決定的な必要性を無視しています。この方法で行うことはお勧めしません。また、Timestampクラスは古く、設計上の問題で満ちているので、特にjava.timelike のクラスを使用できる場合は避けたいと思いLocalDateTimeます。
Ole VV

@ OleV.V。の設計上の問題に興味があるだけでTimestamp、それに関するいくつかの記事を共有できますか?Timestampコードからの使用を避けるのにも役立ちます。ありがとう!
ナラム

1
簡単に言うと、それはのサブクラスとして実装されてDateいますが、として処理できないことがよくありますDate。から継承されたほとんどのメソッドDateと1つのコンストラクタは非推奨です。そのtoString方法は、JVMのタイムゾーンを使用します。これは、同じものTimestampが異なるコンピューターで異なる方法で印刷されるため、多くを混乱させます()。
Ole VV 2018

これは単体テストに最適です。LocalDate.of(year, month, day)
ただ今

これは、「常にUTC」の値を回避するための受け入れられた回答です。
LeYAUable、

9

(エポック以降の)現在の時刻をミリ秒で取得するには、を使用しますSystem.currentTimeMillis()


3

Java 8クロックを使用している場合は、使用できますclock.millis()clock.instant()Java 8インスタントを取得するには、より正確であるため、を使用することをお勧めします)。

なぜJava 8クロックを使用するのですか?したがって、DIフレームワークでClock Beanを作成できます。

@Bean
public Clock getClock() {
    return Clock.systemUTC();
}

テストで簡単にモックできます:

@MockBean private Clock clock;

または、別のBeanを使用することもできます。

@Bean
public Clock getClock() {
    return Clock.fixed(instant, zone);
}

これは、日付と時刻を計り知れないほど主張するテストに役立ちます。


1
  default LocalDateTime getDateFromLong(long timestamp) {
    try {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneOffset.UTC);
    } catch (DateTimeException tdException) {
      //  throw new 
    }
}

default Long getLongFromDateTime(LocalDateTime dateTime) {
    return dateTime.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli();
}

0

なぜ誰もが方法を言及しませんでしたLocalDateTime.toEpochSecond()

LocalDateTime localDateTime = ... // whatever e.g. LocalDateTime.now()
long time2epoch = localDateTime.toEpochSecond(ZoneOffset.UTC);

これは、上記の多くの提案された回答よりもはるかに短いようです...


これは私が探していたものです。その受け入れられた答えは私に意欲を与えていました。
Brill Pappin

API 26でのみ利用可能なものを受け入れます。{
Brill Pappin

1
それはほんの数秒しか与えないからです。toEpochMilliLocalDateTimeでナノ秒も指定できるという事実を考慮すると、メソッドがないことは奇妙ですLocalDateTime.of(int year, int month, int dayOfMonth, int hour, int minute, int second, int nanoOfSecond)。メソッドがあります。
izogfif
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.