在MySQL里做时间转换,核心是根据数据的存储形态选择合适的函数。时间数据通常以三种形式存在:标准日期时间类型(如DATETIME)、Unix时间戳(整数秒)、以及不规范字符串。不同形态之间的互转如果处理不当,不仅查询结果错误,还可能让索引失效。下面通过常用函数和场景示例,说明如何正确地进行时间转换。

一、字符串转日期时间:STR_TO_DATE
当外部系统传来的时间是不规范文本,例如“2024-03-15 14:30:00”之外的“15/03/2024 2:30 PM”,就需要用STR_TO_DATE把字符串按指定格式解析成DATETIME。它的第一个参数是原始字符串,第二个是格式模板,模板里的百分号符号代表具体的年月日时分秒位置。
如果格式不匹配,函数会返回NULL,因此在写入前最好用此法校验。下面示例把日/月/年加十二小时制时间转成标准格式:
SELECT STR_TO_DATE('15/03/2024 02:30 PM', '%d/%m/%Y %h:%i %p') AS dt;
-- 输出:2024-03-15 14:30:00
常见格式符包括%Y四位年、%y两位年、%m两位月、%d两位日、%H二十四小时制小时、%h十二小时制小时、%i分钟、%s秒。掌握这些符号就能应对绝大多数文本时间。注意,若原字符串含中文或其他干扰字符,应先使用REPLACE清理再转换。
二、Unix时间戳转日期:FROM_UNIXTIME
很多日志系统以整数秒保存时间,也就是Unix时间戳。MySQL用FROM_UNIXTIME将其转为DATETIME,反向则用UNIX_TIMESTAMP把日期转回时间戳。这两个函数在做跨系统数据同步时非常实用。
以下代码展示如何把时间戳转成可读时间,并进一步格式化成“年-月-日 时:分”的形式:
SELECT FROM_UNIXTIME(1710508200) AS normal_time,
DATE_FORMAT(FROM_UNIXTIME(1710508200), '%Y-%m-%d %H:%i') AS fmt_time;
-- normal_time: 2024-03-15 14:30:00
-- fmt_time: 2024-03-15 14:30
使用FROM_UNIXTIME时需注意时区。MySQL的time_zone参数会影响输出结果,如果应用服务器与数据库时区不一致,转换出的时间会偏差数小时。建议在连接后统一执行SET time_zone = '+08:00',保证前后端时间一致。
三、日期格式化输出:DATE_FORMAT
报表统计经常要求把DATETIME显示成“2024年03月”或“03/15”等样式,这时用DATE_FORMAT。它和STR_TO_DATE正好相反,是把日期按模板变成字符串。
示例中将当前时间分别输出为年月、完整中文样式:
SELECT DATE_FORMAT(NOW(), '%Y年%m月') AS ym,
DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s') AS full_fmt;
该函数不会改变原字段类型,仅用于控制显示。若对格式化后的列加索引查询则无效,因为索引基于原DATETIME值。正确做法是在WHERE里对原列用区间比较,SELECT里再格式化。
四、提取与计算:日期分量与间隔
有时只需取年份、月份,或计算两个时间差。MySQL提供YEAR、MONTH、DAY函数提取分量,用TIMESTAMPDIFF算差值,用DATE_ADD做加减。
下面例子查出订单表中2024年3月之后的记录,并标记已过去多少天:
SELECT order_id,
TIMESTAMPDIFF(DAY, create_time, NOW()) AS past_days
FROM orders
WHERE create_time >= '2024-03-01 00:00:00';
这些函数配合转换函数,能完成复杂的时间逻辑。比如先用STR_TO_DATE规整文本,再用TIMESTAMPDIFF算龄期。但要避免在WHERE中对列套函数,否则索引失效,应改成范围条件。
五、隐式转换与性能避坑
MySQL在比较字符串和日期时会做隐式转换,例如WHERE datetime_col = '2024-3-15'能跑通,但若是WHERE DATE(datetime_col) = '2024-03-15'则无法用索引。此外,用UNIX_TIMESTAMP(col)对比也会弃用索引。
推荐写法是对原列直接给区间:
SELECT * FROM log WHERE log_time >= '2024-03-15 00:00:00' AND log_time < '2024-03-16 00:00:00';
这样优化器能用上B+树索引,查询速度在百万级数据下可提升十倍以上。时间转换不只是语法问题,更关系系统吞吐,写SQL时应始终优先考虑原列操作。
六、总结
MySQL时间转换围绕STR_TO_DATE、FROM_UNIXTIME、DATE_FORMAT以及提取计算函数展开。明确数据类型、避开隐式转换、控制时区,就能写出准确且高效的查询。实际开发中建议封装常用转换逻辑到视图或存储过程,减少业务端处理负担。