时间戳的两种形式
-
Unix 时间戳:也称为 Epoch 时间,它表示自 1970 年 1 月 1 日 00:00:00 UTC(协调世界时)以来经过的秒数(或毫秒数),这是一个长整型数字。
(图片来源网络,侵删)- 秒级:
1640995200 - 毫秒级(Java 中常用):
1640995200000
- 秒级:
-
java.sql.Timestamp:JDBC API 中用于表示 SQLTIMESTAMP类型的一个类,它本质上继承自java.util.Date,但增加了纳秒(nanoseconds)精度,它内部存储的就是一个毫秒级的值。
Unix 时间戳(毫秒)与 java.sql.Timestamp 互转
这是最常见的需求,尤其是在处理数据库时间戳和前端/后端交互时。
Unix 毫秒时间戳 -> java.sql.Timestamp
使用 Timestamp 的静态工厂方法 valueOf(long millis)。
import java.sql.Timestamp;
public class TimestampConversion {
public static void main(String[] args) {
// 假设这是一个从数据库或 API 获取的毫秒级时间戳
long unixMillisTimestamp = 1678886400000L; // 2025-03-15 00:00:00 UTC
// 将毫秒时间戳转换为 java.sql.Timestamp
Timestamp timestamp = new Timestamp(unixMillisTimestamp);
System.out.println("Unix 毫秒时间戳: " + unixMillisTimestamp);
System.out.println("转换后的 java.sql.Timestamp: " + timestamp);
// 输出: 2025-03-15 00:00:00.0
}
}
java.sql.Timestamp -> Unix 毫秒时间戳
使用 Timestamp 对象的 getTime() 方法,这个方法继承自 java.util.Date。

import java.sql.Timestamp;
public class TimestampConversion {
public static void main(String[] args) {
// 创建一个 java.sql.Timestamp 对象
Timestamp timestamp = Timestamp.valueOf("2025-03-15 08:00:00.123456789");
// 将 java.sql.Timestamp 转换为毫秒时间戳
long unixMillisTimestamp = timestamp.getTime();
System.out.println("原始的 java.sql.Timestamp: " + timestamp);
System.out.println("转换后的 Unix 毫秒时间戳: " + unixMillisTimestamp);
// 输出: 1678915200123
}
}
java.sql.Timestamp 与 java.util.Date 互转
虽然 java.sql.Timestamp 继承自 java.util.Date,但在某些旧框架或 API 中可能需要显式转换。
java.sql.Timestamp -> java.util.Date
由于 Timestamp 是 Date 的子类,可以直接赋值,但这会丢失纳秒精度,如果只是为了兼容需要 Date API,这是可以的。
import java.sql.Timestamp;
import java.util.Date;
public class TimestampToDateConversion {
public static void main(String[] args) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
// 直接赋值,但要注意精度丢失
Date date = timestamp;
// 或者更明确地使用构造函数
// Date date = new Date(timestamp.getTime());
System.out.println("java.sql.Timestamp: " + timestamp);
System.out.println("转换后的 java.util.Date: " + date);
}
}
java.util.Date -> java.sql.Timestamp
同样,可以直接使用 Timestamp 的构造函数,它接受一个 Date 对象。
import java.sql.Timestamp;
import java.util.Date;
public class DateToTimestampConversion {
public static void main(String[] args) {
Date date = new Date(); // 当前时间
// 使用 Date 对象创建 Timestamp
Timestamp timestamp = new Timestamp(date.getTime());
System.out.println("java.util.Date: " + date);
System.out.println("转换后的 java.sql.Timestamp: " + timestamp);
}
}
java.sql.Timestamp 与字符串 互转
我们会将时间戳格式化为易读的字符串,或者从字符串解析出时间戳。

