儲存每年農曆資訊的十六進位編碼與整數值:
CREATE TABLE SolarData (
yearid INT NOT NULL,
data CHAR(7) NOT NULL,
dataint INT NOT NULL
);
-- 插入 1900-2049 年資料(略,完整腳本含 150 年數據)
INSERT INTO SolarData VALUES (1900, '0x04bd8', 19416), (1901, '0x04ae0', 19168), ...;
輸入公曆日期 @solarday,輸出農曆字串(如 2023-1-15)。演算法步驟:
@offset;
CREATE FUNCTION Proc_ConvertLunar(@solarday DATETIME)
RETURNS NVARCHAR(30) AS BEGIN
DECLARE @offset INT, @i INT, @j INT, @ydays INT, @mdays INT;
DECLARE @mleap INT, @mleapnum INT, @bleap SMALLINT, @temp INT;
DECLARE @year NVARCHAR(10), @month NVARCHAR(10), @day NVARCHAR(10);
DECLARE @outputdate NVARCHAR(30);
SET @offset = DATEDIFF(day, '1900-01-30', @solarday);
SET @i = 1900;
WHILE @i < 2050 AND @offset > 0 BEGIN
SET @ydays = 348; SET @mleapnum = 0;
SELECT @ilunar = dataint FROM solardata WHERE yearid = @i;
-- 計算年總天數(位運算解析 dataint)
SET @j = 32768;
WHILE @j > 8 BEGIN
IF @ilunar & @j > 0 SET @ydays = @ydays + 1;
SET @j = @j / 2;
END
-- 處理閏月
SET @mleap = @ilunar & 15;
IF @mleap > 0 BEGIN
IF @ilunar & 65536 > 0 SET @mleapnum = 30 ELSE SET @mleapnum = 29;
SET @ydays = @ydays + @mleapnum;
END
SET @offset = @offset - @ydays; SET @i = @i + 1;
END
IF @offset <= 0 BEGIN SET @offset = @offset + @ydays; SET @i = @i - 1; END
SET @year = @i;
-- 確定月、日(邏輯類同,略)
SET @outputdate = @year + '-' + @month + '-' + @day;
RETURN @outputdate;
END
在基礎版基礎上,輸出如 二〇二三年閏二月初三 格式:
-- 生成 1900-2020 年對照表
CREATE TABLE LunarCalenderContrastTable (Calender DATETIME, Lunar DATETIME);
DECLARE @i INT = DATEDIFF(day, '1900-1-1', '2020-1-1');
WHILE @i > 0 BEGIN
DECLARE @day NVARCHAR(10) = DATEADD(d, @i, '1900-1-1');
INSERT INTO LunarCalenderContrastTable VALUES (@day, dbo.Proc_ConvertLunar(@day));
SET @i = @i - 1;
END
-- 查詢生日對應公曆
CREATE FUNCTION GetCalender(@month VARCHAR(3), @day VARCHAR(3), @now DATETIME)
RETURNS DATETIME AS BEGIN
DECLARE @dates VARCHAR(12) = CAST(YEAR(@now) AS VARCHAR) + '-' + @month + '-' + @day;
RETURN (SELECT Calender FROM LunarCalenderContrastTable WHERE Lunar = @dates);
END
-- 測試
SELECT dbo.GetCalender('2', '7', GETDATE());
—— 作者:佚名