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


118

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

Date d = new Date(1220227200);

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


どのような値を期待していますか?秒/ミリ秒の質問は有効ですが、1220227200は1/1/1970ではありません。コンストラクタに0を渡しているようです。さらにいくつかのコードが役立つかもしれません。
SJuan76 2011

1
@mmmiki-回答を受け入れる必要があります
スチュワート

1970年1月15日を返します。ここでは1月1日ではありません。
njzk2 14

ちなみに、、、、などのひどく欠陥のある日時クラスjava.util.Datejava.util.Calendar、Java 8以降に組み込まれたjava.timeクラスに取って代わられ、java.text.SimpleDateFormat現在はレガシーです。
バジルブルク

回答:


161

Dateコンストラクタは、(リンクをクリック!)など、時間受け付けlongではミリ秒単位ではなく秒。それを1000倍して、として指定する必要がありますlong

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

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

8月31日(日)20:00:00 GMT-04:00 2008


22
またはDate d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));、よりクリーンでマジックナンバーの少ないソリューションに使用します。
Priidu Neemre 2015

56

tl; dr

java.time.Instant                    // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.

データを知る

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

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

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

学んだ教訓:

  • 受け取ったデータの意味を判断し、想定しないでください。
  • ドキュメントをお読みください。

秒単位、ミリ秒単位、マイクロ秒単位、ナノ秒単位など、日時システムの解像度のさまざまな粒度を示すグラフ。

あなたのデータ

データは秒単位のようです。1970年の初めのエポックを想定し、UTCタイムゾーンを想定すると、1,220,227,2002008年9月の最初の日の最初の瞬間になります。

ジョーダタイム

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

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

DateTimeを構築するにはミリ秒が必要です。秒の入力を受け取り、千を掛けます。long32ビットでオーバーフローするため、結果は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は引き続き積極的にサポートされていますが、今後の開発はすべて、ThreeTen-Extraプロジェクトのjava.timeクラスとその拡張で行われます。

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

アンは、Instantタイムライン上の瞬間であるUTCナノ秒の解像度を持ちます。その時代は、UTCにおける1970年の最初の瞬間です。

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

UTCからオフセットを適用してZoneOffsetを取得しOffsetDateTimeます。

さらによくわかっている場合は、タイムゾーンZoneIdを適用してを取得しZonedDateTimeます。

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

モダンとレガシーの両方のJavaのすべての日時タイプの表


1
乾杯バディ。素晴らしい説明。1970年から新しいDateTime(<long number>)を取得していましたが、秒単位で指定し、ミリ秒単位で要求されていることに
気付きました

40

longはミリ秒ではなく、秒のようです。日付コンストラクタはミリ秒単位で時間がかかるため、

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh:反対投票はしませんでしたが、元の回答は異なりました。彼は5分の猶予期間内にそれを編集しました。
BalusC、2011

説明をありがとう。それは、SO自身の欠点です...:-/
f1sh

11

カレンダーオブジェクトの時間のみをミル単位で設定します

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

これらはおそらくにタイムスタンプされているではなくミリ秒 javaの新しい日付(長い)コンストラクタのために必要です。1000倍するだけで大​​丈夫です。


23
より適切には30000ミリ秒が遅すぎる
SJuan76

5

多くの場合、長い値はエポックのタイムスタンプに対応し、値は次のとおりです。

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を使用せずにjava.util.Dateに変換されたlong値を表示した結果です。

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


2

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


2

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

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

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


0

新しい日付(数値)は、number1970年1月1日からミリ秒単位の日付を返します。日付の形式が時間、分、秒を表示しておらず、1970年1月1日の少し後であることがわかります。

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


0

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

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