マイクロ秒
あなたの質問のテキストは入力文字列を引用して2016-05-14 12:54:01.363
いますが、エラーメッセージはそうではありません2016-05-14 12:54:01.363000
. これらの余分な 3 桁はマイクロ秒です。
java.util.Date などの古い日時クラスは、ミリ秒(秒の小数部の小数点以下 3 桁) にのみ解決されます。そのため、そのSimpleDateFormat
ような入力を処理できません。入力文字列を切り捨てるか、代わりに最新の日時クラスを使用してください。
java.time
より大きな問題は、Java の初期バージョンの古い時代遅れの日時クラスを使用していることです。これらのクラスは、Java 8 以降に組み込まれたjava.timeフレームワークに取って代わられました。その java.time 機能の多くは、ThreeTen-Backportプロジェクトによって Java 6 および 7 にバックポートされ、さらにThreeTenABPによって Android に適合されています。したがって、古くて厄介なことで有名なクラスと格闘する理由はありません。
java.time クラスの粒度ははるかに細かく、ナノ秒(10 進数の 9 桁の秒) に解決されます。
java.time では、Instant
クラスはナノ秒の分解能を持つ UTC のタイムライン上の瞬間です。AnInstant
は a と同等ですが、java.util.Date
解像度がより細かくなります。
古い型と java.time 型の間の変換の詳細については、別の質問へのダイアグラム付きの回答を参照してください。
日時型として日時値を取得する
データベースから日時値を文字列ではなく日時型として取得する必要があります。JDBC ドライバーが JDBC 4.2 ( JSR 221への更新であり、ここで説明されています) に準拠している場合は、OffsetDateTime
. は、 UTC からのオフセット(時、分、秒) をOffsetDateTime
加えInstant
たものと考えることができます。
java.time.OffsetDateTime odt = resultSet.getObject( 1 );
そうでない場合は、古いjava.sqlタイプの使用にフォールバックします。日時の場合、それはjava.sql.Timestamp
.
java.sql.Timestamp ts = resultSet.getTimestamp( 1 );
java.util.Date/.Calendar などの混乱の一部であるため、古い java.sql 型の使用を最小限に抑えてください。すぐに java.time に変換します。変換するには、古いクラスに追加された新しいメソッド ( など) を探しますtoInstant
。
Instant instant = ts.toInstant();
解析中
その入力文字列を解析する必要がある場合、最も簡単な方法は、 ISO 8601標準形式に準拠させることです。java.time クラスは、文字列の解析/生成時にデフォルトで ISO 8601 形式を使用します。
準拠するには、真ん中の SPACE を に置き換えT
ます。そして、この文字列が実際に UTC の瞬間を表していると仮定すると、Z
. はのZ
略で、Zulu
UTC を意味します。
String input = "2016-05-14 12:54:01.363000";
String inputModified = input.replace( " " , "T" );
Instant instant = Instant.parse( inputModified );
タイムゾーン
質問は、タイム ゾーンの重要な問題を無視しています。
ベスト プラクティスは、日時の値を UTC で保存することです。優れたデータベースは、受信データを UTC に調整します。値として取得したjava.sql.Timestamp
場合は UTC であり、に変換した場合も同様Instant
です。
日付と時刻はタイムゾーンによって異なります。を取得するには、タイム ゾーン ( ZoneId
) を に適用します。Instant
ZonedDateTime
ZoneId zoneId = zoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
次に、問い合わせて、必要な日付と時刻を取得します。
int dayOfMonth = zdt.getDayOfMonth();
時刻をそれ自体のオブジェクトとして使用する場合は、LocalTime
クラスを使用します。
LocalTime localTime = zdt.toLocalTime();
本当に時刻の文字列が必要な場合は、java.time.formatパッケージを使用してください。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "hh:mm a" );
String output = zdt.format( formatter );
さらに良いのは、java.time に自動的にフォーマットする作業を任せることです。(a) 月の名前などの人間の言語、および (b) 年月日などの要素の順序などの文化的規範を決定する Locale の使用に注意してください。実行時に変更される可能性がある JVM の現在のデフォルト ロケールに暗黙的に依存するよりも、ロケールを明示的に指定する方が適切です。
DateTimeFormatter timeOfDayFormatter = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT );
timeOfDayFormatter = timeOfDayFormatter.withLocale( Locale.CANADA_FRENCH );
String output = zdt.toLocalTime().format( timeOfDayFormatter );