【发布时间】:2016-07-31 08:23:13
【问题描述】:
最初我有一个非常简单的测试:
@Test
public void testMe() {
System.out.println("Records in H2 db:");
List<DateRangeBean> all = dateRangeServiceImpl.findAll();
all.forEach(x -> System.out.println(x.getDateTo()));
Clock.system(ZoneId.of("UTC"));
ZonedDateTime currentDate = ZonedDateTime.of(2016, 8, 9, 0, 0, 0, 0, clock.getZone());
Date currentDate_date = Date.from(currentDate.toInstant());
System.out.println("Current Date is: " + currentDate_date);
List<DateRangeBean> result = new ArrayList<>();
dateRangeServiceImpl.findGreaterDateTo(currentDate_date).iterator().forEachRemaining(result::add);
result.forEach(x -> System.out.println(x.getDateTo()));
assertEquals(result.size(), 2);
}
始终在 PC 上使用默认 TimeZone UTC 执行,并具有以下输出:
Records in H2 db: Mon Aug 08 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Current Date is: Tue Aug 09 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016
在哪里: dateRangeServiceImpl.findAll() 实现为:
public List<DateRangeBean> findAll (){
List<DateRangeBean> result = new ArrayList<>();
dateRangeRepository.findAll().iterator().forEachRemaining(result::add);
return result;
}
dateRangeServiceImpl.findGreatedDateTo(日期日期):
public List<DateRangeBean> test (Date currentDate){
List<DateRangeBean> result = new ArrayList<>();
dateRangeRepository.findGreatedDateTo(currentDate).iterator().forEachRemaining(result::add);
return result;
}
和 dateRangeRepository - 作为 Spring Data 的一部分的纯接口
public interface DateRangeRepository extends PagingAndSortingRepository<DateRangeBean, Long> {
@Query("from DateRangeBean drb where (drb.dateTo >= :currentDate)")
List<DateRangeBean> findGreatedDateTo(@Param("currentDate") Date currentDate);
}
和DateRangeBean:
@Entity
public class DateRangeBean implements java.io.Serializable {
@Temporal(TemporalType.DATE)
@Column(name = "date_To", length = 10)
private Date dateTo;
.....................
public Date getDateTo() {
return new Date(this.dateTo.getTime());
}
public void setDateTo(Date dateTo) {
this.dateTo = new Date(dateTo.getTime());
}
} 今天我尝试在具有时区的 PC 上运行此测试:UTC -07:00,测试失败,输出如下:
Records in H2 db: Mon Aug 08 00:00:00 MST 2016 Thu Oct 20 00:00:00 MST 2016 Thu Oct 20 00:00:00 MST 2016 Current Date is: Mon Aug 08 17:00:00 MST 2016 Mon Aug 08 00:00:00 MST 2016 Thu Oct 20 00:00:00 MST 2016 Thu Oct 20 00:00:00 MST 2016 java.lang.AssertionError: expected [2] but found [3] Expected :2 Actual :3
好吧,也许这是合理的:我们定义了 currentDate 变量 Aug 9 UTC TZ,但在下一步中,我们在 MST TZ 中将 currentDate 重新转换为 currentDate_date,结果是 8 月 8 日。
但是:
第一季度:
基于我们的@Query:drb.DateTo >= :currentDate 在当前情况下:Mon Aug 08 00:00:00 MST 2016 >= Mon Aug 08 17:00:00 MST 2016 - 此语句不正确!
假设 Spring Data 仅比较日、月、年并修剪时间段。 这是正确的吗??
第二季度:
我尝试修复测试,将时区直接放在测试中:
public void testMe() {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
..............
}
但我仍然得到失败的结果:
Records in H2 db: Mon Aug 08 07:00:00 UTC 2016 Thu Oct 20 07:00:00 UTC 2016 Thu Oct 20 07:00:00 UTC 2016 Current Date is: Tue Aug 09 00:00:00 UTC 2016 Mon Aug 08 07:00:00 UTC 2016 Thu Oct 20 07:00:00 UTC 2016 Thu Oct 20 07:00:00 UTC 2016 java.lang.AssertionError: expected [2] but found [3]
目前我无法理解这怎么可能:
2016 年 8 月 8 日星期一 07:00:00 UTC >= 2016 年 8 月 9 日星期二 00:00:00 UTC ?
第三季度: 我试图将 TZ 指定为 Spring Context 的一部分:
<bean id="defaultZoneInfo" class="sun.util.calendar.ZoneInfo" factory-method="getTimeZone">
<constructor-arg type="java.lang.String" value="UTC"/>
</bean>
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="java.util.TimeZone.setDefault"/>
<property name="arguments">
<list>
<ref bean="defaultZoneInfo"/>
</list>
</property>
</bean>
但结果与 Q2 相同。
第四季度: 在静态块中指定 TZ:
static {
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
}
并测试 - 通过!
Records in H2 db: Mon Aug 08 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Current Date is: Tue Aug 09 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016 Thu Oct 20 00:00:00 UTC 2016
那么,有人能解释一下为什么在 Spring Context xml 文件中指定默认 TZ 并直接在测试方法中没有解决问题吗?
只有通过静态块指定 TZ 才能解决问题?
【问题讨论】:
标签: java spring time timezone spring-data