4

ミリ秒の文字列 (RSS フィードから取得されるため、文字列になります。以下の例は簡単なテスト プログラムです) を取り、それらのミリ秒を Date オブジェクトに変換する次のコードがあります。

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 時間が失われています。また、出力のフォーマットが変更されました。なぜこれが起こっているのか、そしてそれを回避する方法について誰かが私を助けることができますか? Date オブジェクトを「Date Format」出力と同じ形式にしたい。

4

2 に答える 2

9

これは、英国が 1970 年に実際にGMT を使用していなかったために発生したと考えられます。Java にはバグがあり、英国が GMT を使用しているかのように 1970 年の日付をフォーマットしますが、実際にはオフセットを変更しません。簡単な例:

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

午前 1 時 GMT であると主張していることに注意してください...これは正しくありません。ヨーロッパ/ロンドン時間で午前 1 時でしたが、ヨーロッパ/ロンドンは GMT を監視していませんでした。

Joda Timeは BST を出力するという点でこれを正しく理解していますが、Joda Time はタイム ゾーンの略語で値を解析することを好みません。ただし、代わりにタイム ゾーンオフセットを使用するように設定できます。

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
    }
}
于 2011-04-28T09:38:44.637 に答える
1

Jon Skeetによる回答は正しいです。

java.time

java.time を介して同じ入力を実行して、結果を確認してみましょう。

適切なタイムゾーン名を指定してください。BSTEST、などの 3 ~ 4 文字の略語は絶対に使用しないでください。ISTこれらは、実際のタイム ゾーンではなく、標準化されておらず、固有でもありません (!)。を使用しますEurope/London

このクラスは、ナノ秒単位の精度でUTCInstantのタイムライン上の瞬間を表します。

String input = "1302805253";
long millis = Long.parseLong ( input );
Instant instant = Instant.ofEpochMilli ( millis );

タイムゾーンを適用してZonedDateTimeオブジェクトを生成します。

ZoneId zoneId = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = instant.atZone ( zoneId );

コンソールにダンプします。Europe/Londonその時点で時刻が UTC より 1 時間進んでいることがわかります。したがって、時刻は02時間ではなく01時間です。どちらもタイムライン上の同じ瞬間を表しており、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 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

Joda -Timeプロジェクトは現在メンテナンス モードにあり、java.time への移行を推奨しています。

詳細については、 Oracle チュートリアルを参照してください。また、Stack Overflow で多くの例と説明を検索してください。

java.time 機能の多くは、ThreeTen-Backportで Java 6 および 7 にバックポートされ、さらにThreeTenABPでAndroidに適合されています。

ThreeTen -Extraプロジェクトは、追加のクラスで java.time を拡張します。このプロジェクトは、java.time.

于 2016-08-14T22:00:43.300 に答える