java.sql.Timestamp -> 格式化字符串
使用 SimpleDateFormat 类。
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
public class TimestampToStringConversion {
public static void main(String[] args) {
Timestamp timestamp = Timestamp.valueOf("2025-10-27 10:30:00");
// 定义日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 格式化时间戳为字符串
String formattedDate = sdf.format(timestamp);
System.out.println("原始的 java.sql.Timestamp: " + timestamp);
System.out.println("格式化后的字符串: " + formattedDate);
// 输出: 2025-10-27 10:30:00
}
}
字符串 -> java.sql.Timestamp
使用 Timestamp 的静态方法 valueOf(String s)。注意:此方法要求字符串格式必须是 yyyy-MM-dd HH:mm:ss[.fffffffff]。
import java.sql.Timestamp;
public class StringToTimestampConversion {
public static void main(String[] args) {
// 必须是 "yyyy-MM-dd HH:mm:ss" 格式
String dateString = "2025-10-27 10:30:00";
// 使用 valueOf 方法转换
Timestamp timestamp = Timestamp.valueOf(dateString);
System.out.println("原始的字符串: " + dateString);
System.out.println("转换后的 java.sql.Timestamp: " + timestamp);
// 输出: 2025-10-27 10:30:00.0
}
}
如果字符串格式不是标准格式,需要先用 SimpleDateFormat 解析成 Date 对象,再创建 Timestamp。
java.sql.Timestamp 与 Java 8+ 的 java.time API 互转
(强烈推荐) Java 8 引入了 java.time 包,它设计更优秀,功能更强大,且线程安全,如果你使用的是 Java 8 或更高版本,应优先使用它。
java.sql.Timestamp 和 java.time 之间没有直接的转换方法,需要通过 java.util.Date 作为桥梁。
java.sql.Timestamp -> java.time.LocalDateTime
LocalDateTime 不包含时区信息,适合表示“本地”的日期和时间。
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class TimestampToLocalDateTime {
public static void main(String[] args) {
Timestamp timestamp = Timestamp.valueOf("2025-10-27 10:30:00");
// 1. 将 Timestamp 转换为 Instant (一个 UTC 时间点)
// 2. 将 Instant 转换为指定时区的 LocalDateTime
LocalDateTime localDateTime = timestamp.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
System.out.println("原始的 java.sql.Timestamp: " + timestamp);
System.out.println("转换后的 java.time.LocalDateTime: " + localDateTime);
// 输出: 2025-10-27T10:30
}
}
java.time.LocalDateTime -> java.sql.Timestamp
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
public class LocalDateTimeToTimestamp {
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2025, 10, 27, 10, 30, 0);
// 1. 将指定时区的 LocalDateTime 转换为 Instant
// 2. 将 Instant 转换为毫秒时间戳
long millis = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
// 3. 使用毫秒时间戳创建 Timestamp
Timestamp timestamp = new Timestamp(millis);
System.out.println("原始的 java.time.LocalDateTime: " + localDateTime);
System.out.println("转换后的 java.sql.Timestamp: " + timestamp);
// 输出: 2025-10-27 10:30:00.0
}
}
总结与最佳实践
| 转换方向 | 推荐方法 (Java 8+) | 旧方法 (Java 7 及更早) |
|---|---|---|
Unix 毫秒 -> Timestamp |
new Timestamp(millis) |
new Timestamp(millis) |
Timestamp -> Unix 毫秒 |
timestamp.getTime() |
timestamp.getTime() |
Timestamp -> Date |
Date.from(timestamp.toInstant()) |
直接赋值或 new Date(timestamp.getTime()) |
Date -> Timestamp |
Timestamp.from(date.toInstant()) |
new Timestamp(date.getTime()) |
Timestamp -> 字符串 |
DateTimeFormatter.format(timestamp.toInstant()) |
SimpleDateFormat.format(timestamp) |
字符串 -> Timestamp |
Timestamp.valueOf(LocalDateTime.parse(str, formatter)) |
Timestamp.valueOf(str) (格式受限) |
Timestamp -> LocalDateTime |
timestamp.toInstant().atZone(zone).toLocalDateTime() |
(无直接方法,需通过 Date 桥) |
核心建议:
- 新项目优先使用
java.time:在业务逻辑、数据处理中,尽量使用LocalDateTime,ZonedDateTime,Instant等java.time类,它们更直观、更强大。 - 仅在 JDBC 和数据库交互时使用
java.sql.Timestamp:这是它存在的唯一合理场景。 - 处理时间戳时,始终考虑时区:尤其是在将时间戳转换为字符串或
LocalDateTime时,明确使用ZoneId.systemDefault()或ZoneId.of("UTC")来避免因服务器时区不同导致的问题。 - 弃用
java.util.Date:除非为了维护旧代码,否则应尽量避免在新的代码中使用java.util.Date。
