代码片段:
private Date fetchTimestampFromDatabase(SqlRowSet rs, String field) {
try {
System.out.println(rs.getTimestamp(field));
for (int i = 0; i < 10; i++) {
System.out.println(rs.getTimestamp(field, Calendar.getInstance(TimeZone.getTimeZone("UTC"))));
Thread.sleep(200);
...
给出如下结果:
2014-06-06 10:44:58.696
2014-06-06 12:44:58.75
2014-06-06 12:44:58.95
2014-06-06 12:44:58.15
2014-06-06 12:44:58.35
2014-06-06 12:44:58.55
2014-06-06 12:44:58.75
2014-06-06 12:44:58.95
2014-06-06 12:44:58.15
2014-06-06 12:44:58.35
2014-06-06 12:44:58.55
很好,正确地应用了时区偏移量,但是为什么毫秒会抖动,可能是从日历实例中获取的?
阅读该方法的javadoc,我发现一个相当模糊的语句,似乎暗示这是指定的行为:
"此方法使用给定的日历为时间戳构造一个适当的毫秒值"
源文件的第6180行证实了这一点:
cal.set(Calendar.YEAR, defaultCal.get(Calendar.YEAR));
cal.set(Calendar.MONTH, defaultCal.get(Calendar.MONTH));
cal.set(Calendar.DAY_OF_MONTH, defaultCal.get(Calendar.DAY_OF_MONTH));
cal.set(Calendar.HOUR_OF_DAY, defaultCal.get(Calendar.HOUR_OF_DAY));
cal.set(Calendar.MINUTE, defaultCal.get(Calendar.MINUTE));
cal.set(Calendar.SECOND, defaultCal.get(Calendar.SECOND));
return new java.sql.Timestamp(cal.getTime().getTime());
有谁知道为什么日历。没有设置毫秒?
欢呼
文档似乎表明,期望在Calendar中提供毫秒值。但是,它与ResultSet (RowSet从其扩展)的文档有些不同。
这个方法使用给定的日历构造一个合适的如果底层数据库有,则为时间戳的毫秒值不存储时区信息
这似乎将两个看似无关的概念联系在一起——数据库中时区信息的存在和数据库中时间戳字段的精度。
源代码中的问题实际上在日历填充之前开始:
defaultCal.setTime((java.util.Date)value);
通过将时间戳转换为java.util。日期,所有部分秒数据丢失。如时间戳javadoc中所述:
注意:该类型是java.util.Date和一个独立的纳秒值。中只存储整数秒java.util.Date组件。