6

我试图写一个Converter<java.sql.Date, java.time.LocalDate>,但我无法让它与所有时区设置一起工作。

想法:

  • 如果客户端代码有LocalDate2014 年 8 月 20 日,并将其保存到数据库中,则无论客户端时区是什么,它都应在数据库中显示为 2014 年 8 月 20 日。
  • 如果数据库包含 2014 年 8 月 20 日的日期,则客户端应收到 2014 年 8 月 20 日的 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 回答