当前位置: 代码迷 >> Sql Server >> 西方一些特殊节日的计算,该如何解决
  详细解决方案

西方一些特殊节日的计算,该如何解决

热度:63   发布时间:2016-04-27 19:11:14.0
西方一些特殊节日的计算
刚刚写的,提取了一部分。比如复活节等。
关于性能, 我也知道分开每个写一个function好的多,呵呵。
旨在重用、动态加载、程序结构上的一个设计思想。


SQL code
/*fcuandy2011.3.23this can be stored in file system or data table.*/DECLARE @x_SPEC XMLSET @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 @[email protected]        SET @[email protected] + 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 + [email protected] + 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 @[email protected]        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)) * (([email protected])/11))        SET @j = (@y + @y/4 + @i + 2 - @cent + @cent/4 ) % 7        SET @emo = 3 + (@[email protected] + 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 @[email protected]        SET @itXML = @x        SET @itKey = @key                SET @sql=  @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')        EXEC sp_executeSQL @sql,[email protected] INT,@outDay DATETIME OUT'',@y,@PassoverD1 OUT                SET @y = @y + 1        EXEC sp_executeSQL @sql,[email protected] 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 @[email protected]        SET @itXML = @x        SET @itKey = @key                        SET @sql=  @itXml.value(''(//item[key=sql:variable("@itKey")]/script)[1]'',''NVARCHAR(2000)'')        EXEC sp_executeSQL @sql,[email protected] 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 @[email protected]        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,[email protected] INT,@outDay DATETIME OUT'',@y,@PassoverD1 OUT        SET @y = @year        EXEC sp_executeSQL @sql,[email protected] 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 @[email protected]        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,[email protected] 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 DATETIMESET @year= 2010  --param from outside/*INSERT holidays SPEC*/DECLARE @i INT, @cnt INTSELECT @i = 1, @cnt = @x_SPEC.value('count(//key)','INT')WHILE @i<= @cntBEGIN    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,[email protected] INT,@outDay DATETIME OUT',@year,@hDay OUT    ELSE        EXEC sp_executeSQL @sql,[email protected] 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 @[email protected]+1ENDSELECT * FROM @t_res
  相关解决方案