web-dev-qa-db-ja.com

LocalDateTime、ZonedDateTimeおよびTimestamp

SpringBootアプリを持っています。 Spring Initializer、組み込みTomcat、Thymeleafテンプレートエンジン、および実行可能JARファイルとしてのパッケージを使用します。

2つのプロパティ(initDate、endDate)を持つドメインオブジェクトがあります。 mySQL DBに対応する2つのコンバーターを作成したい

_@Convert(converter = LocalDateTimeAttributeConverter.class) 
private LocalDateTime initDate;

@Convert(converter = ZonedDateTimeAttributeConverter.class) 
private ZonedDateTime endDate;
_

コンバーター1(OK)

_@Converter
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {

    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {
        return (localDateTime == null ? null : Timestamp.valueOf(localDateTime));
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
        return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
    }
}
_

これは私が作成したいものです

_@Converter
public class ZonedDateTimeAttributeConverter implements AttributeConverter<ZonedDateTime, Timestamp> {

    @Override
    public Timestamp convertToDatabaseColumn(ZonedDateTime zoneDateTime) {
        return (zoneDateTime == null ? null : Timestamp.valueOf(zoneDateTime));
    }


    @Override
    public ZonedDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
        return (sqlTimestamp == null ? null : sqlTimestamp.toZonedDateTime());
    }
}
_

しかし、2つのエラーがあるためできません。

_The method valueOf(String) in the type Timestamp is not applicable for the arguments (ZonedDateTime)
_

また、タイムスタンプにはtoZonedDateTime()メソッドがありません

zonedDateにコンバーターを追加しない場合、JPAはvarbinary(255)型のテーブルを作成します

12
La Carbonell

タイムスタンプ は、Dateを拡張してナノ秒の精度を提供します。 DateTimestampも、特定のタイムゾーンをZoneDateTimeとして参照するように設計されていません。

ZonedDateTime-> Timestampを変換する必要がある場合は、タイムゾーン/オフセット情報を破棄する必要があります。例えば。

LocalDateTime withoutTimezone = zoneDateTime.toLocalDateTime();
Timestamp timestamp = Timestamp.valueOf(withoutTimezone));

Timestamp-> ZonedDateTimeを変換するには、オフセットを指定する必要があります。

LocalDateTime withoutTimezone = sqlTimestamp.toLocalDateTime();
ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("+03:00"));

またはタイムゾーン:

ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("Europe/Paris"));

データベースにZonedDateTime変数を保存し、そこで指定されたさまざまなタイムゾーンを保持することを目的とする場合は、それに応じてデータベースを設計することをお勧めします。提案:

  1. タイプDATETIMEの列を使用して、LocalDateTimeおよびVARCHARを保存し、"Europe/Paris"SMALLINTなどのタイムゾーンを保存します。
  2. ZonedDateTimeStringに変換し、"2017-05-16T14:12:48.983682+01:00[Europe/London]"のようなVARCHAR列に保存します。その後、データベースから読み取るときに解析する必要があります。
12

ジョン・スキートはすでに言った:

_@Override
public Timestamp convertToDatabaseColumn(ZonedDateTime zoneDateTime) {
    return zoneDateTime == null ? null : Timestamp.from(zoneDateTime.toInstant());
}

@Override
public ZonedDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
    return sqlTimestamp == null ? null : sqlTimestamp.toInstant().atZone(ZoneId.systemDefault());
}
_

ジョンも良い質問をしました。どのタイムゾーンが欲しいですか? ZoneId.systemDefault()を推測しました。明らかに、タイムゾーンが異なると結果も異なります。したがって、考え直して、目的に合った適切なタイムゾーンを見つけることができることを願っています。

PSかっこが少ないほど読みやすくなったため、かっこの使用を減らしました。必要に応じて、それらを再び追加できます。

8
Ole V.V.