1. 概述
在Java中处理时间戳是常见任务,尤其是在操作数据库或开发全球化应用时。两个核心类——java.sql.Timestamp
和org.joda.time.DateTime
——分别承担着不同的时间处理职责。
本文将探讨在Java中转换这两种时间类型的三种主流方法,并附上可直接运行的代码示例。⚠️ 注意:所有方案都基于JDK 8+和Joda-Time 2.x版本。
2. 将java.sql.Timestamp转换为org.joda.time.DateTime
2.1. 使用构造函数转换
这是最简单粗暴的方式——直接通过Timestamp
的毫秒值创建DateTime
对象:
DateTime convertToDateTimeUsingConstructor(Timestamp timestamp) {
return new DateTime(timestamp.getTime());
}
测试用例验证:
@Test
public void givenTimestamp_whenUsingConstructor_thenConvertToDateTime() {
long currentTimeMillis = System.currentTimeMillis();
Timestamp timestamp = new Timestamp(currentTimeMillis);
DateTime expectedDateTime = new DateTime(currentTimeMillis);
DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingConstructor(timestamp);
assertEquals(expectedDateTime, convertedDateTime);
}
✅ 优点:代码极简,性能最优
❌ 缺点:依赖系统默认时区,跨时区场景需谨慎
2.2. 使用Instant类转换
Instant
表示UTC时间轴上的一个绝对时间点,非常适合作为中间桥梁:
DateTime convertToDateTimeUsingInstant(Timestamp timestamp) {
Instant instant = timestamp.toInstant();
return new DateTime(instant.toEpochMilli());
}
核心步骤拆解:
timestamp.toInstant()
→ 转换为UTC时间点instant.toEpochMilli()
→ 获取Unix纪元毫秒数- 构造
DateTime
对象
测试验证:
@Test
public void givenTimestamp_whenUsingInstant_thenConvertToDateTime() {
long currentTimeMillis = System.currentTimeMillis();
Timestamp timestamp = new Timestamp(currentTimeMillis);
DateTime expectedDateTime = new DateTime(currentTimeMillis);
DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingInstant(timestamp);
assertEquals(expectedDateTime, convertedTimestamp);
}
⚠️ 注意:此方案最终仍使用系统默认时区,若需指定时区需额外处理
2.3. 使用LocalDateTime类转换
Java 8引入的LocalDateTime
不包含时区信息,需配合ZoneId
使用:
DateTime convertToDateTimeUsingLocalDateTime(Timestamp timestamp) {
LocalDateTime localDateTime = timestamp.toLocalDateTime();
return new DateTime(localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
执行流程:
timestamp.toLocalDateTime()
→ 转为无时区日期时间.atZone(ZoneId.systemDefault())
→ 绑定系统时区- 转换为Instant再获取毫秒数
测试用例:
@Test
public void givenTimestamp_whenUsingLocalDateTime_thenConvertToDateTime() {
long currentTimeMillis = System.currentTimeMillis();
Timestamp timestamp = new Timestamp(currentTimeMillis);
DateTime expectedDateTime = new DateTime(currentTimeMillis);
DateTime convertedDateTime = DateTimeAndTimestampConverter.convertToDateTimeUsingLocalDateTime(timestamp);
assertEquals(expectedDateTime, convertedDateTime);
}
🔧 适用场景:需要显式控制时区转换逻辑时
3. 将org.joda.time.DateTime转换为java.sql.Timestamp
3.1. 使用构造函数转换
反向操作同样简单,直接获取DateTime
的毫秒值构造Timestamp
:
Timestamp convertToTimestampUsingConstructor(DateTime dateTime) {
return new Timestamp(dateTime.getMillis());
}
测试验证:
@Test
public void givenDateTime_whenUsingConstructor_thenConvertToTimestamp() {
long currentTimeMillis = System.currentTimeMillis();
DateTime dateTime = new DateTime(currentTimeMillis);
Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingConstructor(dateTime);
assertEquals(expectedTimestamp, convertedTimestamp);
}
✅ 优势:零中间对象,性能最佳
❌ 局限:隐式使用系统时区
3.2. 使用Instant类转换
通过Instant
作为中间媒介实现转换:
Timestamp convertToTimestampUsingInstant(DateTime dateTime) {
Instant instant = Instant.ofEpochMilli(dateTime.getMillis());
return Timestamp.from(instant);
}
关键步骤:
dateTime.getMillis()
→ 获取毫秒值Instant.ofEpochMilli()
→ 创建UTC时间点Timestamp.from()
→ 生成时间戳对象
测试用例:
@Test
public void givenDateTime_whenUsingInstant_thenConvertToTimestamp() {
long currentTimeMillis = System.currentTimeMillis();
DateTime dateTime = new DateTime(currentTimeMillis);
Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingInstant(dateTime);
assertEquals(expectedTimestamp, convertedTimestamp);
}
💡 提示:此方案比构造函数方式更符合Java 8+的时间API设计理念
3.3. 使用LocalDateTime类转换
适用于需要处理本地日期时间的场景:
Timestamp convertToTimestampUsingLocalDateTime(DateTime dateTime) {
Instant instant = Instant.ofEpochMilli(dateTime.getMillis());
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return Timestamp.valueOf(localDateTime);
}
转换流程:
- 创建
Instant
对象 - 转换为系统默认时区的
LocalDateTime
- 通过
Timestamp.valueOf()
生成目标对象
测试验证:
@Test
public void givenDateTime_whenUsingLocalDateTime_thenConvertToTimestamp() {
long currentTimeMillis = System.currentTimeMillis();
DateTime dateTime = new DateTime(currentTimeMillis);
Timestamp expectedTimestamp = new Timestamp(currentTimeMillis);
Timestamp convertedTimestamp = DateTimeAndTimestampConverter.convertToTimestampUsingLocalDateTime(dateTime);
assertEquals(expectedTimestamp, convertedTimestamp);
}
⚠️ 踩坑预警:LocalDateTime
不包含时区信息,若时区处理不当会导致时间偏差
4. 总结
转换方向 | 推荐方案 | 适用场景 |
---|---|---|
Timestamp → DateTime | 构造函数 | 简单场景,性能优先 |
Timestamp → DateTime | Instant | 需要UTC时间点处理 |
DateTime → Timestamp | 构造函数 | 基础转换需求 |
DateTime → Timestamp | Instant | 符合Java 8+ API风格 |
💎 核心结论:
- 构造函数方案最简单高效,但隐含时区风险
- Instant方案更符合现代Java时间API设计
- LocalDateTime方案适用于需要显式时区控制的复杂场景
完整代码示例可在GitHub仓库获取,或联系作者:contact@baeldung.com