2011-04-28 12 views
4

次のコードでは、ミリ秒の文字列(RSSフィードから取得されるので、文字列になります。以下の例は簡単なテストプログラムです) millisをDateオブジェクトに変換します。1970年1月の日付をミリ秒単位で返すときに1時間を失う

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 

ご覧のとおり、カレンダーオブジェクトの書式設定と結果のStringの解析の間に、1時間が失われています。また、出力の書式が変更されました。なぜこれが起きているのか、それをどう回避するのか、誰でも助けてくれますか? Dateオブジェクトを "Date Format"出力と同じフォーマットにしたい。

+0

イギリスはBST(= GMT + 1)、または1970年に全年が裁判であったことが問題です。 http://stackoverflow.com/questions/1238172/why-does-an-hour-get-added-on-to-java-util-date-for-dates-before-nov-1-1971 –

+0

ああ、私見る。情報をありがとう。 – MeanwhileInHell

答えて

8

私は英国が実際には、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)); 

結果:それは間違っている午前1時GMT ...だと主張していること

01 Jan 1970 01:00:00 GMT 

注意。 はヨーロッパ/ロンドン時間で 1amでしたが、ヨーロッパ/ロンドンは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 
    } 
} 
+0

よかった、ありがとう。 – MeanwhileInHell

0

Answer by Jon Skeetが正しい:しかし、あなたはそれがタイムゾーンにoffets代わりを使用して取得することができます。

java.time

はのは、結果を確認するためにjava.timeを通じて同じ入力を実行してみましょう。

proper time zone nameを指定します。 BSTEST、またはISTのような3〜4文字の略語は、標準化されておらず、ユニークではない(!)ではないため、決して使用しないでください。したがって、Europe/Londonを使用します。

Instantクラスは、タイムライン上の瞬間をUTCに表し、解像度はnanosecondsです。

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時間早いことがわかります。だから時刻は01時間ではなく02時間です。両方ともタイムライン上の同じ同時の瞬間を表し、ちょうど2つの異なるwall-clock timesのレンズを通して見られる。

System.out.println ("input: " + input + " | instant: " + instant + " | zdt: " + zdt); 

入力:1302805253 |インスタント:1970-01-16T01:53:25.253Z | zdt:1970-01-16T02:53:25253 + 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プロジェクトは、今maintenance modeで、java.timeへの移行をアドバイスします。

詳しくはOracle Tutorialをご覧ください。そして、多くの例と説明のためにStack Overflowを検索してください。

java.time機能ThreeTen-BackportでJava 6 & 7に戻って、移植、さらにThreeTenABPAndroidに適合されているの多く。

ThreeTen-Extraプロジェクトは、追加のクラスでjava.timeを拡張します。このプロジェクトは、将来のjava.timeへの追加の可能性を証明する土台です。

関連する問題