web-dev-qa-db-ja.com

JavaでLongを日付に変換すると1970が返されます

Webサービスからダウンロードした長い値(例:1220227200、1220832000、1221436800 ...)のリストがあります。日付に変換する必要があります。残念ながら、この方法で、たとえば:

Date d = new Date(1220227200);

1970年1月1日を返します。正しく変換する別の方法を知っている人はいますか?

98
mmmiki

Dateコンストラクター (リンクをクリックしてください!)は、秒ではなく、millisecondslongとして時刻を受け入れます。 1000倍して、longとして指定する必要があります。

Date d = new Date(1220227200L * 1000);

これはここに表示されます

2008年8月31日20:00:00 GMT-04:00 2008

140
BalusC

tl; dr

Instant.ofEpochSecond( 1_220_227_200L )

データを知る

エポック であるため、人々は時間を追跡する際にさまざまな精度を数値として使用します。したがって、エポック以降のカウントとして解釈されるいくつかの数値を取得する場合、以下を決定する必要があります。

  • エポックは何ですか?
    多くのエポック日付 は、さまざまなシステムで使用されています。一般的に使用されるのは POSIX/Unix時間 です。ここで、エポックはUTCの1970年の最初の瞬間です。ただし、このエポックをと想定しないでください
  • 精度は?
    私たちは、エポック以降、秒、 ミリ秒マイクロ秒 、または ナノ秒 を話しているのでしょうか?
  • どのタイムゾーンですか?
    エポックは UTC /GMTタイムゾーンにあるため、通常はカウントです。つまり、タイムゾーンオフセットはまったくありません。しかし、経験の浅い、または日時を知らないプログラマーが関与する場合、暗黙のタイムゾーンが存在する場合があります。

あなたの場合、他の人が指摘したように、Unixエポックから数秒が与えられたようです。しかし、ミリ秒を期待するコンストラクターにそれらの秒を渡します。したがって、解決策は1,000を掛けることです。

学んだ教訓:

  • 受信したデータの意味を判断します(想定しないでください)。
  • ドキュメント を読んでください。

Graph showing various granularities of resolution in date-time systems including whole seconds, milliseconds, microseconds, and nanoseconds.

あなたのデータ

データは数秒であるようです。 1970年の初めのエポックを想定し、UTCタイムゾーンを想定する場合、1,220,227,200は2008年9月1日の最初の瞬間です。

ジョーダタイム

JavaにバンドルされているJava.util.Dateおよび.Calendarクラスは厄介なことで有名です。それらを避けてください。代わりに、 Joda-Time ライブラリまたはJava 8にバンドルされた新しい Java.timeパッケージ を使用してください(Joda-Timeに触発された)。

J.u.Dateとは異なり、Joda-Timeの DateTime は、独自に割り当てられた time zone を本当に知っていることに注意してください。したがって、以下に示すJoda-Time 2.4コードの例では、UTCのデフォルトの仮定を使用してミリ秒を最初に解析することに注意してください。次に、調整するパリのタイムゾーンを割り当てます。宇宙のタイムラインでは同じ瞬間ですが、異なる 壁時計時間 。デモンストレーションのために、UTCに再度調整します。ほとんどの場合、暗黙のデフォルト(多くの場合、日時作業でのトラブルの原因)に依存するよりも、希望する/予想されるタイムゾーンを明示的に指定する方が適切です。

DateTimeを構築するにはミリ秒が必要です。したがって、秒単位で入力し、1000を掛けます。 32ビットのlongをオーバーフローさせるため、結果は64ビットのintでなければなりません。

long input = 1_220_227_200L;  // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".

ミリ秒のカウントをコンストラクターにフィードします。その特定のコンストラクターは、カウントが1970年のUnixエポックからのものであると想定しています。したがって、構築後、必要に応じてタイムゾーンを調整します。

適切なタイムゾーン 名前、大陸と都市/地域の組み合わせを使用します。 ESTなどの3文字または4文字のコードは使用しないでください。これらは一意ではなく標準化されていません。

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );

デモンストレーションのために、タイムゾーンを再度調整します。

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );

コンソールにダンプします。モントリオールでは日付がどのように異なっているかに注意してください。新しい日はヨーロッパでは始まっていますが、アメリカではまだ始まっていません。

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );

実行すると。

dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00

Java.time

Joda-Timeのメーカーは、都合の良いときに、代わりの Java.time フレームワークに移行するように依頼しました。 Joda-Timeは引き続き積極的にサポートされていますが、今後の開発はすべて、Java.timeクラスとThreeTen-Extraプロジェクトの拡張機能で行われます。

Java-timeフレームワークは JSR 31 で定義され、Java 8以降に組み込まれています。 Java.timeクラスは、 ThreeTen-Backport プロジェクトのJava 6&7および ThreeTenABPのAndroidにバックポートされました。 プロジェクト。

Instant は、ナノ秒の解像度で UTC のタイムライン上の瞬間です。そのエポックはUTCの1970年の最初の瞬間です。

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

offset-from-UTCZoneOffset を適用して、 OffsetDateTime を取得します。

さらに良いのは、既知の場合、タイムゾーン ZoneId を適用して ZonedDateTime を取得することです。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
45
Basil Bourque

ロングはミリ秒ではなく秒であるように見えます。日付コンストラクターはミリ秒単位の時間を要するため、

Date d = new Date(timeInSeconds * 1000);
37
Codemwnci

これらはおそらくJava new Date(long)コンストラクターに必要なミリ秒ではなくのタイムスタンプです。 1000倍するだけで大​​丈夫です。

9
Magnus Winter

Calendarオブジェクトのミルでのみ時間を設定します

Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());
9
Marlon

ほとんどの場合、長い値は Epoch タイムスタンプに対応し、値は次のとおりです。

1220227200 =月、2008年9月1日00:00:00 GMT

1220832000 = 2008年9月8日月曜日00:00:00 GMT

1221436800 =月、2008年9月15日00:00:00 GMT

これらの長い値を Java.util.Date に変換できます。これは、Java.util.Dateがミリ秒を使用するという事実を考慮に入れています。

// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L); 

ここで、日付を正しく表示するために、以下に示すようにJava.text.DateFormatを使用できます。

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));

以下は、DateFormatを使用および使用せずに、変換されたlong値をJava.util.Dateに表示した結果です。

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC
5
Jack G.

これを試して:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
4
Mohammad Namvar

1220227200は1980年1月15日に対応します(実際、新しいDate(1220227200).toString()は「Thu Jan 15 03:57:07 CET 1970」を返します)。 1970年1月1日より前の日付にlong値を渡すと、実際には1970年1月1日の日付が返されます。値がこの状況(82800000未満)になっていないことを確認してください。

2
Shivan Dragon

日付形式を調整してこれを試してください。

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

注:24時間または12時間のサイクルを確認してください。

1
abhimanyu

新しいDate(number)は、1970年1月1日からnumberミリ秒後の日付を返します。オッズは、1970年1月1日からほんの少し後の日付、時間、分、秒を表示していないことです。

正しい解析ルーティングに従って日付を解析する必要があります。 1220227200が何であるかはわかりませんが、1970年1月1日から数秒後であれば、それを乗算してミリ秒を求めます。そうでない場合は、何らかの方法で1970年以降のミリ秒に変換します(Java.util.Dateを引き続き使用する場合)。

0
Edwin Buck

私のために働く。おそらく、1970からの秒数を取得し、1970年1月1日からのミリ秒を渡さなければならないため、1000で乗算する必要があります。

0
leifg