萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 日期時間函數完整速查手冊:計算、提取、格式化、時區實戰

日期時間處理是業務開發高頻需求。本文系統整理 MySQL 5.7/8.0 核心日期時間函數,分類為**當前時間獲取、日期時間拆解、運算運算、格式化輸出、時區轉換、範圍查詢**六大類,附帶實戰範例與效能提示。

一、獲取當前日期時間

函數返回類型特性示例輸出
NOW()DATETIME語句執行開始時刻(事務內固定)2023-08-08 14:30:45
SYSDATE()DATETIME函數**實際執行**時刻(動態)2023-08-08 14:30:45.000001
CURDATE() / CURRENT_DATE()DATE當前日期2023-08-08
CURTIME() / CURRENT_TIME()TIME當前時間14:30:45
UTC_DATE()DATEUTC 日期2023-08-08
UTC_TIME()TIMEUTC 時間06:30:45
UTC_TIMESTAMP()DATETIMEUTC 日期時間2023-08-08 06:30:45

NOW() vs SYSDATE():事務/存儲過程中 NOW() 固定為開始時間,SYSDATE() 每次調用取當前時間,影響複制一致性,建議統一用 NOW()。

二、日期時間拆解提取


SET @dt = '2023-08-08 14:30:45.123456';

SELECT DATE(@dt);        -- 2023-08-08
SELECT TIME(@dt);        -- 14:30:45.123456
SELECT YEAR(@dt);        -- 2023
SELECT QUARTER(@dt);     -- 3
SELECT MONTH(@dt);       -- 8
SELECT WEEK(@dt);        -- 31 (模式 0)
SELECT DAY(@dt);         -- 8
SELECT DAYOFMONTH(@dt);  -- 8
SELECT DAYOFWEEK(@dt);   -- 3 (1=週日)
SELECT WEEKDAY(@dt);     -- 1 (0=週一)
SELECT DAYOFYEAR(@dt);   -- 220
SELECT HOUR(@dt);        -- 14
SELECT MINUTE(@dt);      -- 30
SELECT SECOND(@dt);      -- 45
SELECT MICROSECOND(@dt); -- 123456

三、日期時間運算

函數語法示例結果
DATE_ADD / + INTERVALDATE_ADD(date, INTERVAL expr unit)DATE_ADD('2023-01-01', INTERVAL 1 MONTH)2023-02-01
DATE_SUB / - INTERVALDATE_SUB(date, INTERVAL expr unit)'2023-01-01' - INTERVAL 1 DAY2022-12-31
DATEDIFFDATEDIFF(date1, date2)DATEDIFF('2023-08-08', '2023-08-01')7 (date1 - date2)
TIMEDIFFTIMEDIFF(time1, time2)TIMEDIFF('14:30:00', '12:00:00')02:30:00
TIMESTAMPDIFFTIMESTAMPDIFF(unit, datetime1, datetime2)TIMESTAMPDIFF(DAY, '2023-01-01', '2023-08-08')219 (精確單位)
ADDDATEADDDATE(date, INTERVAL expr unit)ADDDATE('2023-01-01', 10)2023-01-11
SUBDATESUBDATE(date, INTERVAL expr unit)SUBDATE('2023-01-01', 10)2022-12-22

INTERVAL 單位:MICROSECOND、SECOND、MINUTE、HOUR、DAY、WEEK、MONTH、QUARTER、YEAR、SECOND_MICROSECOND、MINUTE_MICROSECOND、MINUTE_SECOND、HOUR_MICROSECOND、HOUR_SECOND、HOUR_MINUTE、DAY_MICROSECOND、DAY_SECOND、DAY_MINUTE、DAY_HOUR、YEAR_MONTH。

四、格式化輸出與解析


-- 格式化輸出
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');  -- 2023-08-08 14:30:45
SELECT DATE_FORMAT(NOW(), '%Y%m%d%H%i%s');       -- 20230808143045
SELECT TIME_FORMAT('14:30:45', '%H點%i分%s秒');   -- 14點30分45秒

-- 常用格式符
%Y 4位年  %y 2位年  %m 月(01-12)  %c 月(1-12)
%d 日(01-31)  %e 日(1-31)  %H 時(00-23)  %k 時(0-23)
%i 分(00-59)  %s 秒(00-59)  %f 微秒(000000-999999)
%W 週名  %a 週名縮寫  %M 月名  %b 月名縮寫

-- 字串解析為日期
SELECT STR_TO_DATE('2023-08-08 14:30:45', '%Y-%m-%d %H:%i:%s');
SELECT STR_TO_DATE('08/08/2023', '%m/%d/%Y');

五、時區處理


-- 查看當前時區
SELECT @@session.time_zone, @@global.time_zone;
-- SYSTEM / +08:00 / UTC / Asia/Shanghai

-- 會話級設定時區
SET time_zone = '+08:00';
SET time_zone = 'Asia/Shanghai';

-- 全局設定(需權限,配置檔永久)
SET GLOBAL time_zone = '+08:00';
-- my.cnf: default-time-zone = '+08:00'

-- 轉換時區
SELECT CONVERT_TZ('2023-08-08 14:30:00', '+00:00', '+08:00');  -- 2023-08-08 22:30:00

六、範圍查詢最佳實踐(索引友好)


-- ❌ 錯誤:函數包裹欄位 → 索引失效
SELECT * FROM orders WHERE DATE(create_time) = '2023-08-08';
SELECT * FROM orders WHERE YEAR(create_time) = 2023 AND MONTH(create_time) = 8;

-- ✅ 正確:欄位裸露,利用索引範圍掃描
SELECT * FROM orders
WHERE create_time >= '2023-08-08 00:00:00'
  AND create_time <  '2023-08-09 00:00:00';

-- 近 30 天
SELECT * FROM orders
WHERE create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY);

-- 本月
SELECT * FROM orders
WHERE create_time >= DATE_FORMAT(NOW(), '%Y-%m-01')
  AND create_time < DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 1 MONTH), '%Y-%m-01');

-- 本週(週一開始)
SELECT * FROM orders
WHERE create_time >= DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) DAY)
  AND create_time < DATE_ADD(DATE_SUB(NOW(), INTERVAL WEEKDAY(NOW()) DAY), INTERVAL 7 DAY);

七、常見陷阱與避坑

陷阱後果正確做法
WHERE DATE(col) = '...'全表掃描,索引失效用範圍查詢 col >= '...' AND col < '...'
BETWEEN '2023-08-01' AND '2023-08-31' 用於 DATETIME漏掉 23:59:59 後的毫秒col >= '2023-08-01' AND col < '2023-09-01'
NOW() 在複制/備份中不一致主從數據不一致用 SYSDATE() 或啟用 sysdate_is_now=1
TIMESTAMP 2038 年問題32 位有符號整數溢出改用 DATETIME(支援到 9999 年)
隱式轉型字串比較日期索引失效、結果錯誤用 STR_TO_DATE 統一格式
copyright © 萬盛學電腦網 all rights reserved