コードには 3 つの主要な問題があります。
- はミリ秒を超える精度をサポートしていません (
.SSSSSS
) 。また、1 秒未満の桁数を 3 桁に制限する必要があることも意味します。SimpleDateFormat
.SSS
Z
タイムゾーン オフセットの解析に使用しましたが、-05:00
これの正しいパターンは ですXXX
。
- 24 時間形式で時間を使用
hh
しましたが、これの正しいパターンは ですHH
。記号hh
は、12 時間形式 (つまり、午前/午後) 形式で時間に使用されます。
これとは別にLocale
、日付時刻文字列の一部は s ごとに異なる方法で表現されるため、常に日付の解析/書式設定 API を使用することをお勧めしますLocale
。
デモ:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
Date date = sdf.parse("2011-04-11T22:27:18.491-05:00");
// Print the default string i.e. Date#toString
System.out.println(date);
// Print the date-time in a custom format
sdf.setTimeZone(TimeZone.getTimeZone("GMT-05:00"));
System.out.println(sdf.format(date));
}
}
出力:
Tue Apr 12 04:27:18 BST 2011
2011-04-11T22:27:18.491-05:00
従来の日時 API に関するいくつかの事実:
- オブジェクトは、最新の日時型のような実際の
java.util.Date
日時オブジェクトではありません。むしろ、「エポック」(または UTC) として知られる標準ベース時刻からのミリ秒数を表します。のオブジェクトを出力すると、そのメソッドは、このミリ秒値から計算された JVM のタイムゾーンで日時を返します。異なるタイムゾーンで日時を出力する必要がある場合は、タイムゾーンを に設定し、そこからフォーマットされた文字列を取得する必要があります。January 1, 1970, 00:00:00 GMT
java.util.Date
toString
SimpleDateFormat
java.util
日時 API とそのフォーマット APIはSimpleDateFormat
時代遅れで、エラーが発生しやすいものです。それらの使用を完全に停止し、最新の日時 APIに切り替えることをお勧めします*。
最新の日時 API を使用する:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2011-04-11T22:27:18.491726-05:00");
// Print the default string i.e. OffsetDateTime#toString
System.out.println(odt);
// Print the date-time in a custom format. Note: OffsetDateTime#toString drops
// seconds if it is zero
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXX");
System.out.println(dtf.format(odt));
}
}
出力:
2011-04-11T22:27:18.491726-05:00
2011-04-11T22:27:18.491726-05:00
注:の場合DateTimeFormatter
、記号は年u
を意味し、記号は紀元年を意味します。[AD][2] 時代の 1 年間は問題ありませんが、BC 時代の 1 年間は問題になります。詳細については、この回答を確認してください。y
最新の日時 API の詳細については、Trail: Date Timeを参照してください。
* 何らかの理由で、Java 6 または Java 7 に固執する必要がある場合は、 java.time機能のほとんどを Java 6 & 7 にバックポートするThreeTen-Backportを使用できます。Androidプロジェクトと Android API で作業している場合レベルはまだ Java-8 に準拠していません。desugarで利用可能な Java 8+ APIと Android プロジェクトで ThreeTenABP を使用する方法 を確認してください。