2016-09-01 16 views
0

私は文字列形式の日付があります。解析する必要があります。世界中からのタイムゾーンで、次のようなフォーマットは次のとおりです。JodaTimeで元のタイムゾーンを保持する方法

String stringDate = "2016-04-29 12:16:49.222+04:30"; 
String pattern = "yyyy-MM-dd HH:mm:ss.SSSZ"; 

java.util.Date:、セパレータとタイムゾーンを受け入れていないようです。だから私はJodatimeライブラリにしようとしている:

DateTime formattedDate = DateTimeFormat.forPattern(pattern).parseDateTime(stringDate); 
LocalDateTime formattedDate2 = DateTimeFormat.forPattern(pattern).parseLocalDateTime(stringDate); 
MutableDateTime formattedDate3 = DateTimeFormat.forPattern(pattern).parseMutableDateTime(stringDate); 

System.out.println(formattedDate); 
System.out.println(formattedDate2); 
System.out.println(formattedDate3); 

これらのライン出力:

2016-04-29T09:46:49.222+02:00 
2016-04-29T12:16:49.222 
2016-04-29T09:46:49.222+02:00 

私の知る限り、私はパリにいるよ(フォーマッタが地雷を遵守するために、出力のタイムゾーンを変更理解し、 UTC + 2)ですが、出力は元のタイムゾーンを維持します。 Jodatimeライブラリでも可能ですか?または私は別のものに変更する必要がありますか?

編集:(私のローカルタイムゾーンオフセット)120の代わりに: 実は私は、タイムゾーンのオフセットは(4時間30分の時間帯は、stringDateのオフセット)270だろうどのDateオブジェクトを取得する必要があります。

System.out.println(formattedDate.toDate().getTimezoneOffset()); // I expect 270 but I get 120 
+0

期待される出力は?私は元の文字列を印刷するだけでいいのですね。 – joc

+0

@joc実際には、 'TimeZoneOffset()'が120 * 'ではなく270 *である' Date'オブジェクトが必要です。 (私の質問を更新します) – Fractaliste

+1

'Date.getTimezoneOffset()'はJDK 1.1から廃止され、常に_yourローカルのtimezone_offsetを返します。タイムゾーンサポートを取得するには、jodaの 'DateTime'またはjava-8の' ZonedDateTime'を使用できます。あなたはどちらを好みますか? – Roman

答えて

0

私はあなたが投稿した同じコードを実行すると、私は

あなたが気づく場合
2016-04-29T02:46:49.222-05:00 
2016-04-29T12:16:49.222 
2016-04-29T02:46:49.222-05:00 

で終わる、異なる時間値とtを持っていますime-zone値。

System.out.println(formattedDate.getMillis()); 
System.out.println(formattedDate2.toDateTime().getMillis()); 
System.out.println(formattedDate3.getMillis()); 

は、あなたが出力

1461916009222 
1461950209222 
1461916009222 

だから、彼らが同じエポックタイムを持って表示されますが、別々にプリントアウトされています。しかし、あなたはそれらのミリ秒を見れば。これは、DateTimeオブジェクトのtoString()のメカニズムと、それらをどのように解釈するのかによるものです。

異なる時刻で同じエポック時間を扱うDateTimeとLocalDateTime(MutableDateTimeはDateTimeの可変バージョンです)。 LocalDateTime 常にはエポック時間がUTC時間(javadoc for LocalDateTime)であると仮定しますが、DateTimeはエポックがそれが保持する年表の時間帯(javadoc again)で表されると仮定します。構築時にTimeZoneが指定されていない場合、クロノロジは、デフォルトロケールのタイムゾーンを、JVMによって設定されるとすることを前提とします。あなたのケースでは、デフォルトロケールはパリフランスで、私はセントルイスUSAです。パリは現在+2:00のタイムゾーンオフセットを保持していますが、セントルイスは-5:00であり、印刷時にタイムゾーンの表現が異なります。

さらに迷惑になるため、これらのオフセットは時間とともに変化する可能性があります。私は6ヶ月で戻ってきて、再びこれを答えることをしようとすると、私の値が-6表示されます:00(!愚かな夏時間を)

覚えておくべき重要なことは、これら2つの日付が同じエポックタイムを持っているということです :私たちは同じ瞬間について話しています。私たちは、それを印刷するときに、その時を別々に表現しています。

あなたは、解析結果の出力を表現するための別のタイムゾーンを使用する場合は、あなたがDateTimeFormat.withZone()DateTimeFormat.withLocaleを使用してフォーマット中にDateTimeZoneを設定することができます

を出力します
DateTimeFormatter sdf = DateTimeFormat.forPattern(pattern).withZone(DateTimeZone.forOffsetHoursMinutes(4,30)); 
System.out.println(formattedDate.getMillis()); 
System.out.println(formattedDate2.toDateTime().getMillis()); 
System.out.println(formattedDate3.getMillis()); 

2016-04-29 12:16:49.222+0430 
2016-04-29 12:16:49.222 
2016-04-29 12:16:49.222+0430 

LocalDateTimeバージョンがTimeZoneなしで印刷されることに注意してください。これはLocalDateTimeの機能の一種です。このすべてのビジネスに対処する必要はありません。

あなたの印刷値が奇妙に見えるのはこのためです。解析されたDateTimeオブジェクトからjava.util.Dateオブジェクトを取得することに関する質問をさらに進める:toDateは、同じエポック時間を表すjava.util.Dateを表示します。ただし、java.util.Dateは、特に指定のない限り、デフォルトロケールのTimeZoneを使用する点でDateTimeと同様に動作します。ロケールを事前に知っている場合は、toDate(Locale)メソッドを使用して、ロケールのTimeZoneオフセットを確実に使用することができます。

タイムゾーンがわからない場合は、時間がかかります。以前は、TimeZoneの時間と分のオフセットを手動で解析して、使用する適切なTimeZoneを決定しなければなりませんでした。この正確なケースでは、それほど難しくありません。なぜなら、最後の6文字はきわめて整形式であり、かつ規則的です(もちろん、そうでない限り:)。あなたは逃した何

1

DateTimeFormatter#withOffsetParsedです:

解析された文字列のオフセットと同等のタイムゾーンと日時を作成する新しいフォーマッタを返します。

そうしないと、フォーマッタがローカルのタイムゾーンに解析します(驚くべきことですが)。あなたの編集については

@Test 
public void preserveTimeZone() { 
    String stringDate = "2016-04-29 12:16:49.222+04:30"; 
    String pattern = "yyyy-MM-dd HH:mm:ss.SSSZ"; 

    DateTime dt = DateTimeFormat.forPattern(pattern).withOffsetParsed().parseDateTime(stringDate); 

    System.out.println(dt); // prints "2016-04-29T12:16:49.222+04:30" 
} 

からjava.util.Dateは、タイムゾーン情報のみ

が適切であるUTCへのローカルタイムゾーンの相対的のために、分単位で測定し、オフセットを返し廃止予定getTimezoneOffset()方法を保持していませんこのDateオブジェクトによって表される時間。

タイムゾーンを正しく処理するには、Joda Timeまたはjava.timeクラスを使用することをお勧めします。

関連する問題