1. 程式人生 > >SQL 計算西方一些特殊節日

SQL 計算西方一些特殊節日

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

[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 +
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 @[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,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 @[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,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 @[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,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 @[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,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 @[email protected]+1
END

SELECT * FROM @t_res

hType yy          hKey                                     hDate                   wDay
----- ----------- ---------------------------------------- ----------------------- -----------
S     2010        Passover                                 2010-03-30 00:00:00.000 3
S     2010        Easter                                   2010-04-04 00:00:00.000 1
S     2010        OEaster                                  2010-03-22 00:00:00.000 2
S     2010        Chanukah                                 2010-12-01 00:00:00.000 4
S     2010        TishaBAv                                 2010-07-20 00:00:00.000 3
S     2010        TuBishvat                                2010-01-30 00:00:00.000 7
S     2010        YomHaAtzmaut                             2010-04-19 00:00:00.000 2
S     2010        YomHaAtzmaut                             2010-04-19 00:00:00.000 2

相關推薦

SQL 計算西方一些特殊節日

/* 2011.3.23 this can be stored in file system or data table. */ DECLARE @x_SPEC XML SET @x_SPEC =     ' <root>     <item>   

orale sql一些特殊sql示例

1、rowid(行標示符)概述 rowid是一個用來唯一標記表中行的偽列。它是物理表中行資料的內部地址(唯一),包含兩個地址,其一為指向資料表中包含該行的塊所存放資料檔案的地址,另一個是可以直接定位到資料行自身的這一行在資料塊中的地址 orale 刪除相同的資料

SQL 中單引號 和一些特殊字元的處理

為了防止程式SQL語句錯誤以及SQL注入,單引號必須經過處理。有2種辦法: 1、使用引數,比如SELECT * FROM yourTable WHERE name = @name; 在JAVA中就是用預處理PreparedStatement來新增引數。 2、如果不

SQL Server查詢中特殊字符的處理方法

下劃線 包括 舉例 art 劃線 一個 表達 com ase SQL Server查詢中,經常會遇到一些特殊字符,比如單引號“‘”等,這些字符的處理方法,是SQL Server用戶都應該需要知道的。 我們都知道SQL Server查詢過程中,單引號“‘”是特殊字符,所以在S

java基本類型(數值範圍):浮點的底層表示定義,float計算一些

方法 -1 att ieee754 符號位 無法 字符類 數值計算 小數 Java八種基本類型: 六種數字類型(四個整數型,兩個浮點型), 一種字符類型, 一種布爾型。 詳細例如以下 1、整數:包含int,short,byte,long

如何查找Linux中一些特殊數據類型定義,比如pid_t和uid_t(轉)

分享 文件 技術分享 定義 log 相關 uid linux源碼 pid 1. 查看man手冊,找到pid_t,可以通過getpid函數來看 2. 打開sys/types.h 3. 打開bits/types.h 4.

簡化動態MERGE的SQL計算

動態merge 更新 table acl 實現 iss 可用 src sso MSSQL。ORACLE等數據庫支持MERGE語句更新表。但表結構未知時,因為缺乏集合類數據。用存儲過程獲得表結構再動態拼出SQL很麻煩,代碼會有幾十行之多;相同原因,用J

最全的常用正則表達式大全——包括校驗數字、字符、一些特殊的需求等等

反斜杠 -1 正則表達 所有 2個 嵌套 pan span 至少 轉載:http://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html 一、校驗數字的表達式 1 數字:^[0-9]*$ 2 n位的數字:^\d{n

android中一些特殊字符(如:←↑→↓等箭頭符號)的Unicode碼值

lin gb2312 ring clu itl app lan orien lam 在項目中,有時候在一些控件(如Button、TextView)中要添加一些符號,如下圖所示: 這個時候可以使用圖片的方式來顯示,不過這

決策樹算法(五)——處理一些特殊的分類

字典 如果 span items 分類 lis 函數 可能 一個 在之前的決策樹算法中我們已經講解了從數據集構造決策樹算法的功能模塊。 首先是創建數據集,然後計算香農熵,然後基於最好的屬性值劃分數據集,由於特征值可能多於兩個,因此可能存在大於兩個分支的數據集劃分。第一次劃

(轉)最全的常用正則表達式大全——包括校驗數字、字符、一些特殊的需求等

需求 至少 xxxxx 0.00 下劃線 最全的 電話 使用 字符串 一、校驗數字的表達式 1 數字:^[0-9]*$ 2 n位的數字:^\d{n}$ 3 至少n位的數字:^\d{n,}$ 4 m-n位的數字:^\d{m,n}$ 5 零和非零開頭的數字:^(0|[1-

linux的cut、sort_wc_uniq、tee_tr_split命令及一些特殊符號介紹

linux cut sort wc uniq tee shell特殊符號cut命令:1、* 任意個任意字符(這是一個通配符)2、? 任意一個字符3、 # 註釋字符4、 \ 脫義字符5、 | 管道符幾個和管道有關的命令:1、cut 分割,-d 分隔符 -f 指定段號 -c 指定第幾

通過pl/sql計算程序的運行時間

get mod tar ger this int || auth var 在sqlplus中運行sql語句或者pl/sql的時候如果需要統計運行的時間,只需要開啟set timing on選項即可。 SQL> set timing onSQL>SQL> s

python 中的一些特殊語法

python1.高階函數python支持函數式編程,它內置了一些特殊函數,這些函數具有這樣的函數式編程特性,可以使代碼更加簡潔。filter、reduce、map類似於上面的函數都可以用一個函數作為參數 filter原型:filter(function,序列)filter會依次對序列中的項執行function

SQL常見的一些面試題(太有用啦)

ali avatar max 一中 重要 綁定 for ast 狀況 SQL常見面試題 1.用一條SQL 語句 查詢出每門課都大於80 分的學生姓名 name kecheng fenshu張三 語文 81張三 數學 75李

去除SAP中的一些特殊字符

spa imp tran fields cat nbsp nat 正常 range ① 換行符,TAB KEY等的表示 在數據文件輸出的時候,有時候需要使各個字段間用TAB KEY進行分割。 那麽,TAB KEY在ABAP中是如何表示的,就是寫入一個TAB KEY嗎? 事

mybatis的一些特殊符號標識(大於,小於,等於,不等於)

pan AS 紅色 _id pro cda batis myba amp 特殊字符 替代符號(紅色基本為常用的) & &amp; < &lt; >

spring配置的一些特殊配置說明

pan bsp conf 說明 參數 beans 上下文 BE font 第二個 abstract =‘‘true‘ 如果你有一個(父)bean定義你希望僅僅作為模版使用,而這個定義說明了一個類,你必須把abstract參數設置為true,否則應用程序上下文將試圖預

IPv6的一些特殊地址

個人 ip路由 sem 鏈接 工作 檢驗 中繼 min 動態 IPv6的一些特殊地址 2008年7月3日第二次修正! 昨天是修正了地址部分,本想發上來的,沒來得及。今天修正了NDP協議,接下來會是路由和轉換部分。 總結一下各協議的精華:OSPF在於LSA,BGP在屬性

我的SQL筆記&一些練習題(一)

eat sid UNC score server 隔離性 回退 sql命令 sql數據庫 Oracle 數據庫使用的端口為:1521在Windows平臺下需保證 Oracle server xe 和 Oraclelistener 服務正常運行才可以連接到數據庫MySQL數據