您的位置:首页 > 数据库 > MySQL

MySQL:根据阳历获取农历日期函数

2013-11-06 12:44 423 查看
begin
DECLARE   v_OffSet         INT;
DECLARE   v_Lunar          INT;          # 农历年是否含闰月,几月是闰月,闰月天数,其它月天数
DECLARE   v_YearDays       INT;          # 农历年所含天数
DECLARE   v_MonthDays      INT;          # 农历月所含天数
DECLARE   v_LeapMonthDays  INT;          # 农历闰月所含天数
DECLARE   v_LeapMonth      INT;          # 农历年闰哪个月 1-12 , 没闰传回 0
DECLARE   v_LeapFlag       INT;          # 某农历月是否为闰月  1:是  0:不是
DECLARE   v_MonthNo        INT;          # 某农历月所对应的2进制数 如农历3月: 001000000000
DECLARE   i                INT;
DECLARE   j                INT;
DECLARE   k                INT;

DECLARE   v_Year           INT;          # i_SolarDay 对应的农历年
DECLARE   v_Month          INT;          # i_SolarDay 对应的农历月
DECLARE   v_Day            INT;          # i_SolarDay 对应的农历日

DECLARE   o_OutputDate     VARCHAR(25); # 返回值  格式:农历 ****年 **(闰)月 **日

DECLARE   e_ErrMsg         VARCHAR(200);
declare   v_j              int;
declare   v_temp_m         varchar(100);
declare   v_temp_d         varchar(100);

# -e_ErrDate        EXCEPTION;
#输入参数判断
/* IF i_SolarDay<TO_DATE('1900-01-31','YYYY-MM-DD') OR i_SolarDay>=TO_DATE('2050-01-23','YYYY-MM-DD') THEN
RAISE e_ErrDate;
END IF ;
*/

# i_SolarDay 到 1900-01-30(即农历1900-01-01的前一天) 的天数
# v_OffSet := TRUNC(i_SolarDay, 'DD') - TO_DATE('1900-01-30', 'YYYY-MM-DD');

DECLARE exit HANDLER FOR SQLEXCEPTION,SQLWARNING,NOT FOUND
begin
set o_OutputDate ='获取农历失败';
return o_OutputDate;
end;

set v_OffSet = DATEDIFF(i_SolarDay,str_to_date('1900-01-30', '%Y-%c-%d'));
# 确定农历年开始
set i = 1900;
WHILE i < 2050 AND v_OffSet > 0 DO
set v_YearDays = 348;    #  29*12 以每年12个农历月,每个农历月含29个农历日为基数
set v_LeapMonthDays = 0;
# 取出农历年是否含闰月,几月是闰月,闰月天数,其它月天数
# 如农历2001年: 0x0d954(16进制) -> 55636(10进制) -> 0 110110010101 0100(2进制)
# 1,2,4,5,8,10,12月大, 3,6,7,9,11月小, 4月为闰月,闰月小
SELECT DataInt INTO v_Lunar FROM SolarData WHERE YearId = i;
# 传回农历年的总天数
set j = 32768;            #   100000000000 0000 -> 32768
# 0 110110010101 0100 -> 55636(农历2001年)

# 依次判断v_Lunar年个月是否为大月,是则加一天
WHILE j > 8 Do       # 闰月另行判断 8 -> 0 000000000000 1000
set v_j = v_Lunar&j;
#IF BITAND(v_Lunar, j) + 0 > 0 then
if v_j+0 >0 then
set v_YearDays = v_YearDays + 1;
#v_YearDays := v_YearDays + 1;
END IF;
set j = j/2;            # 判断下一个月是否为大
END WHILE;

# 传回农历年闰哪个月 1-12 , 没闰传回 0   15 -> 1 0000
# v_LeapMonth := BITAND(v_Lunar, 15) + 0;
set v_LeapMonth = v_Lunar&15 + 0;

