🗄️
TimeCraft

MySQL Timestamp

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函数转换时区。