6

を書き込もうとしましたConverter<java.sql.Date, java.time.LocalDate>が、すべてのタイムゾーン設定で動作させることができません。

アイデア:

  • クライアント コードにLocalDate20-Aug-2014 などの があり、それを DB に保存する場合、クライアントのタイム ゾーンに関係なく、DB では 20-Aug-2014 として表示されます。
  • DB に 20-Aug-2014 の日付が含まれている場合、クライアントのタイム ゾーンに関係なく、クライアントは 20-Aug-2014 の LocalDate を受け取る必要があります。

私のテスト:

@Test public void dateConverter() {
  for (int offset = -12; offset <= 12; offset++) {
    TimeZone localTz = TimeZone.getTimeZone(ZoneOffset.ofHours(offset));
    TimeZone.setDefault(localTz);
    LocalDate ld = LocalDate.now();

    sql.insertInto(DATE_TEST).set(new DateTestRecord(ld)).execute();
    LocalDate savedLd = sql.selectFrom(DATE_TEST).fetchOne(DATE_TEST.DATE_);
    assertEquals(savedLd, ld, "offset=" + offset);
    sql.delete(DATE_TEST).execute();
  }
}

私のコンバーター:

public class DateConverter implements Converter<Date, LocalDate>{
  @Override public LocalDate from(Date date) { return date.toLocalDate(); }
  @Override public Date to(LocalDate ld) { return Date.valueOf(ld); }
  @Override public Class<Date> fromType() { return Date.class; }
  @Override public Class<LocalDate> toType() { return LocalDate.class; }
}

さまざまなバリエーションを試しましたが、どれもうまくいきませんでした...

4

1 に答える 1

2

問題は実際にテストにあります!JDBC ドライバーは作成時にタイムゾーンをキャッシュし、テスト ループでのタイム ゾーンの更新は考慮されませんでした。テストでタイムゾーンが変わるたびに新しい接続を取得すると、テストに合格します。

したがって、問題のコードは Date から LocalDate へのコンバーターで機能します (ただし、null を受け入れる必要があります)。最終版:

public class DateConverter implements Converter<Date, LocalDate> {
  @Override public LocalDate from(Date date) { return date == null ? null : date.toLocalDate(); }
  @Override public Date to(LocalDate ld) { return ld == null ? null : Date.valueOf(ld); }
  @Override public Class<Date> fromType() { return Date.class; }
  @Override public Class<LocalDate> toType() { return LocalDate.class; }
}

タイムゾーンのある時間から OffsetTime へのコンバーターは、同様の方法で実行できます。

public class TimeConverter implements Converter<Time, OffsetTime> {
  @Override public OffsetTime from(Time time) {
    return time == null ? null : OffsetTime.ofInstant(Instant.ofEpochMilli(time.getTime()), ZoneOffset.systemDefault());
  }
  @Override public Time to(OffsetTime offsetTime) {
    return offsetTime == null ? null : new Time(offsetTime.atDate(LocalDate.ofEpochDay(0)).toInstant().toEpochMilli());
  }
  @Override public Class<Time> fromType() { return Time.class; }
  @Override public Class<OffsetTime> toType() { return OffsetTime.class; }
}
于 2014-08-21T18:55:55.137 に答える