# 传回农历年闰月的天数 ,加在年的总天数上
IF v_LeapMonth > 0 THEN
# 判断闰月大小 65536 -> 1 000000000000 0000
#IF BITAND(v_Lunar, 65536)+0 > 0 THEN
if v_Lunar&65536 + 0 > 0 then
set v_LeapMonthDays = 30;
ELSE
set v_LeapMonthDays = 29;
END IF;
set v_YearDays = v_YearDays + v_LeapMonthDays;
END IF;

set  v_OffSet = v_OffSet - v_YearDays;
set i = i + 1;
END WHILE;

IF v_OffSet <= 0 THEN
# i_SolarDay 在所属农历年(即i年)中的第 v_OffSet 天
set v_OffSet = v_OffSet + v_YearDays;
set  i = i - 1;
END IF;

# 确定农历年结束
set v_Year = i;

# 确定农历月开始
set i = 1;
SELECT DataInt INTO v_Lunar FROM SolarData WHERE YearId = v_Year;

# 判断那个月是润月
# 如农历2001年 (55636,15 -> 0 1101100101010100, 1111 -> 4) 即润4月,且闰月小
set v_LeapMonth = v_Lunar&15 + 0;
set v_LeapFlag = 0;

WHILE i < 13 AND v_OffSet > 0 DO
# 判断是否为闰月
set v_MonthDays = 0;
IF (v_LeapMonth > 0 AND i = (v_LeapMonth + 1) AND v_LeapFlag = 0) THEN
# 是闰月
set i = i - 1;
set k = i;                # 保存是闰月的时i的值
set v_LeapFlag = 1;

# 传回农历年闰月的天数
#IF BITAND(v_Lunar, 65536)+0 > 0 THEN
if v_Lunar&65536+0 > 0 then
set  v_MonthDays = 30;
ELSE
set v_MonthDays = 29;
END IF;
ELSE
# 不是闰月
set  j = 1;
set  v_MonthNo = 65536;
# 计算 i 月对应的2进制数 如农历3月: 001000000000
WHILE j<= i DO
set v_MonthNo = v_MonthNo/2;
set j = j + 1;
END WHILE;
# 计算农历 v_Year 年 i 月的天数
#IF BITAND(v_Lunar, v_MonthNo)+0 > 0 THEN
if v_Lunar&v_MonthNo + 0 > 0 then
set v_MonthDays = 30;
ELSE
set v_MonthDays = 29;
END IF;
END IF;

# 解除闰月
IF v_LeapFlag = 1 AND i = v_LeapMonth +1 THEN
set  v_LeapFlag = 0;
END IF;
set v_OffSet = v_OffSet - v_MonthDays;
set i = i + 1;
END while;

IF v_OffSet <= 0 THEN
# i_SolarDay 在所属农历月(即i月)中的第 v_OffSet 天
set  v_OffSet = v_OffSet + v_MonthDays;
set  i = i - 1;
END IF;

# 确定农历月结束
set v_Month = i;
# 确定农历日结束
set v_Day = v_OffSet;
# 格式化返回值
set o_OutputDate =CONCAT(getNumYear(v_Year),'年');

IF k = i THEN
#set  o_OutputDate := o_OutputDate || LPAD(TO_CHAR(v_Month), 2, '0')||'(润)月 ';
set v_temp_m = concat(getNumMonth(v_Month),'(润)月 ');
ELSE
# o_OutputDate := o_OutputDate || LPAD(TO_CHAR(v_Month), 2, '0')||'月 ';
set v_temp_m = concat(getNumMonth(v_Month),'月');
END IF;

# o_OutputDate := o_OutputDate || LPAD(TO_CHAR(v_Day), 2, '0')||'日';
set v_temp_d = getNumDay(v_Day);
set o_OutputDate = CONCAT(CONCAT(o_OutputDate,v_temp_m),v_temp_d);

RETURN o_OutputDate;
END
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: