MySQL时间戳转换完整教程
掌握MySQL中处理Unix时间戳的所有技巧,包含UNIX_TIMESTAMP、FROM_UNIXTIME等函数的详细SQL示例。
获取当前时间戳
使用MySQL函数获取当前Unix时间戳
SQL
-- 获取当前Unix时间戳(秒级)
SELECT UNIX_TIMESTAMP();
-- 结果: 1735660800
-- 获取当前时间戳(毫秒级,MySQL 5.6.4+)
SELECT ROUND(UNIX_TIMESTAMP(NOW(3)) * 1000);
-- 结果: 1735660800000
-- 获取当前日期时间
SELECT NOW(); -- 2025-01-01 00:00:00
SELECT CURRENT_TIMESTAMP(); -- 2025-01-01 00:00:00
SELECT SYSDATE(); -- 2025-01-01 00:00:00
-- 获取UTC时间
SELECT UTC_TIMESTAMP(); -- 2024-12-31 16:00:00
SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP()); -- UTC时间戳时间戳转日期
将Unix时间戳转换为日期时间格式
SQL
-- 时间戳转日期时间
SELECT FROM_UNIXTIME(1735660800);
-- 结果: 2025-01-01 00:00:00
-- 指定格式输出
SELECT FROM_UNIXTIME(1735660800, '%Y-%m-%d');
-- 结果: 2025-01-01
SELECT FROM_UNIXTIME(1735660800, '%Y年%m月%d日 %H:%i:%s');
-- 结果: 2025年01月01日 00:00:00
-- 毫秒时间戳转换(需要先转换为秒)
SELECT FROM_UNIXTIME(1735660800000 / 1000);
-- 结果: 2025-01-01 00:00:00
-- 提取时间部分
SELECT FROM_UNIXTIME(1735660800, '%Y') as year; -- 2025
SELECT FROM_UNIXTIME(1735660800, '%m') as month; -- 01
SELECT FROM_UNIXTIME(1735660800, '%d') as day; -- 01
SELECT FROM_UNIXTIME(1735660800, '%H') as hour; -- 00日期转时间戳
将日期时间转换为Unix时间戳
SQL
-- 日期字符串转时间戳
SELECT UNIX_TIMESTAMP('2025-01-01 00:00:00');
-- 结果: 1735660800
-- 日期格式转换
SELECT UNIX_TIMESTAMP('2025/01/01 00:00:00');
SELECT UNIX_TIMESTAMP('2025-01-01');
-- NOW()转时间戳
SELECT UNIX_TIMESTAMP(NOW());
-- 指定日期转时间戳
SELECT UNIX_TIMESTAMP(DATE('2025-01-01')); -- 只取日期部分
SELECT UNIX_TIMESTAMP(DATE_ADD(NOW(), INTERVAL 1 DAY)); -- 明天的时间戳
-- STR_TO_DATE解析后转时间戳
SELECT UNIX_TIMESTAMP(STR_TO_DATE('2025-01-01', '%Y-%m-%d'));日期格式化
使用DATE_FORMAT格式化日期时间
SQL
-- 常用格式化符号
/*
%Y - 4位年份 (2025)
%y - 2位年份 (25)
%m - 月份,带前导零 (01-12)
%c - 月份,不带前导零 (1-12)
%d - 日期,带前导零 (01-31)
%e - 日期,不带前导零 (1-31)
%H - 24小时制 (00-23)
%h - 12小时制 (01-12)
%i - 分钟 (00-59)
%s - 秒 (00-59)
%W - 星期几完整名称 (Sunday)
%a - 星期几缩写 (Sun)
*/
-- 格式化示例
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); -- 2025-01-01
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i:%s'); -- 2025/01/01 00:00:00
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日'); -- 2025年01月01日
SELECT DATE_FORMAT(NOW(), '%W, %M %d, %Y'); -- Wednesday, January 01, 2025
-- 时间戳格式化
SELECT DATE_FORMAT(FROM_UNIXTIME(1735660800), '%Y-%m-%d %H:%i:%s');时间戳存储设计
数据库表设计时如何存储时间戳
SQL
-- 方式1:使用INT存储秒级时间戳
CREATE TABLE events (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(100),
created_at INT UNSIGNED, -- 秒级时间戳
updated_at INT UNSIGNED
);
-- 方式2:使用BIGINT存储毫秒时间戳
CREATE TABLE events_ms (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(100),
created_at BIGINT UNSIGNED, -- 毫秒级时间戳
updated_at BIGINT UNSIGNED
);
-- 方式3:使用TIMESTAMP类型(推荐)
CREATE TABLE events_ts (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 方式4:使用DATETIME类型
CREATE TABLE events_dt (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(100),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- 插入数据
INSERT INTO events (event_name, created_at, updated_at)
VALUES ('事件1', UNIX_TIMESTAMP(), UNIX_TIMESTAMP());时间戳查询技巧
使用时间戳进行各种查询操作
SQL
-- 查询今天的数据
SELECT * FROM events
WHERE DATE(FROM_UNIXTIME(created_at)) = CURDATE();
-- 查询最近7天的数据
SELECT * FROM events
WHERE created_at >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY));
-- 查询本月的数据
SELECT * FROM events
WHERE YEAR(FROM_UNIXTIME(created_at)) = YEAR(NOW())
AND MONTH(FROM_UNIXTIME(created_at)) = MONTH(NOW());
-- 按日期分组统计
SELECT
DATE(FROM_UNIXTIME(created_at)) as date,
COUNT(*) as count
FROM events
GROUP BY DATE(FROM_UNIXTIME(created_at))
ORDER BY date;
-- 时间范围查询
SELECT * FROM events
WHERE created_at BETWEEN UNIX_TIMESTAMP('2025-01-01')
AND UNIX_TIMESTAMP('2025-01-31 23:59:59');
-- 计算时间差(秒)
SELECT TIMESTAMPDIFF(SECOND, FROM_UNIXTIME(created_at), NOW()) as seconds_ago
FROM events;
-- 转换为其他时区显示
SELECT CONVERT_TZ(FROM_UNIXTIME(created_at), '+00:00', '+08:00') as beijing_time
FROM events;最佳实践
- •推荐使用BIGINT存储毫秒时间戳,避免2038年问题
- •查询时尽量在应用层计算时间戳范围,避免在索引列上使用函数
- •TIMESTAMP类型会自动转换为当前会话时区,注意时区设置
- •使用DATETIME DEFAULT CURRENT_TIMESTAMP可以自动记录创建时间
常见问题
TIMESTAMP和DATETIME有什么区别?
TIMESTAMP范围是1970-2038年,受时区影响,占用4字节。DATETIME范围是1000-9999年,不受时区影响,占用8字节。推荐使用DATETIME存储,或使用BIGINT存储毫秒时间戳。
MySQL时间戳是秒还是毫秒?
UNIX_TIMESTAMP()返回秒级时间戳。MySQL没有内置函数直接获取毫秒时间戳,可以用ROUND(UNIX_TIMESTAMP(NOW(3)) * 1000)获取毫秒。
FROM_UNIXTIME为什么返回NULL?
FROM_UNIXTIME在时间戳超出范围时返回NULL。TIMESTAMP类型的范围是1970-01-01 00:00:01到2038-01-19 03:14:07。超出范围请使用DATETIME或BIGINT存储。
如何处理时区问题?
1) 数据库连接设置时区:SET time_zone = '+08:00'; 2) 存储使用UTC时间戳,显示时转换;3) 使用CONVERT_TZ函数转换时区。