私は外部のAPIからのUTCのタイムスタンプ文字列を受信しています、と私はとして保存する必要がありますLocalDateTime
。タイムスタンプは、夏時間がアクティブである期間内であれば、他の言葉で、それは(通常は時間によって)DSTに調整されるべきです。
私は、着信文字列を解析しOffsetDateTime
、私は、その後に変換され、ZonedDateTime
し、その後にInstant
。この時点で、DST時間が正しく調整されています。私が作成したときしかしLocalDateTime
からInstant
、それは調整を失います。
@Test
public void testDates() {
final DateTimeFormatter OFFSET_FORMAT = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSXX");
final ZoneId zoneId = TimeZone.getDefault().toZoneId();
final String summerTime = "2019-09-11T10:00:00.000+0000";
final String winterTime = "2019-12-11T10:00:00.000+0000";
OffsetDateTime odtSummer = OffsetDateTime.parse(summerTime, OFFSET_FORMAT);
OffsetDateTime odtWinter = OffsetDateTime.parse(winterTime, OFFSET_FORMAT);
ZonedDateTime zdtSummer = odtSummer.toLocalDateTime().atZone(zoneId);
ZonedDateTime zdtWinter = odtWinter.toLocalDateTime().atZone(zoneId);
Instant instSummer = zdtSummer.toInstant();
Instant instWinter = zdtWinter.toInstant();
System.out.println("instSummer = " + instSummer); // instSummer = 2019-09-11T09:00:00Z
System.out.println("instWinter = " + instWinter); // instWinter = 2019-12-11T10:00:00Z
LocalDateTime ldtSummer = LocalDateTime.ofInstant(instSummer, zoneId);
LocalDateTime ldtWinter = LocalDateTime.ofInstant(instWinter, zoneId);
System.out.println("ldtSummer = " + ldtSummer); // ldtSummer = 2019-09-11T10:00
System.out.println("ldtWinter = " + ldtWinter); // ldtWinter = 2019-12-11T10:00
}
私はこれをどのようにすればよいですか?私は、再解析のような醜いものに頼る必要はありませんInstant.toString()
。
問題は、あなたが入力を変換している方法であるZonedDateTime
値
ZonedDateTime zdtSummer = odtSummer.toLocalDateTime().atZone(zoneId);
ZonedDateTime zdtWinter = odtWinter.toLocalDateTime().atZone(zoneId);
ここでは、「現地の日付時刻バージョンを取ると言っているOffsetDateTime
、と実際に指定されたタイムゾーンのローカル値だったことふり」。あなたは、「タイムゾーンの午前10時現地時間」ではなくで終わるように、「午前10時のUTC、現地のタイムゾーンに変換」。
あなたは「この時点では、DSTの時間が正しく調整されている」と書きました-しかし、そうではありません。「00.000 + 0000:00 2019-09-11T10」がありますが、印刷するときは、の値で開始しInstant
、それは「2019-09-11T09を:00:00Z」を印刷しています。午前10時UTCと午前9時UTCは同じ瞬間ではありません。
代わりに、変換する必要がありますOffsetDateTime
にInstant
-それはあなたが本当に解析されてきたものだと-してから入れることに関連する時間帯に:
ZonedDateTime zdtSummer = odtSummer.toInstant().atZone(zoneId);
ZonedDateTime zdtWinter = odtWinter.toInstant().atZone(zoneId);
または使用 OffsetDateTime.atZoneSameInstant
ZonedDateTime zdtSummer = odtSummer.atZoneSameInstant(zoneId);
ZonedDateTime zdtWinter = odtSummer.atZoneSameInstant(zoneId);
そのから行くにはポイントがないことを注意戻って取得するためにインスタントにLocalDateTime
だけ使用することを- toLocalDateTime
。あなたが関連するすべての種類をしたい場合は、ここで適切なコードは次のとおりです。
OffsetDateTime odtSummer = OffsetDateTime.parse(summerTime, OFFSET_FORMAT);
OffsetDateTime odtWinter = OffsetDateTime.parse(winterTime, OFFSET_FORMAT);
Instant instSummer = odtSummer.toInstant();
Instant instWinter = odtWinter.toInstant();
ZonedDateTime zdtSummer = instSummer.atZone(zoneId);
ZonedDateTime zdtWinter = instWinter.atZone(zoneId);
LocalDateTime ldtSummer = zdtSummer.toLocalDateTime();
LocalDateTime ldtWinter = zdtWinter.toLocalDateTime();
あなたが必要としない場合はInstant
、単に:
OffsetDateTime odtSummer = OffsetDateTime.parse(summerTime, OFFSET_FORMAT);
OffsetDateTime odtWinter = OffsetDateTime.parse(winterTime, OFFSET_FORMAT);
ZonedDateTime zdtSummer = odtSummer.atZoneSameInstant(zoneId);
ZonedDateTime zdtWinter = odtWinter.atZoneSameInstant(zoneId);
LocalDateTime ldtSummer = zdtSummer.toLocalDateTime();
LocalDateTime ldtWinter = zdtWinter.toLocalDateTime();