2017-04-27 23 views
3

文字列「2017-04-21T17:46:00Z」が最初のメソッドに渡されると、結果のフォーマットされた日付文字列は「06:46 21 Apr 1970」になります。時間はなぜ11時間動いているのですか?入力文字列は、JSONのHTTPサーバーアプリケーションによって提供されています。私はZ接尾辞がズールー、すなわちGMTと呼ばれると考えました。JodaTimeのタイムゾーンを日付の時間に移動するのはなぜですか?

private static final String DATE_TIME_FORMAT = "hh:mm dd MMM yyyy"; 

public static String formatTimestamp(String dateTimestamp) { 
    DateTime dateTime = getDateTimeFromTimestamp(dateTimestamp); 
    DateTimeFormatter fmt = DateTimeFormat.forPattern(DATE_TIME_FORMAT); 
    return fmt.print(dateTime); 
} 

private static DateTime getDateTimeFromTimestamp(String dateTimestamp) { 
    return new DateTime(dateTimestamp); 
} 

私はそれがタイムゾーンに関係していると思われますが、どのように、どこかにはっきりしません。このコードは、GMTのタイムゾーンで、英国のAndroid搭載端末で実行されています。

+0

この作品は '新しいのSimpleDateFormat(DATE_TIME_FORMAT")を返しませんフォーマット(dateTimestamp); '' –

+0

のSystem.out.println(DateTimeZone.getDefault())の出力何;? ' –

+0

@Hugo "Europe/London" –

答えて

3

私は、問題を再現することができる方法のJava 7とジョダタイム2.7(ただし、Androidのバージョン)

でテストを行った:

// changing my default timezone (because I'm not in UK) 
DateTimeZone.setDefault(DateTimeZone.forID("Europe/London")); 
// calling your method 
System.out.println(formatTimestamp("2017-04-21T17:46:00Z")); 

出力は

です2017

ABR

6時46分21間違っているかどうか確認するために、私は、cをしました日付フォーマットを絞首刑:

a「はAMまたはPM」を意味
DATE_TIME_FORMAT2 = "hh:mm a dd MMM yyyy Z z zzzz"; 

Zは、タイムゾーンオフセット/ IDで、zは、タイムゾーン「ショート」の名前とzzzzは、タイムゾーン「長い」の名前です。このフォーマットを使用すると、出力は次のようになります。

6:46 PM 21 ABR 2017 0100 BST英国夏時間

だから、作成日時が午後6時、先に入力のわずか1時間、11時間ではないです(実際には、hhの代わりにHHにフォーマットを変更すると、06の代わりに18になります)。

また、タイムゾーンフィールド:+0100 BST British Summer Timeにも注意してください。最初の部分(+0100)は、このDateTimeがGMTより1時間遅れていることを意味し、BST British Summer TimeBritish's Daylight Saving Timeを意味します。

1.変更UTCにあなたのデフォルトのタイムゾーン:


だから、あなたの出力は、あなたの入力に等しく持っている、あなたは2つの選択肢を持っている

DateTimeZone.setDefault(DateTimeZone.UTC); 
System.out.println(formatTimestamp("2017-04-21T17:46:00Z")); 

出力は次のようになります。

午前5時46分2017年4月21日

あなたが17:46する時間を変更したい場合は、HH

2でhhを交換し、あなたの日付形式を変更します。DateTimeZoneを受けDateTimeコンストラクタを使用します。

private static DateTime getDateTimeFromTimestamp(String dateTimestamp) { 
    // creates a DateTime in UTC 
    return new DateTime(dateTimestamp, DateTimeZone.UTC); 
} 

出力は1代替と同じになりますが、この場合には、デフォルトのタイムゾーンを変更する必要はありません。

私にとって

ので、代わりの2は、より理にかなって:あなたは(アプリケーションの他の部分でいくつかの混乱を引き起こす可能性があります)デフォルトのタイムゾーンを変更する必要はありません

  • あなたが既に知っていますこのコードによって処理されるすべての日付はUTC時刻であること(because of the "Z" in the end
+1

このような詳細で明確な答えをありがとう。あなたが言うように、UTCを指定し、24時間形式を使用すると、問題は回避されます。 –

1

Answer by Hugoをjava.timeを使用して正しいと思わ有益である。しかし、FYIのJoda-Timeプロジェクトはmaintenance modeにあり、チームはjava.timeクラスへの移行をアドバイスしています。 Androidの場合は、下の最後の箇条書きを参照してください。

入力文字列は標準ISO 8601の形式です。 java.timeクラスは、&の文字列を解析するときに標準形式を使用します。したがって、書式設定パターンを指定する必要はありません。

Instantクラスは、nanoseconds(小数点以下9桁まで)の解像度を持つUTCのタイムライン上の瞬間を表します。

String input = "2017-04-21T17:46:00Z" ; 
Instant instant = Instant.parse(input) ; 

instant.toString():2017-04-21T17:46:00Z

より柔軟なフォーマットについては、あなたが望むように、OffsetDateTimeオブジェクトに変換あなたが任意offset-from-UTC指定することができました。時間と分で表します。 UTC自体(ゼロのオフセット)が必要なので、定数ZoneOffset.UTCを使用できます。

OffsetDateTime odt = instant.atOffset(ZoneOffset.UTC) ; 

odt.toString():2017-04-21T17:46Z

は、ご希望の形式に合わせて、書式設定のパターンを定義します。 (a)日の名前、月の名前などを翻訳するための人間の言語、および(b)略語、大文字小文字、句読点、区切り記号などの問題を決定する文化的な基準を決定するには、Localeを指定する必要があります。

DateTimeFormatter f = DateTimeFormatter.ofPattern("hh:mm dd MMM yyyy" , Locale.US) ; 
String output = odt.format(f) ; 

出力:5:46 2017年4月21日

あなたは、このようなEurope/LondonPacific/Aucklandなど地域の壁時計時間のレンズを通して、この同じ瞬間を見たい場合は、時間をかけますゾーンを取得するZonedDateTime

は、America/MontrealAfrica/Casablanca、又はPacific/Aucklandとして、continent/regionの形式でproper time zone nameを指定します。ESTまたはISTまたはBSTなどの3文字の略語を使用しないでください。標準時ではなく、ユニークではない(!)。

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

夏時間(DST)のため、時間帯が1時間ずれていることに注意してください。

zdt.toString():2017-04-21T18:46 + 01:00 [ヨーロッパ/ロンドン]

このcode run live at IdeOne.comを参照してください。

java.time

についてjava.timeフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは面倒古いlegacy日時クラスなどjava.util.DateCalendar、& SimpleDateFormatに取って代わります。

maintenance modeにあるJoda-Timeプロジェクトは、java.timeクラスへの移行を推奨しています。

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

ここで、java.timeクラスを取得するには?

  • Java SE 8Java SE 9、以降
    • 内蔵しています。
    • バンドルされた実装の標準Java APIの一部です。
    • Java 9には、いくつかのマイナーな機能と修正が加えられています。
  • Java SE 6Java SE 7
    • java.time機能の多くはThreeTen-BackportのJava 6 & 7に戻って、移植されます。
  • Android
      ThreeTenABP
    • プロジェクトは、具体的にはAndroid用(上記)ThreeTen-バックポートを適応させます。
    • How to use ThreeTenABP…を参照してください。
関連する問題