ミリ秒から1970年1月の日付を返すときに1時間を失う
-
26-10-2019 - |
質問
一連のミリ秒を取る次のコード(RSSフィードからのものであるため、文字列になります。以下の例はクイックテストプログラムです)を持ち、それらのミリを日付オブジェクトに変換します。
public static void main(String[] args) {
String ms = "1302805253";
SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(Long.parseLong(ms));
try {
String dateFormat = dateFormatter.format(calendar.getTime());
System.out.println("Date Format = " + dateFormat);
Date dateParse = dateFormatter.parse(dateFormatter.format(calendar.getTime()));
System.out.println("Date Parse = " + dateParse);
} catch (ParseException e) {
// TODO: handle exception
}
}
Output:
Date Format = Fri, 16 Jan 1970 02:53:25 GMT
Date Parse = Fri Jan 16 03:53:25 GMT 1970
ご覧のとおり、カレンダーオブジェクトのフォーマットと結果の文字列の解析の間に、1時間が失われています。また、出力のフォーマットが変更されました。なぜこれが起こっているのか、そしてそれを回避する方法について誰も私を助けることができますか?日付オブジェクトを「日付形式」出力と同じ形式にしたい。
解決
英国がそうしなかったので、それが起こっていると思います 実際に 1970年にGMTを使用すると、Javaはその周りにバグがあります... フォーマット 1970年の日付は、英国がGMTを使用しているかのようですが、実際にオフセットを変更することはありませんでした。簡単な例:
Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(sdf.format(date));
結果:
01 Jan 1970 01:00:00 GMT
GMTの午前1時だと主張していることに注意してください...これは間違っています。これ だった ヨーロッパ/ロンドンの時間の午前1時ですが、ヨーロッパ/ロンドンはGMTを観察していませんでした。
ジョーダ時間 BSTを印刷するという点でこれを正しく理解してください - しかし、Jodaの時間は好きではありません 解析 タイムゾーンの略語を備えた値。ただし、タイムゾーンを使用することができます オフェット 代わりは:
import org.joda.time.*;
import org.joda.time.format.*;
public class Test {
public static void main(String[] args) throws Exception {
DateTime date = new DateTime(0, DateTimeZone.forID("Europe/London"));
DateTimeFormatter formatter = DateTimeFormat.forPattern(
"dd MMM yyyy HH:mm:ss Z");
String text = formatter.print(date); // 01 Jan 1970 01:00:00 +0100
System.out.println(text);
DateTime parsed = formatter.parseDateTime(text);
System.out.println(parsed.equals(date)); // true
}
}
他のヒント
Jon Skeetによる回答 正しい。
Java.Time
Java.timeを通して同じ入力を実行して、結果を確認しましょう。
aを指定します 適切なタイムゾーン名. 。次のような3-4文字の略語を使用しないでください BST
, EST
, 、 また IST
それらは真のタイムゾーンではなく、標準化されておらず、ユニークでさえありません(!)。だから私たちは使用します Europe/London
.
Instant
クラスは、タイムラインの瞬間を表します UTC の決議付き ナノ秒.
String input = "1302805253";
long millis = Long.parseLong ( input );
Instant instant = Instant.ofEpochMilli ( millis );
タイムゾーンを適用してaを生成します ZonedDateTime
物体。
ZoneId zoneId = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = instant.atZone ( zoneId );
コンソールにダンプします。確かにわかります Europe/London
その瞬間、UTCの1時間先です。したがって、時刻はそうです 02
ではなく時間 01
時間。どちらもタイムライン上の同じ同時モーメントを表し、2つの異なるレンズを通して見たばかりです 壁2回.
System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );
入力:1302805253 |インスタント:1970-01-16T01:53:25.253Z | ZDT:1970-01-16T02:53:25.253+01:00 [ヨーロッパ/ロンドン
全体の秒
ちなみに、私はあなたの入力文字列が表すと思われます 全体 1970年のEPOCH以来の数秒ではなく、UTCではなく ミリ秒. 。数秒として2011年に日付を取得し、この質問が投稿されたと解釈しました。
String output = Instant.ofEpochSecond ( Long.parseLong ( "1302805253" ) ).atZone ( ZoneId.of ( "Europe/London" ) ).toString ();
2011-04-14T19:20:53+01:00 [ヨーロッパ/ロンドン
Java.timeについて
Java.Time フレームワークはJava 8以降に組み込まれています。これらのクラスは、古い厄介な日付クラスに取って代わります java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
ジョーダタイム プロジェクト、今 メンテナンスモード, 、Java.timeへの移行をアドバイスします。
詳細については、を参照してください Oracleチュートリアル. 。多くの例と説明については、スタックオーバーフローを検索します。
Java.timeの機能の多くは、Java 6と7にバックポートされています Threeten-Backport さらに適応します アンドロイド の Threetenabp.
Threeten-Extra プロジェクトは、追加のクラスでJava.Timeを延長します。このプロジェクトは、Java.timeに将来の追加の可能性の実証済みの基盤です。