2016-12-10 3 views
1

アンドロイド用のJodaTimeライブラリで日付を解析し、誤ったタイムゾーンオフセットを取得しようとしています。JodaTimeの解析後にアンドロイドのタイムゾーンオフセットが正しくない

String dateString = "1990-05-03T20:00:00.000Z"; 
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(DateTimeZone.UTC); 
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(DateTimeZone.getDefault()); 
DateTime dt = inputFormatter.parseDateTime(dateString); 
String result = outputFormatter.print(dt); 

私のデフォルトのタイムゾーンは、 "ヨーロッパは/モスクワ" である。しかし、結果は "1990-05-04T00:00:00.000 + 0400"、それが「あるべきとき1990-05-03T23:00:00.000 + 0300 " AndroidのバージョンはKitKatです。

どうしたのですか?

+0

私は何も間違っていると思います。 1990年5月3日は夏時間(5月)であるため、Joda-Timeはヨーロッパ/モスクワの夏時間オフセット+04:00を使用します。実際には、モスクワの冬の間にあなたはちょうど混乱しているかもしれません。 –

+0

@MenoHochschild 2014年以来、ロシアは冬の時間しか持たず、毎年時間を変更しません。 Joda-Timeで夏/冬の時間をどのように無効にできますか? – preceptron

答えて

3

あなただけの、あなたはこのコードを使用することができます歴史的なタイムスタンプを表示するための実際のオフセットモスクワゾーンを使用にしたい場合は:ただの異なるオフセットおよび現地時間の一部で、同じ瞬間それでも

String dateString = "1990-05-03T20:00:00.000Z"; 
DateTimeFormatter inputFormatter = 
    DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(DateTimeZone.UTC); 
DateTime dt = inputFormatter.parseDateTime(dateString); 
System.out.println(dt); // 1990-05-03T20:00:00.000Z 

// only use actual offset for Moscow 
DateTimeZone zoneOffset = 
    DateTimeZone.forOffsetMillis(
     DateTimeZone.forID("Europe/Moscow").getOffset(DateTime.now()) 
    ); 
DateTimeFormatter outputFormatter = 
    DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").withZone(zoneOffset); 
String result = outputFormatter.print(dt); 
System.out.println(result); // 1990-05-03T23:00:00.000+0300 

をあなたが探しているフォーム。

サーバからUTC時刻を解析する方法あなたのコメントについて:

String input = "2016-12-10T13:40:38.595"; 
DateTime utc = 
    DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS").parseLocalDateTime(input) 
    .toDateTime(DateTimeZone.UTC); 
System.out.println(utc); // 2016-12-10T13:40:38.595Z 

デバイスデータが間違っている場合は、サーバーへのUTCとして現在のデバイス時間を送信する方法?

最初の言い方:クライアントのメッセージを受信するときにサーバーが独自のクロックを使用してタイムスタンプを登録する必要があるため、現在のクライアントのタイムスタンプをサーバーに送信する必要がない場合は、これにより、偽のクライアントが何らかのナンセンス時間を送信することを効果的に防ぎます。

tz-dataとデバイスクロック(System.currentTimeMillis()経由)の両方が間違っているにもかかわらず、ローカルデバイスのタイムスタンプがあなたのコメント(year-month-day-hour-minuteの有効なフィールド値)

// incorrect platform data from device clock or outdated tz-data 
long platformMillis = System.currentTimeMillis(); 
int offsetMillis = TimeZone.getDefault().getOffset(platformMillis); 
DateTimeZone tzPlatform = DateTimeZone.forOffsetMillis(offsetMillis); // +04 on your device 

// we assume correct local time if the errors of platform data compensate each other 
LocalDateTime ldt = new LocalDateTime(new Date(platformMillis), tzPlatform); 

// now we combine local timestamp with the tz-data of Joda-Time (hopefully up-to-date) 
long utcMillis = ldt.toDateTime(DateTimeZone.getDefault()).getMillis(); 

サイドノート:Time4Aが短いソリューションを可能にマイライブラリその後、あなたは次の回避策を適用することができます。

Moment now = SystemClock.inPlatformView().now().inStdTimezone(); 
long utcMillis = TemporalType.MILLIS_SINCE_UNIX.from(now); 
+0

それは仕事です。 しかし、そのようなコードをすべてのタイムゾーンで使用するとどうなりますか? 'DateTimeZone zoneOffset = DateTimeZone.forOffsetMillis(DateTimeZone.getDefault()。getOffset(DateTime.now())); DateTimeFormatter outputFormatter = DateTimeFormat.forPattern( "yyyy-MM-dd'T'HH:mm:ss.SSSZ").Zone(zoneOffset); ' – preceptron

+0

@preceptron他のタイムゾーンで働かないのはなぜですか?瞬間を維持しながらローカルタイムスタンプを変更する任意のオフセットで任意の瞬間を表示することができます。しかし、歴史的なオフセットを持つ歴史的なフォームは私にとってより自然なようで、表示したいタイムスタンプには関係しない実際のオフセットだけを使用するという要求はありません。 –

+0

@preceptronこれは明らかにそうです:あなたがモスクワではなくブラジルにいると想像してみてください。そうすれば、サンパウロゾーンの相殺を使って同じ瞬間を表示し、ブラジルのローカルタイムスタンプを得ることができます。ローカルのタイムスタンプの部分とオフセットの変更。ただし、瞬間は同じです。そして、あなたがディスプレイに使用したいオフセットは、あなた次第です。Joda-Timeにモスクワゾーン(明示的オフセットなし)を使用するように指示するだけの場合、Joda-Timeは、状況的な歴史的な瞬間(印刷される予定)でオフセットを使用します。 –

関連する問題