根据日期计算出星期几的几种算法
由于坑爹的DEV系统未装自带函数库 不得不在网上各处寻觅算法。
大概有如下几种方法:
一:常用公式
W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D
Y是年份数,D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天。
二:蔡勒(Zeller)公式
w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
公式中的符号含义如下,w:星期;c:世纪;y:年(两位数); m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。
相比于通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。
三:对蔡勒(Zeller)公式的改进
相比于另外一个通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。不过,笔者给出的通用计算公式似乎更加简洁(包括运算过程)。现将公式列于其下:
W=[y/4]+r (y/7)-2r(c/4)+m’+d
公式中的符号含义如下,r ( )代表取余,即只要余数部分;m’是m的修正数,现给出1至12月的修正数1’至12’如下:(1’,10’)=6;(2’,3’,11’)=2;(4’,7’)=5;5’=0;6’=3;8’=1;(9’,12’)=4(注意:在笔者给出的公式中,y为润年时1’=5;2’=1)。其他符号与蔡勒(Zeller)公式中的含义相同。
四:基姆拉尔森计算公式
W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
在公式中d表示日期中的日数,m表示月份数,y表示年数。
注意:在公式中有个与其他公式不同的地方:
把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。
这里值得一提:后来发现用这公式算出结果总有问题,换为蔡勒了,虽然有如下一说,但未亲测。
基姆拉尔森星期公式=W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
在公式中d表示日期中的日数+1,m表示月份数,y表示年数。
故应该为:
基姆拉尔森星期公式=W= (d+1+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7
在公式中d表示日期中的日数,m表示月份数,y表示年数。
贴出转换代码:
DATA: NUM TYPE I.
DATA: COUNT TYPE P.
DATA: L_C TYPE c LENGTH 2.
DATA: L_Y TYPE c LENGTH 2.
DATA: L_M TYPE c LENGTH 2.
DATA: L_D TYPE c LENGTH 2.
CLEAR NUM.
CLEAR L_C.
CLEAR L_Y.
CLEAR L_M.
CLEAR L_D.
*截取/BIC/ZPOS_JYSJ字段获得日期的世纪,年,月,日。
L_C = SOURCE_FIELDS-/BIC/ZPOS_JYSJ+6(2).
L_Y = SOURCE_FIELDS-/BIC/ZPOS_JYSJ+8(2).
L_M = SOURCE_FIELDS-/BIC/ZPOS_JYSJ+10(2).
L_D = SOURCE_FIELDS-/BIC/ZPOS_JYSJ+12(2).
*若为1、2月要看作上一年的13、14月来计算
IF L_M = '01' or L_M = '02'.
L_M = L_M + 12.
IF L_Y = '00'.
L_C = L_C - 1.
L_Y = '99'.
ELSE.
L_Y = L_Y - 1.
ENDIF.
ENDIF.
*蔡勒(Zeller)公式w=(y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1)% 7
COUNT = L_Y + TRUNC( ( L_Y / 4 ) ) + TRUNC( ( L_C / 4 ) ) - 2 * L_C + TRUNC( ( 26 * ( L_M + 1 ) / 10 ) ) + L_D - 1.
NUM = COUNT MOD 7.
CASE NUM.
WHEN 1.
RESULT = '一'.
WHEN 2.
RESULT = '二'.
WHEN 3.
RESULT = '三'.
WHEN 4.
RESULT = '四'.
WHEN 5.
RESULT = '五'.
WHEN 6.
RESULT = '六'.
WHEN 0.
RESULT = '日'.
WHEN OTHERS.
WRITE: / 'Others Number'.
ENDCASE.