タイムスタンプを生成して解析するこのコードがあります。
DateTimeFormatter formatter =
DateTimeFormatter
.ofPattern("yyyyMMdd kk:HH:ss.SSSZ")
.withLocale(Locale.getDefault())
.withZone(ZoneId.systemDefault());
Instant now = Instant.now();
String formatted = formatter.format(now);
Instant parsed = formatter.parse(formatted, Instant::from);
実行すると、最後の行で例外が発生します。
Java.time.format.DateTimeParseException: Text '20180123 12:12:45.648-0500' could not be parsed: Unable to obtain Instant from TemporalAccessor: {SecondOfMinute=45, NanoOfSecond=648000000, OffsetSeconds=-18000, MilliOfSecond=648, MicroOfSecond=648000, HourOfDay=12},ISO,America/New_York resolved to 2018-01-23 of type Java.time.format.Parsed
Caused by: Java.time.DateTimeException: Unable to obtain Instant from TemporalAccessor: {SecondOfMinute=45, NanoOfSecond=648000000, OffsetSeconds=-18000, MilliOfSecond=648, MicroOfSecond=648000, HourOfDay=12},ISO,America/New_York resolved to 2018-01-23 of type Java.time.format.Parsed
Caused by: Java.time.temporal.UnsupportedTemporalTypeException: **Unsupported field: InstantSeconds**
フォーマッタをDateTimeFormatter.ISO_INSTANTに置き換えます。正しく機能します。生成される実際のデータはほぼ同じです。切断とは何ですか?
ISO_INSTANT: 2018-01-23T16:51:25.516Z
My Format: 20180119 23:59:59.999-0800
私は自分のフォーマットを使用する必要があります。ここの問題は何ですか?
問題は、形式が分の表現をまったく持たないため、形式がインスタントを完全に表現しないことです。インスタントにはフォーマットに必要なすべてのデータが含まれていますが、フォーマットにはインスタントに必要なすべてが含まれていないため、フォーマッタはインスタントから正しく結果をフォーマットに出力できます。
パターンをyyyyMMdd kk:HH:mm:ss.SSS
に変更すると、コードが機能するようになります。 mm
が追加されていることに注意してください。
微細なパターンが絶対に必要な場合は、独自のTemporalQueryを作成して、TemporalAccessorから必要な情報を抽出する必要があります。この場合は、単に分を0
に設定します。
public class MyQuery implements TemporalQuery<Instant> {
@Override
public Instant queryFrom(TemporalAccessor temporal) {
LocalDate ld = LocalDate.from(temporal);
LocalTime lt = LocalTime.of(temporal.get(ChronoField.HOUR_OF_DAY), 0, temporal.get(ChronoField.SECOND_OF_MINUTE), temporal.get(ChronoField.NANO_OF_SECOND));
return ZonedDateTime.of(ld, lt, ZoneId.systemDefault()).toInstant();
}
}
次に、このTemporalQueryを次のように使用できます。
public class Test {
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter
.ofPattern("yyyyMMdd kk:HH:mm:ss.SSS")
.withLocale(Locale.getDefault())
.withZone(ZoneId.systemDefault());
Instant now = Instant.now();
String formatted = formatter.format(now);
System.out.println(formatted);
Instant ld = formatter.parse(formatted, new MyQuery());
}
}