日期:2014-05-18  浏览次数:20481 次

西方一些特殊节日的计算
刚刚写的,提取了一部分。比如复活节等。
关于性能, 我也知道分开每个写一个function好的多,呵呵。
旨在重用、动态加载、程序结构上的一个设计思想。


SQL code

/*
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(