MySQL时间类型与Java日期时间类对应关系示例详解
作者:比特森林探险记
在开发中数据库和编程语言通常需要处理日期和时间数据,MySQL数据库和Java编程语言都提供了各种时间类型来处理日期和时间数据,这篇文章主要介绍了MySQL时间类型与Java日期时间类对应关系的相关资料,需要的朋友可以参考下
一、MySQL 时间类型与 Java 类型对应关系
MySQL 类型 | 范围/描述 | Java 对应类型 | 精度级别 |
---|---|---|---|
DATE | '1000-01-01' - '9999-12-31' | java.time.LocalDate | 日期 |
TIME | '-838:59:59' - '838:59:59' | java.time.LocalTime | 时间 |
DATETIME | '1000-01-01 00:00:00' - '9999-12-31 23:59:59' | java.time.LocalDateTime | 毫秒/微秒 |
TIMESTAMP | '1970-01-01 00:00:01' - '2038-01-19 03:14:07' | java.time.Instant java.sql.Timestamp | 秒/毫秒 |
YEAR | 1901 - 2155 | java.time.Year java.lang.Integer | 年 |
二、JDBC 操作映射关系
1. 从数据库读取数据
try (ResultSet rs = stmt.executeQuery("SELECT * FROM time_table")) { while (rs.next()) { LocalDate date = rs.getObject("date_column", LocalDate.class); LocalTime time = rs.getObject("time_column", LocalTime.class); LocalDateTime dateTime = rs.getObject("datetime_column", LocalDateTime.class); Instant timestamp = rs.getObject("ts_column", Instant.class); } }
2. 向数据库写入数据
PreparedStatement ps = conn.prepareStatement( "INSERT INTO time_table (date_column, time_column, datetime_column, ts_column) " + "VALUES (?, ?, ?, ?)"); ps.setObject(1, LocalDate.now()); ps.setObject(2, LocalTime.now()); ps.setObject(3, LocalDateTime.now()); ps.setObject(4, Instant.now()); ps.executeUpdate();
三、MySQL 时间类型详细对比
特性 | DATE | TIME | DATETIME | TIMESTAMP | YEAR |
---|---|---|---|---|---|
时区敏感 | 否 | 否 | 否 | 是 | 否 |
自动初始化 | 否 | 否 | 否 | 是 | 否 |
自动更新 | 否 | 否 | 否 | 是 | 否 |
存储空间(字节) | 3 | 3 | 5-8 | 4 | 1 |
微秒精度支持 | - | MySQL 5.6+ | MySQL 5.6+ | MySQL 5.6.4+ | - |
2038年限制 | 无 | 无 | 无 | 有 (2038年) | 无 |
四、微秒精度处理(MySQL 5.6+)
// Java 端处理微秒(MySQL DATETIME(6)) LocalDateTime ldt = LocalDateTime.now() .withNano(456000000); // 456毫秒 // MySQL 创建表 CREATE TABLE events ( event_time DATETIME(6) // 支持微秒级精度 );
五、时区处理最佳实践
1. 时间存储策略
// 写入统一使用 UTC 时间 ps.setObject(4, Instant.now()); // UTC 时间戳 // 读取时转换为本地时间 Instant dbTime = rs.getObject("event_time", Instant.class); ZonedDateTime localTime = dbTime.atZone(ZoneId.systemDefault());
2. MySQL 服务器配置
-- 检查时区设置 SELECT @@global.time_zone, @@session.time_zone; -- 推荐设置为 UTC SET GLOBAL time_zone = '+00:00';
六、特殊场景处理方案
1. 日期范围统计
LocalDate start = LocalDate.of(2023, 1, 1); LocalDate end = LocalDate.of(2023, 12, 31); PreparedStatement ps = conn.prepareStatement( "SELECT * FROM orders WHERE order_date BETWEEN ? AND ?"); ps.setObject(1, start); ps.setObject(2, end);
2. 时间区间查询(TIMESTAMP + 时区)
Instant startInstant = ZonedDateTime.of( 2023, 5, 1, 0, 0, 0, 0, ZoneId.of("Asia/Shanghai")).toInstant(); PreparedStatement ps = conn.prepareStatement( "SELECT * FROM transactions WHERE create_time >= ?"); ps.setObject(1, startInstant);
3. 时间间隔计算(Java 端处理)
LocalDateTime orderTime = rs.getObject("order_time", LocalDateTime.class); LocalDateTime deliveryTime = rs.getObject("delivery_time", LocalDateTime.class); Duration interval = Duration.between(orderTime, deliveryTime); System.out.printf("配送耗时: %.1f小时", interval.toMinutes() / 60.0);
七、传统 java.sql 类替代方案
传统类 | Java 8+ 替代方案 | 使用场景 |
---|---|---|
java.sql.Date | LocalDate | 只处理日期部分 |
java.sql.Time | LocalTime | 只处理时间部分 |
java.sql.Timestamp | Instant 或 LocalDateTime | 带时区的时间戳/本地日期时间 |
转换示例:
// 传统转现代 Timestamp ts = rs.getTimestamp("create_time"); LocalDateTime ldt = ts.toLocalDateTime(); // 现代转传统 LocalDateTime now = LocalDateTime.now(); Timestamp ts = Timestamp.valueOf(now);
八、时区转换流程图
graph LR A[业务系统时间\nLocalDateTime] -->|应用时区| B[JVM 默认时区] B -->|转换为UTC| C[Instant/UTC时间] C -->|存储至MySQL| D[TIMESTAMP列] D -->|读取为Instant| E[Java Instant类型] E -->|转换至目标时区| F[用户时区显示]
九、常见问题解决方案
时区错乱问题
// 明确设置JVM时区(启动参数) -Duser.timezone=Asia/Shanghai // JDBC连接指定时区 jdbc:mysql://localhost/db?serverTimezone=Asia/Shanghai
2038年TIMESTAMP溢出
- 在 MySQL 8.0 升级 TIMESTAMP 到 8 字节存储
- 将 TIMESTAMP 改为 DATETIME 类型
微秒精度丢失
// 数据库指定精度(DATETIME(6)) LocalDateTime ldt = LocalDateTime.now().withNano(123456000);
跨时区同步问题
- 统一使用 UTC 时间存储(TIMESTAMP)
- 前端显示时根据用户时区转换
总结建议
类型选择优先级:
- 日期 →
DATE
↔LocalDate
- 时间 →
TIME
↔LocalTime
- 完整时间 →
DATETIME
↔LocalDateTime
- 跨时区时间 →
TIMESTAMP
↔Instant
- 日期 →
最佳实践:
// 创建表规范 CREATE TABLE events ( id BIGINT PRIMARY KEY, event_date DATE, -- 日期类数据 event_time TIME(3), -- 毫秒级时间 start_datetime DATETIME(6), -- 微秒级本地时间 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 带时区时间 ); // Java操作规范 repository.save(new Event( LocalDate.now(), LocalTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().withNano(456000000), Instant.now() ));
重要原则:
- 前端交互:字符串(ISO 8601格式)
- 业务层:java.time 类型
- 持久层:直接映射数据库类型
- 存储时态:统一使用UTC标准时区
调试技巧:
-- MySQL查看实际存储值 SELECT date_column, UNIX_TIMESTAMP(ts_column) AS timestamp_value, CONVERT_TZ(ts_column, '+00:00', @@session.time_zone) AS local_time FROM time_table;
掌握MySQL和Java时间类型的精确对应关系,是处理国际化应用、财务系统和时效敏感业务的基础。遵循UTC存储、本地化展示的原则,可规避90%的时区相关问题。
到此这篇关于MySQL时间类型与Java日期时间类对应关系的文章就介绍到这了,更多相关MySQL时间类型与Java日期时间类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!