1. 引言

本文将探讨如何将 java.sql.Timestamp 对象转换为 java.util.Calendar 对象。我们将先分析这两个类在时间处理上的差异,然后探讨转换的典型场景,最后提供具体实现方案。

2. Java 中的时间处理

Java 中时间通常以毫秒为单位表示(自 1970-01-01 00:00:00 GMT 起)。当需要更高精度时,会使用纳秒(十亿分之一秒)。

核心特性对比

java.sql.Timestamp

  • 继承自 java.util.Date
  • 新增纳秒级精度(通过 nanos 字段)
  • 专为数据库时间戳设计
  • 时间值 = 毫秒 + 纳秒

java.util.Calendar

  • 最高仅支持毫秒级精度
  • 提供日期字段操作(年/月/日等)
  • 适合日期计算和格式化

⚠️ 关键差异Timestamp 的纳秒精度在转换到 Calendar 时会丢失,这是常见的踩坑点。

3. 时间对象转换

3.1. Timestamp 转 Calendar

当从数据库获取时间戳后,通常需要转换为 Calendar 进行日期字段操作:

Timestamp timestamp = new Timestamp(1713544200801L);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp.getTime());

转换原理:通过 getTime() 获取毫秒值设置到 Calendar。验证转换是否正确:

assertEquals(calendar.getTimeInMillis(), timestamp.getTime());

3.2. Calendar 转 Timestamp

反向转换时需注意精度丢失问题:

public static Timestamp calendarToTimestamp(Calendar calendar) {
    return new Timestamp(calendar.getTimeInMillis());
}

精度丢失演示

int nanos = 801789562;
int losslessNanos = 801000000; // 转换后实际保留值

Timestamp timestamp = new Timestamp(1713544200801L);
timestamp.setNanos(nanos);
assertEquals(nanos, timestamp.getNanos());

Calendar calendar = SqlTimestampToCalendarConverter.timestampToCalendar(timestamp);
timestamp = SqlTimestampToCalendarConverter.calendarToTimestamp(calendar);
assertEquals(losslessNanos, timestamp.getNanos()); // 断言通过

丢失原因TimestampgetTime() 方法内部将纳秒值除以 1,000,000 取整(801789562 → 801 毫秒)。

4. 总结

  • TimestampCalendar 都基于毫秒时间戳
  • Timestamp 独有的纳秒精度适合高精度场景
  • ❌ 转换到 Calendar 会丢失纳秒精度
  • ✅ 当需要操作日期字段(年/月/日)时,转换到 Calendar 是合理选择

如果应用需要纳秒级精度,建议使用 Java 8+ 的 java.time API(如 InstantZonedDateTime),可避免精度丢失问题。

完整示例代码请查阅 GitHub 仓库


原始标题:Converting java.sql.Timestamp to java.util.Calendar | Baeldung