首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 日期處理大全:格式化、推算 (年初/季初/月初/週初)、常用片段

     編輯:關於SqlServer

一、日期格式化輸出


DECLARE @dt DATETIME = GETDATE();

-- 短日期 YYYY-M-D
SELECT REPLACE(CONVERT(VARCHAR(10), @dt, 120), '-0', '-');

-- 長日期 YYYY年MM月DD日 (方法 1: STUFF)
SELECT STUFF(STUFF(CONVERT(CHAR(8), @dt, 112), 5, 0, '年'), 8, 0, '月') + '日';

-- 長日期 YYYY年MM月DD日 (方法 2: DATENAME)
SELECT DATENAME(year, @dt) + '年' + DATENAME(month, @dt) + '月' + DATENAME(day, @dt) + '日';

-- 長日期 YYYY年M月D日 (無前導零)
SELECT DATENAME(year, @dt) + '年' + CAST(DATEPART(month, @dt) AS VARCHAR) + '月' + DATENAME(day, @dt) + '日';

-- 完整日期時間 YYYY-MM-DD HH:MI:SS.mmm
SELECT CONVERT(CHAR(10), @dt, 120) + ' ' + CONVERT(CHAR(12), @dt, 114);

二、日期邊界推算 (通用函數化建議)


DECLARE @dt DATETIME = GETDATE(), @n INT = 3;

-- 1. 年初 / 年尾
SELECT DATEADD(year, DATEDIFF(year, 0, @dt), 0) AS YearStart;
SELECT DATEADD(day, -1, DATEADD(year, DATEDIFF(year, 0, @dt) + 1, 0)) AS YearEnd;

-- 2. 季初 / 季尾
DECLARE @q INT = DATEPART(quarter, @dt);
SELECT DATEADD(quarter, DATEDIFF(quarter, 0, @dt), 0) AS QuarterStart;
SELECT DATEADD(day, -1, DATEADD(quarter, DATEDIFF(quarter, 0, @dt) + 1, 0)) AS QuarterEnd;

-- 3. 月初 / 月尾 (最穩健)
SELECT DATEADD(month, DATEDIFF(month, 0, @dt), 0) AS MonthStart;
SELECT DATEADD(day, -1, DATEADD(month, DATEDIFF(month, 0, @dt) + 1, 0)) AS MonthEnd;
-- ❌ 錯誤寫法:DATEADD(month, 1, DATEADD(day, -DAY(@dt), @dt))  -- 2/28/2023 → 3/28/2023 (非月尾)

-- 4. 週任意一天 (以週日為第 1 天)
SELECT DATEADD(day, @n - DATEPART(weekday, @dt), @dt);

-- 5. 週任意一天 (指定週一為第 1 天)
SELECT DATEADD(day, @n - (DATEPART(weekday, @dt) + @@DATEFIRST - 2) % 7 - 1, @dt);

三、實務高頻片段

需求SQL 片段
年齡計算DATEDIFF(year, @Birth, GETDATE()) - CASE WHEN DATEADD(year, DATEDIFF(year, @Birth, GETDATE()), @Birth) > GETDATE() THEN 1 ELSE 0 END
本月工作日數見下方函數
兩日期相差月數DATEDIFF(month, @Start, @End) - CASE WHEN DAY(@Start) > DAY(@End) THEN 1 ELSE 0 END
下一個工作日遞迴 CTE 或迴圈跳過週末
季度標籤'Q' + CAST(DATEPART(quarter, @dt) AS VARCHAR) + ' ' + CAST(YEAR(@dt) AS VARCHAR)

四、工作日計算函數 (排除週末)


CREATE FUNCTION dbo.fn_WorkDays(@Start DATE, @End DATE)
RETURNS INT
AS BEGIN
    DECLARE @Days INT = DATEDIFF(day, @Start, @End) + 1;
    DECLARE @Weeks INT = @Days / 7;
    DECLARE @Remain INT = @Days % 7;
    DECLARE @StartDow INT = DATEPART(weekday, @Start); -- 受 @@DATEFIRST 影響
    RETURN @Weeks * 5 + 
           CASE 
               WHEN @StartDow + @Remain - 1 <= 5 THEN @Remain
               WHEN @StartDow <= 5 THEN 6 - @StartDow
               ELSE 0 
           END;
END;

五、SQL Server 2008+ 新型別優勢

  • DATE:3 bytes,純日期,無時區困擾。
  • TIME:100ns 精度,純時間。
  • DATETIME2:取代 DATETIME,範圍更大、精度更高、儲存更小 (6-8 bytes)。
  • DATETIMEOFFSET:含時區位移,全球化系統必備。
  • EOMONTH(@dt) (2012+):直接取得月尾日期。
  • DATEFROMPARTS(y, m, d) (2012+):組合日期無字串轉換風險。

結語

日期處理核心原則:儲存用標準型別 (DATETIME2/DATE)、運算用 DATEDIFF/DATEADD 邊界法、輸出用 CONVERT 格式化、避免字串拼接運算。將常用邊界推算封裝為內聯函數/視圖,全專案統一呼叫,消除時區、語言、閏年等邊界 Bug。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved