西方一些特殊节日的计算

fcuandy 2011-03-23 03:44:04
加精
刚刚写的,提取了一部分。比如复活节等。
关于性能, 我也知道分开每个写一个function好的多,呵呵。
旨在重用、动态加载、程序结构上的一个设计思想。



/*
fcuandy
2011.3.23
this can be stored in file system or data table.
*/
DECLARE @x_SPEC XML
SET @x_SPEC =
'
<root>
<item>
<id>1</id>
<key>Passover</key>
<refKey></refKey>
<script>
DECLARE @y INT
,@hy INT
,@mat INT
,@leap INT
,@fday NUMERIC(10,2)
,@ffday NUMERIC(10,2)
,@dow INT
,@cent INT
,@leapExp INT
,@day INT
,@mo INT
,@PassoverDay DATETIME
SET @y=@year
SET @hy=@y + 3760
SET @mat = (12 * @hy + 17) %19
SET @leap = @hy %4
SET @fday = 32 + 4343 / 98496.0 + @mat + @mat * (272953 / 492480.0) + @leap / 4.0
SET @fday = @fday - @hy * (313 / 98496.0)
SET @ffday = @fday - CAST(@fday AS INT)
SET @dow = (3 * @hy + 5*@leap + CAST(@fday AS INT) + 5) % 7

IF @dow IN (2,4,6)
SET @fday = @fday + 1
ELSE IF @dow=1 AND @mat>6 AND @ffday>= 1367 / 2160.0
SET @fday = @fday + 2
ELSE IF @dow=0 AND @mat>11 AND @ffday>=23269 / 25920.0
SET @fday = @fday + 1

SET @cent = CAST(@y/100.0 AS INT)
SET @leapExp = CAST((3 * @cent - 5)/4.0 AS INT)
IF @y > 1582
SET @fday = @fday + @leapExp


SET @day = CAST(@fday AS INT)
SET @mo = 3

IF @day>153
BEGIN
SET @mo = 8
SET @day = @day - 153
END
ELSE IF @day>122
BEGIN
SET @mo = 7
SET @day = @day -122
END
ELSE IF @day > 92
BEGIN
SET @mo = 6
SET @day = @day - 92
END
ELSE IF @day > 61
BEGIN
SET @mo = 5
SET @day = @day - 61
END
ELSE IF @day > 31
BEGIN
SET @mo = 4
SET @day = @day - 31
END

SET @PassoverDay = RTRIM(@y) + ''-''+RTRIM(@mo) + ''-'' + RTRIM(@Day)
SET @outDay = @PassoverDay
</script>
</item>
<item>
<id>2</id>
<key>Easter</key>
<refKey></refKey>
<script>
DECLARE @y INT
,@cent INT
,@i INT
,@j INT
,@k INT
,@met INT
,@emo INT
,@eday INT
,@Easter DATETIME
SET @y=@year
SET @cent = @y /100
SET @met = @y % 19
SET @k = (@cent - 17) / 25
SET @i = (@cent - @cent / 4 - (@cent - @k)/3 + 19 * @met + 15)%30
SET @i = @i - (@i/28) * (1 - (@i/28) * (29/(@i+1)) * ((21-@met)/11))
SET @j = (@y + @y/4 + @i + 2 - @cent + @cent/4 ) % 7
SET @emo = 3 + (@i-@j + 40) / 44
SET @eday = @i - @j + 28 - 31 * (@emo / 4)

SET @Easter = RTRIM(@y) + ''-''+RTRIM(@emo) + ''-'' + RTRIM(@eday)
SET @outDay = @Easter
</script>
</item>
<item>
<id>3</id>
<key>OEaster</key>
<refKey></refKey>
<script>
DECLARE @y INT
,@i INT
,@j INT
,@met INT
,@emo INT
,@eday INT
,@leap INT
,@OEaster DATETIME

SET @y = @year
SET @leap = @y /100 - @y / 400 -2
SET @met = @y % 19
SET @i = (19 * @met + 15) % 30
SET @j = (@y + @y /4 + @i) % 7
SET @emo = 3 + (@i - @j + 40) / 44
SET @eday = @i - @j + 28 - 31 * (@emo /4)

SET @OEaster = RTRIM(@y) + ''-''+RTRIM(@emo) + ''-'' + RTRIM(@eday)
SET @outDay = @OEaster
</script>
</item>
<item>
<id>4</id>
<key>Chanukah</key>
<refKey>Passover</refKey>
<script>
DECLARE @y INT
,@days INT
,@PassoverD1 DATETIME
,@PassoverD2 DATETIME
,@Chanukah DATETIME
,@sql NVARCHAR(2000)
,@itXml XML
,@itKey VARCHAR(40)

SET @y=@year
SET @itXML = @x
SET @itKey = @key

SET @sql= @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@PassoverD1 OUT

SET @y = @y + 1
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@PassoverD2 OUT

SET @days = DATEDIFF(dd,@PassoverD1,@PassoverD2)

IF @days IN (355, 385)
SET @outDay = DATEADD(dd,246,@PassoverD1)
ELSE
SET @outDay = DATEADD(dd,245,@PassoverD1)

</script>
</item>
<item>
<id>5</id>
<key>TishaBAv</key>
<refKey>Passover</refKey>
<script>
DECLARE @y INT
,@dw INT
,@Passover DATETIME
,@sql NVARCHAR(2000)
,@itXml XML
,@itKey VARCHAR(40)

SET @y=@year
SET @itXML = @x
SET @itKey = @key

SET @sql= @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@Passover OUT

SET @dw = DATEPART(DW,@Passover)
IF @dw = 7
SET @outDay = DATEADD(dd,113, @Passover)
ELSE
SET @outDay = DATEADD(dd,112, @Passover)
</script>
</item>
<item>
<id>6</id>
<key>TuBishvat</key>
<refKey>Passover</refKey>
<script>
DECLARE @y INT
,@days INT
,@PassoverD1 DATETIME
,@PassoverD2 DATETIME
,@sql NVARCHAR(2000)
,@itXml XML
,@itKey VARCHAR(40)

SET @y=@year
SET @itXML = @x
SET @itKey = @key

SET @y = @y - 1
SET @sql= @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@PassoverD1 OUT
SET @y = @year
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@PassoverD2 OUT

SET @days = DATEDIFF(dd,@PassoverD1,@PassoverD2)
IF @days > 355
SET @outDay = DATEADD(dd,-89, @PassoverD2)
ELSE
SET @outDay = DATEADD(dd,-59, @PassoverD2)
</script>
</item>
<item>
<id>7</id>
<key>YomHaAtzmaut</key>
<refKey>Passover</refKey>
<script>
DECLARE @y INT
,@dw INT
,@Passover DATETIME
,@sql NVARCHAR(2000)
,@itXml XML
,@itKey VARCHAR(40)

SET @y=@year
SET @itXML = @x
SET @itKey = @key

IF @y = 2004
SET @outDay = CONVERT(DATETIME,''2004-04-27'',120)
ELSE
BEGIN
SET @sql= @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')
EXEC sp_executeSQL @sql,N''@year INT,@outDay DATETIME OUT'',@y,@Passover OUT
SET @dw = DATEPART(DW,@Passover)
IF @dw = 1
SET @outDay = DATEADD(dd,18,@Passover)
ELSE IF @dw = 7
SET @outDay = DATEADD(dd,19,@Passover)
ELSE
SET @outDay = DATEADD(dd,20,@Passover)
END
</script>
</item>
</root>
'

DECLARE @t_res TABLE(
hType VARCHAR, --F,M,S,O
yy INT,
hKey VARCHAR(40),
hDate DATETIME,
wDay AS DATEPART(DW,hDate)
)

DECLARE @key VARCHAR(40)
,@refKey VARCHAR(40)
,@year INT
,@sql NVARCHAR(2000)
,@hDay DATETIME

SET @year= 2010 --param from outside

/*
INSERT holidays SPEC
*/
DECLARE @i INT, @cnt INT
SELECT @i = 1, @cnt = @x_SPEC.value('count(//key)','INT')

WHILE @i<= @cnt
BEGIN
SELECT @sql=T.x.value('script[1]','NVARCHAR(2000)') ,
@key = T.x.value('key[1]','VARCHAR(40)'),
@refKey = T.x.value('refKey[1]','VARCHAR(40)')
/*FROM @x_SPEC.nodes('root/item[position()=sql:variable("@i")]') AS T(x)*/
FROM @x_SPEC.nodes('root/item[id=sql:variable("@i")]') AS T(x)

IF @refKey = ''
EXEC sp_executeSQL @sql,N'@year INT,@outDay DATETIME OUT',@year,@hDay OUT
ELSE
EXEC sp_executeSQL @sql,N'@year INT,@x XML,@key VARCHAR(40),@outDay DATETIME OUT',@year,@x_SPEC,@refKey,@hDay OUT

INSERT @t_res(hType,yy,hKey,hDate) SELECT 'S',@year,@key,@hDay

SET @i=@i+1
END

SELECT * FROM @t_res

...全文
4944 233 打赏 收藏 转发到动态 举报
写回复
用AI写文章
233 条回复
切换为时间正序
请发表友善的回复…
发表回复
lmhtingna 2011-08-19
  • 打赏
  • 举报
回复
看看怎么样!
--reply by CSDN Study V1.0.0.3 (starts_2000)
onmywayqiu 2011-04-03
  • 打赏
  • 举报
回复
不错的想法 呵呵
l396634084 2011-04-01
  • 打赏
  • 举报
回复
j6j67uj6
KLL 2011-04-01
  • 打赏
  • 举报
回复
jfzr
hjl13960 2011-04-01
  • 打赏
  • 举报
回复
hhaannddaann 2011-03-31
  • 打赏
  • 举报
回复
收藏了~~
zxwnumb 2011-03-31
  • 打赏
  • 举报
回复
很好。。。留下
finish222 2011-03-31
  • 打赏
  • 举报
回复
这么多节日好麻烦啊
radarbqradarbq 2011-03-31
  • 打赏
  • 举报
回复
好东西,了解
userqidong 2011-03-31
  • 打赏
  • 举报
回复
呵呵,中国人用处不大
FANGFANGSIME 2011-03-30
  • 打赏
  • 举报
回复
看看 学习学习
ghost13650249503 2011-03-29
  • 打赏
  • 举报
回复
好下旧正是止旧旧下卓日子
fjiog 2011-03-29
  • 打赏
  • 举报
回复
谢谢楼主分享这么好的资源
zjmcly 2011-03-29
  • 打赏
  • 举报
回复
很实用啊!
techexcel123 2011-03-29
  • 打赏
  • 举报
回复
system or data table.
fcuandy 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 179 楼 tsinlei 的回复:]

引用 11 楼 fcuandy 的回复:
引用 9 楼 wxf163 的回复:

为什么不把数据直接存在数据库里


西方有很多节日,需要动态算法。 就像中国算节气一样,如春至, 白露。


“春至”?只听说过春分、夏至。

还是把中国的节气先弄清楚了再搞西方的吧~
[/Quote]

你只听过春风,说明你见识少。


春至
拼音:
解释: 1.即春分。 2.春天来到。


(1).即春分。《管子·轻重己》:“以冬日至始,数九十二日,谓之春至。”参见“ 春分 ”。

(2).春天来到。 唐 李白 《桓公井诗》:“秋来桐暂落,春至桃还发。” 唐 李绅 《柳》诗之一:“人事推移无旧物,年年春至緑垂丝。”
----------------------------------------------



别的方面我不敢说, 但如果你一直死扣概念,做技术这块不会有长进的.
azzui 2011-03-28
  • 打赏
  • 举报
回复
怎么说我0分啊,我是来拿分地。
azzui 2011-03-28
  • 打赏
  • 举报
回复
好多啊,就是看不懂。
lswys456 2011-03-28
  • 打赏
  • 举报
回复
不懂?!?!
孤飞俊驰 2011-03-28
  • 打赏
  • 举报
回复
这东西也有算法?
加载更多回复(99)

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