zoukankan      html  css  js  c++  java
  • SQL Server时间粒度系列----第7节日历数据表详解

     
    将该系列涉及到的时间粒度以及分钟以下的粒度做个总结,如以下表格:
    时间粒度
     
     
       
     
     
     
     
    纳秒
     
     
     
     
     
     
     
     
    微妙
     
     
     
     
     
     
     
     
    毫秒
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
    分钟
    日期分钟数(整数)*
    日期分钟*
    日内分钟数
     
     
     
     
     
    小时
    日期小时数(整数)
    日期小时
    日内小时数
     
     
     
     
     
    日期天数(整数)
    日期天
    周内日索引
    旬内日索引
    月内日索引
    季内日索引
    年内日索引 日期内日索引
    日期周数(整数)
    日期周
    旬内周索引
    月内周索引
    季内周索引
    年内周索引
    日期内周索引
     
    日期旬数(整数)
    日期旬
    月内旬索引 季内旬索引
    年内旬索引
    日期内旬索引
     
     
    日期月数(整数)
    日期月
    季内月索引
    年内月索引
    日期内月索引
     
     
     
    日期季数(整数)
    日期季
    年内季索引
    日期内季索引
     
     
     
     
    日期年数(整数)
    日期年
    日期内年索引
     
     
     
     
     
    注意:
    1、最左边第一列表示时间粒度,其左边列的空格表示没有相应的参数,有文字表示有相对应的功能函数。
    2、带有数的描述从0开始计数,带有索引则是从1开始计数。
    3、日期天和日期天数(整数)是一对一映射的,一个日期对应一个整数。日期周、日期旬、日期月、日期季、日期年都是其时间粒度的基准日期的。
    4、日期内相关的索引这个日期内是个范围区间[0001-01-01,9999-12-31],时间粒度日、周、旬、月、季、年的有关日期内的相关索引都是基于这个范围区间计算的。
    5、带有*符号的表示谨慎使用。
     
    时间维度有关功能函数
        
        根据时间粒度有关表述中总结的表格,将提供的时间粒度有关功能函数分为:日期时间通用有关函数、分钟时间粒度有关函数、 小时时间粒度有关函数、周以上时间粒度基准日期有关函数、天时间粒度有关函数、周时间粒度有关函数、旬时间粒度有关函数、月时间粒度有关函数、季时间粒度有关函数、年时间粒度有关函数。日期时间通用函数主要包括获取最小日期时间、获取最大日期时间、获取默认基准日期以及获取有效日期时间和有效日期时间数的函数。周以上时间粒度基准日期就是获取周、旬、月、季、年和日期的相关基准日期,都是其时间刻度的第一天所对应的日期范围。
     
        日期时间通用有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_GetMinDateTime', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_GetMinDateTime
    END
    GO
     
    --==================================
    -- 功能: 获取最小日期时间
    -- 说明: 运行在SQL Server 2008+。
    --       结果值为date数据类型。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_GetMinDateTime();
    --==================================
    CREATE FUNCTION dbo.ufn_GetMinDateTime
    (
     
    ) RETURNS DATE
        --$Encode$--
    AS 
    BEGIN
        RETURN '0001-01-01';
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_GetMaxDateTime', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_GetMaxDateTime
    END
    GO
     
    --==================================
    -- 功能: 获取最最大日期时间
    -- 说明: 运行在SQL Server 2005+。
    --       结果值为datetime数据类型。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_GetMaxDateTime();
    --==================================
    CREATE FUNCTION dbo.ufn_GetMaxDateTime
    (
     
    ) RETURNS DATETIME
        --$Encode$--
    AS 
    BEGIN
        RETURN '9999-12-31 23:59:59';
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_GetDefaultBasedate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_GetDefaultBasedate
    END
    GO
     
    --==================================
    -- 功能: 获取默认基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       默认设置为"1900-01-01",调整范围区间为[1753-01-01,9999-12-31];可以调整为该区间任意一个日期,不能为该区间以外的。
    --       结果值为datetime数据类型。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_GetDefaultBasedate();
    --==================================
    CREATE FUNCTION dbo.ufn_GetDefaultBasedate
    (
     
    ) RETURNS DATETIME
        --$Encode$--
    AS 
    BEGIN
        RETURN '1900-01-01';
    END
    GO
     
    -- Test Code
    SELECT dbo.ufn_GetMinDateTime() AS 'MinDateTime'
        ,dbo.ufn_GetMaxDateTime() AS 'MaxDateTime'
        ,dbo.ufn_GetDefaultBasedate() AS 'DefaultBasedate';
    GO
     
    IF OBJECT_ID(N'dbo.ufn_GetValidDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_GetValidDate;
    END
    GO
     
    --==================================
    -- 功能: 获取有效日期
    -- 说明: 运行在SQL Server 2005+。
    --         指定的日期如果为NULL或者小于默认基准日期时则直接返回默认基准日期。
    --       结果值为datetime数据类型。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_GetValidDate('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_GetValidDate
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS DATETIME
        --$Encode$--
    BEGIN
        DECLARE @dtmDefaultBasedate AS DATETIME;
        SET @dtmDefaultBasedate = dbo.ufn_GetDefaultBasedate();
     
        IF @dtmDate IS NULL OR @dtmDate < @dtmDefaultBasedate
        BEGIN
            RETURN @dtmDefaultBasedate;
        END
     
        RETURN @dtmDate;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_GetValidDateNum', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION ufn_GetValidDateNum;
    END
    GO
     
    --==================================
    -- 功能: 获取有效日期数
    -- 说明: 运行在SQL Server 2005+。
    --       指定的日期数如果为NULL或负数,则默认设置为0。
    --       结果值为datetime数据类型。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @@intDateNum = dbo.ufn_GetValidDateNum(-1)
    --==================================
    CREATE FUNCTION dbo.ufn_GetValidDateNum
    (
        @intDateNum INT            -- 指定的日期数
    ) RETURNS INT
        --$Encode$--
    BEGIN
        IF @intDateNum IS NULL OR @intDateNum < 0
        BEGIN
            RETURN 0;
        END
     
        RETURN @intDateNum;
    END
    GO
     
    -- Test Code
    SELECT dbo.ufn_GetValidDate('1899-01-01') AS 'ValidDate'
        ,dbo.ufn_GetValidDateNum(0) AS 'ValidDateNum';
    GO
     
    以上5个通用函数的测试效果,如下图:
     
        分钟时间粒度有关函数,T-SQL代码如下:
     IF OBJECT_ID(N'dbo.ufn_Minutes', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Minutes;
    END
    GO
     
    --==================================
    -- 功能: 获得指定的日期时间基于默认基准日期的总小时数(一个整数值)
    -- 说明: 运行在SQL Server 2005 +。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intMinutes = dbo.ufn_Minutes('5983-01-24 02:07:00.000');
    --==================================
    CREATE FUNCTION dbo.ufn_Minutes
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS INT
    AS
    BEGIN
        RETURN DATEDIFF(MINUTE, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Minutes2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Minutes2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的日期时间
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0。
    --       如果指定的整数值大于“5983-01-24 02:07:00”对应的整数值时,则其值默认设置为“5983-01-24 02:07:00”对应的整数值。
    --       结果值为基于默认基准日期开始计数的日期。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Minutes2Date(947033) -- '2008-01-14 17:00'
    --==================================
    CREATE FUNCTION dbo.ufn_Minutes2Date
    (
        @intMinutes INT                -- 指定的整数值
    ) RETURNS DATETIME
    AS
    BEGIN
        SET @intMinutes = dbo.ufn_GetValidDateNum(@intMinutes);
     
        DECLARE @intMinutesMax AS INT;
        SET @intMinutesMax = dbo.ufn_Minutes('5983-01-24 02:07:00');
     
        IF @intMinutes >= @intMinutesMax
        BEGIN
            SET @intMinutes = @intMinutesMax;
        END
     
        RETURN DATEADD(MINUTE, @intMinutes, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_MinutesOfDay', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_MinutesOfDay;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间基于所在当前日午夜零时的分钟数
    -- 功能: 运行在SQL Server 2005+。
    --       结果值从0开始计数,包括0、1、2、3、1439。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @sintMinutesOfDay = dbo.fn_MinutesOfDay(GETDATE());
    --==================================
    CREATE FUNCTION dbo.ufn_MinutesOfDay
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS SMALLINT
    AS
    BEGIN
        RETURN DATEPART(HOUR, @dtmDate) * 60 + DATEPART(MINUTE, @dtmDate);
    END
    GO
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-02-14 02:14:18';
     
    SELECT
        @dtmDate AS 'The Current DateTime'
        ,dbo.ufn_Minutes(@dtmDate) AS 'Minutes'
        ,dbo.ufn_Minutes2Date(dbo.ufn_Minutes(@dtmDate)) AS 'DateTime Mapping Minutes'
        ,dbo.ufn_MinutesOfDay(@dtmDate) AS 'Minutes Of The Current Day';
     
    SET @dtmDate = '2016-05-20 05:20:48';
     
    SELECT 
        @dtmDate AS 'The Current DateTime'
        ,dbo.ufn_Minutes(@dtmDate) AS 'Minutes'
        ,dbo.ufn_Minutes2Date(dbo.ufn_Minutes(@dtmDate)) AS 'DateTime Mapping Minutes'
        ,dbo.ufn_MinutesOfDay(@dtmDate) AS 'Minutes Of The Current Day';
    GO
     
    以上3个函数的测试效果,如下图:
     
        小时时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Hours', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Hours;
    END
    GO
     
    --==================================
    -- 功能: 获得指定的日期时间基于基准日期的总小时数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intHours = dbo.ufn_Hours('2008-01-14 17:45')  -- 947033
    --==================================
    CREATE FUNCTION dbo.ufn_Hours 
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEDIFF(HOUR, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Hours2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Hours2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于基准日期对应的日期时间
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0;
    --       如果指定的整数值大于“9999-12-31 23:00:00”对应的整数值时,则其值默认设置为“9999-12-31 23:00:00”对应的整数值。
    --       结果值为基于默认基准日期开始计数的日期。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.fn_Hours2Date(947033) -- '2008-01-14 17:00'
    --==================================
    CREATE FUNCTION dbo.ufn_Hours2Date 
    (
        @intHours INT                        -- 指定的整数值
    ) RETURNS DATETIME
    AS
    BEGIN
        SET @intHours = dbo.ufn_GetValidDateNum(@intHours);
     
        DECLARE @intMaxHours AS INT;
        SET @intMaxHours = dbo.ufn_Hours(dbo.ufn_GetMaxDateTime());
     
        IF @intHours >= @intMaxHours
        BEGIN
            SET @intHours = @intMaxHours;
        END
     
        RETURN DATEADD(HOUR, @intHours, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
     
    IF OBJECT_ID(N'dbo.ufn_HoursOfDay', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_HoursOfDay;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期日期基于所在当期日午夜零时的小时数
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从0开始计数,包括0、1、2、……、23。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintHoursOfDay = dbo.ufn_HoursOfDay(GETDATE());
    --==================================
    CREATE FUNCTION dbo.ufn_HoursOfDay
    (
        @dtmDate DATETIME            -- 指定的日期时间
    )
    RETURNS TINYINT
    AS
    BEGIN
        RETURN DATEPART(HOUR, @dtmDate);
    END
    GO
     
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2014-02-14 6:12:00'
     
    SELECT 
        @dtmDate AS 'The Current DateTime'
        ,dbo.ufn_Hours(@dtmDate) AS 'Hours'
        ,dbo.ufn_Hours2Date(dbo.ufn_Hours(@dtmDate)) AS 'DateTime Mapping Hours'
        ,dbo.ufn_HoursOfDay(@dtmDate) AS 'Hours Of The Current Day';
     
    SET @dtmDate = '2014-05-20 8:18:00'
     
    SELECT
        @dtmDate AS 'The Current DateTime'
        ,dbo.ufn_Hours(@dtmDate) AS 'Hours'
        ,dbo.ufn_Hours2Date(dbo.ufn_Hours(@dtmDate)) AS 'DateTime Mapping Hours'
        ,dbo.ufn_HoursOfDay(@dtmDate) AS 'Hours Of The Current Day'
    GO
     
    以上3个函数的测试效果,如下图:
     
        周以上时间粒度基准日期有关函数,T-SQL代码如下:   
    IF OBJECT_ID(N'dbo.ufn_FirstDayOfPeriodTable', 'IF') IS NOT NULL
    BEGIN
        DROP FUNCTION ufn_FirstDayOfPeriodTable;
    END
    GO
     
    --==================================
    -- 功能: 旬首日索引表
    -- 说明: 运行在SQL Server 2005+。
    --       结果值为表数据,列名为FirstDayOfPeriod,其字段列(域)值包括1、11、21这3个数字,其字段列值对应每年每个旬的第一天。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT * FROM dbo.ufn_FirstDayOfPeriodTable();
    --==================================
    CREATE FUNCTION dbo.ufn_FirstDayOfPeriodTable
    (
     
    ) RETURNS TABLE
        --$Encode$--
        RETURN ( 
            SELECT 1 AS FirstDayOfPeriod
            UNION ALL SELECT 11
            UNION ALL SELECT 21
        );
    GO
     
    IF OBJECT_ID(N'dbo.ufn_FirstDayOfPeriod', N'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_FirstDayOfPeriod;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前旬的第一个日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、11、21。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT @tintFirstDayOfPeriod = ufn_FirstDayOfPeriod(@dtmDate);
    --==================================
    CREATE FUNCTION dbo.ufn_FirstDayOfPeriod
    (
        @dtmDate DATETIME                    -- 指定的日期时间
     
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE @tintFirstDayOfPeriod AS TINYINT;
        SET @tintFirstDayOfPeriod = 1;
     
        SELECT TOP 1 @tintFirstDayOfPeriod = FirstDayOfPeriod
        FROM dbo.ufn_FirstDayOfPeriodTable()
        WHERE FirstDayOfPeriod <= DAY(@dtmDate)
        ORDER BY FirstDayOfPeriod DESC;
     
        RETURN @tintFirstDayOfPeriod;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_BasedateOfPeriod', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_BasedateOfPeriod;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在旬的基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       结果值为旬基准日,即每个旬第一天对应的日期。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmBasedateOfPeriod = dbo.ufn_BasedateOfPeriod('2016-01-12');
    --==================================
    CREATE FUNCTION dbo.ufn_BasedateOfPeriod
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS DATETIME
        --$Encode$--
    BEGIN
        RETURN CONVERT(DATETIME, CAST(YEAR(@dtmDate) AS CHAR(4)) + '-' + CAST(MONTH(@dtmDate) AS VARCHAR(2)) + '-' + CAST(dbo.ufn_FirstDayOfPeriod(@dtmDate) AS VARCHAR(2)), 120);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_BasedateOfMonth', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_BasedateOfMonth;
    END
    GO
     
    --==================================
    -- 功能: 获取指定日期时间所在月的基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       结果值为月基准日,即每个月第一天对应的日期。 
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmBasedateOfMonth = dbo.ufn_BasedateOfMonth('2016-01-12');
    --==================================
    CREATE FUNCTION dbo.ufn_BasedateOfMonth
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS DATETIME
        --$Encode$--
    BEGIN
        RETURN CONVERT(DATETIME, CAST(YEAR(@dtmDate) AS CHAR(4)) + '-' + CAST(MONTH(@dtmDate) AS VARCHAR(2)) + '-' + CAST(1 AS CHAR(1)), 120);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_FirstMonthOfQuarterTable', 'IF') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_FirstMonthOfQuarterTable;
    END
    GO
     
    --==================================
    -- 功能: 季首月索引表
    -- 说明: 运行在SQL Server 2005+。
    --       结果值为表数据,列名为FirstMonthOfQuarter,其字段列(域)值包括1、4、7、10这4个数字,其字段列值对应每年每个季的第一个月份。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT * FROM dbo.ufn_FirstMonthOfQuarterTable();
    --==================================
    CREATE FUNCTION dbo.ufn_FirstMonthOfQuarterTable
    (
    ) RETURNS TABLE
        --$Encode$--
        RETURN ( 
            SELECT 1 AS FirstMonthOfQuarter
            UNION ALL SELECT 4
            UNION ALL SELECT 7
            UNION ALL SELECT 10
        );
    GO
     
    IF OBJECT_ID(N'dbo.ufn_FirstMonthOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_FirstMonthOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前季度的第一个月索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、4、7、10。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT @tintFirstMonthOfQuarter = ufn_FirstMonthOfQuarter(@dtmDate);
    --==================================
    CREATE FUNCTION dbo.ufn_FirstMonthOfQuarter
    (
        @dtmDate DATETIME                    -- 指定的日期时间
     
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE @tintFirstMonthOfQuarter AS TINYINT;
        SET @tintFirstMonthOfQuarter = 1;
     
        SELECT TOP 1 @tintFirstMonthOfQuarter = FirstMonthOfQuarter
        FROM dbo.ufn_FirstMonthOfQuarterTable() 
        WHERE FirstMonthOfQuarter <= MONTH(@dtmDate)
        ORDER BY FirstMonthOfQuarter DESC;
     
        RETURN @tintFirstMonthOfQuarter;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_BasedateOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_BasedateOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前季的季基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       结果值格式"XXXX-01-01",包括:"XXXX-01-01"、"XXXX-04-01"、"XXXX-07-01"、"XXXX-10-01"。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT @tintFirstMonthOfQuarter = ufn_BasedateOfQuarter(@dtmDate);
    --==================================
    CREATE FUNCTION dbo.ufn_BasedateOfQuarter
    (
        @dtmDate DATETIME                    -- 指定的日期时间
     
    ) RETURNS DATETIME
        --$Encode$--
    BEGIN
        RETURN  CONVERT(DATETIME, CAST(YEAR(@dtmDate) AS CHAR(4)) + '-' + CAST(dbo.ufn_FirstMonthOfQuarter(@dtmDate) AS VARCHAR(2)) + '-' + CAST(1 AS CHAR(1)), 120);
    END
    GO
     
     
    IF OBJECT_ID(N'dbo.ufn_BasedateOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_BasedateOfYear;
    END
    GO
    --==================================
    -- 功能: 获取指定日期时间所在年的基准日期
    -- 说明: 结果值是每个年的基准日,每个年第一天对应的日期。 
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmBasedateOfYear = dbo.ufn_BasedateOfYear('2016-01-12');
    --==================================
    CREATE FUNCTION dbo.ufn_BasedateOfYear
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS DATETIME
        --$Encode$--
    BEGIN
        RETURN CONVERT(DATETIME, CAST(YEAR(@dtmDate) AS CHAR(4)) + '-' + CAST(1 AS CHAR(1)) +  '-' + CAST(1 AS char(1)), 120);
    END
    GO
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-14';
     
    SELECT 
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_BasedateOfPeriod(@dtmDate) AS 'Basedate Of The Current Period'
        ,dbo.ufn_BasedateOfMonth(@dtmDate) AS 'Basedate Of The Current Month'
        ,dbo.ufn_BasedateOfQuarter(@dtmDate) AS 'Basedate Of the Current Quarter'
        ,dbo.ufn_BasedateOfYear(@dtmDate) AS 'Basedate Of the Current Year'
        ,dbo.ufn_GetMinDateTime() AS 'Basedate Of the Current Date';
     
    SET @dtmDate = '2016-4-30';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_BasedateOfPeriod(@dtmDate) AS 'Basedate Of The Current Period'
        ,dbo.ufn_BasedateOfMonth(@dtmDate) AS 'Basedate Of The Current Month'
        ,dbo.ufn_BasedateOfQuarter(@dtmDate) AS 'Basedate Of the Current Quarter'
        ,dbo.ufn_BasedateOfYear(@dtmDate) AS 'Basedate Of the Current Year'
        ,dbo.ufn_GetMinDateTime() AS 'Basedate Of the Current Date';
    GO
     
    以上几个函数的测试效果,如下图:
        
        天时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Days', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Days;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总天数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intDays = dbo.ufn_Days('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Days
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEDIFF(DAY, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Days2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Days2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0。
    --       如果指定的整数值大于最大日期时间对应的整数值时,则其值默认设置为最大日期时间对应的整数值。
    --       结果值为基于默认基准日期开始计数的日期。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Days2Date(39459) --'2008-01-14'
    --==================================
    CREATE FUNCTION dbo.ufn_Days2Date 
    (
        @intDays INT                -- 指定的整数值
    ) RETURNS DATETIME
        --$Encode$--
    AS
    BEGIN
        SET @intDays = dbo.ufn_GetValidDateNum(@intDays);
     
        DECLARE @intMaxDays AS INT;
        SET @intMaxDays = dbo.ufn_Days(dbo.ufn_GetMaxDateTime());
     
        IF @intDays >= @intMaxDays
        BEGIN
            SET @intDays = @intMaxDays;
        END
     
        RETURN DATEADD(DAY, @intDays, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_DayOfWeek', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfWeek;
    END
    GO
     
    --==================================
    -- 功能: 获取指定日期时间的所在当前周的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1到7,分别对应从周一到周日,该值与@@DATEFISRT配置函数值保持一致。
    --       使用(@@datefirt + datepart(weekday, @dtmDate))%7的结果值从2、3、4、5、6、0、1
    --       分别对应周一、周二、周三、周四、周五、周六、周日。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_DayOfWeek('2017-01-07') -- 4(表示星期四)
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfWeek
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE    @tintRemainder AS TINYINT;
        SET @tintRemainder = (@@DATEFIRST + DATEPART(WEEKDAY, @dtmDate)) % 7;
        IF @tintRemainder <= 1
        BEGIN
            SET @tintRemainder = @tintRemainder + 6;
        END
        ELSE
        BEGIN
            SET @tintRemainder = @tintRemainder - 1;
        END
     
        RETURN @tintRemainder;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_DayOfPeriod', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfPeriod;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间在当前旬的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3、……、8、9、10、11。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intPeriods = dbo.ufn_DayOfPeriod('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfPeriod
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    AS
    BEGIN
        --RETURN DAY(@dtmDate) - (dbo.ufn_PeriodOfMonth(@dtmDate) - 1) * 10;
        RETURN DATEDIFF(DAY, dbo.ufn_BasedateOfPeriod(@dtmDate), @dtmDate) + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_DayOfMonth', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfMonth;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前月的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3.……、28、29、30、31。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @sintDayOfYear = dbo.ufn_DayOfMonth('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfMonth
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        RETURN DAY(@dtmDate);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_DayOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在季的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3.……、89、90、91、92。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfQuarter
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        RETURN DATEDIFF(DAY, dbo.ufn_BasedateOfQuarter(@dtmDate), @dtmDate) + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_DayOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfYear;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前年的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3.……、364、365、366。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @sintDayOfYear = dbo.ufn_DayOfYear('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfYear
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS SMALLINT
        --$Encode$--
    BEGIN
        RETURN DATEPART(DAYOFYEAR, @dtmDate);
    END
    GO
     
     
    IF OBJECT_ID(N'dbo.ufn_DayOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_DayOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前日期的日索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3.……、3652057、3652058、3652059。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @inntDayOfDate = dbo.ufn_DayOfDate('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_DayOfDate
    (
        @dtmDate DATETIME
    ) RETURNS INT
        --$Encode$--
    BEGIN
        RETURN DATEDIFF(DAY, dbo.ufn_GetMinDateTime(), dbo.ufn_GetValidDate(@dtmDate)) + 1
    END
    GO
     
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-14';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Days(@dtmDate) AS 'Days'
        ,dbo.ufn_Days2Date(dbo.ufn_Days(@dtmDate)) AS 'Date Mapping Days'
        ,dbo.ufn_DayOfWeek(@dtmDate) AS 'Day Of The Current Week'
        ,dbo.ufn_DayOfPeriod(@dtmDate) AS 'Day Of The Current Period'
        ,dbo.ufn_DayOfMonth(@dtmDate) AS 'Day Of The Current Month'
        ,dbo.ufn_DayOfQuarter(@dtmDate) AS 'Day Of The Current Quarter'
        ,dbo.ufn_DayOfYear(@dtmDate) AS 'Day Of The Current Year'
        ,dbo.ufn_DayOfDate(@dtmDate) AS 'Day Of The Current Date';
     
    SET @dtmDate = '2016-03-14';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Days(@dtmDate) AS 'Days'
        ,dbo.ufn_Days2Date(dbo.ufn_Days(@dtmDate)) AS 'Date Mapping Days'
        ,dbo.ufn_DayOfWeek(@dtmDate) AS 'Day Of The Current Week'
        ,dbo.ufn_DayOfPeriod(@dtmDate) AS 'Day Of The Current Period'
        ,dbo.ufn_DayOfMonth(@dtmDate) AS 'Day Of The Current Month'
        ,dbo.ufn_DayOfQuarter(@dtmDate) AS 'Day Of The Current Quarter'
        ,dbo.ufn_DayOfYear(@dtmDate) AS 'Day Of The Current Year'
        ,dbo.ufn_DayOfDate(@dtmDate) AS 'Day Of The Current Date';
    GO
     
    以上几个函数的测试效果,如下图:
     
        周时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Weeks', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Weeks;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总周数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intDays = dbo.ufn_Weeks('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Weeks
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        RETURN dbo.ufn_Days(@dtmDate) / 7;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Weeks2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Weeks2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0;
    --       如果指定的整数值大于最大日期时间对应的整数值时,则其值默认设置为最大日期时间对应的整数值。
    --       结果值为基于默认基准日期开始计数的周基准日期,也就是周一对应的日期。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Weeks2Date(39459);
    --==================================
    CREATE FUNCTION dbo.ufn_Weeks2Date
    (
        @intWeeks INT                    -- 指定的整数值
    ) RETURNS DATETIME
        --$Encode$--
    AS
    BEGIN
        SET @intWeeks = dbo.ufn_GetValidDateNum(@intWeeks);
     
        DECLARE @intMaxWeeks AS INT;
        SET @intMaxWeeks = dbo.ufn_Weeks(dbo.ufn_GetMaxDateTime());
     
        IF @intWeeks >= @intMaxWeeks
        BEGIN
            SET @intWeeks = @intMaxWeeks;
        END
     
        RETURN DATEADD(DAY, @intWeeks * 7, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_WeekOfPeriod', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_WeekOfPeriod;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前旬的周索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintWeekOfPeriod = dbo.ufn_WeekOfPeriod('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_WeekOfPeriod
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE @tintWeekOffsetOfPeriod AS TINYINT;
        SET @tintWeekOffsetOfPeriod = DATEDIFF(WEEK, dbo.ufn_BasedateOfPeriod(@dtmDate), @dtmDate);
     
        IF dbo.ufn_DayOfWeek(@dtmDate) = 7 AND @tintWeekOffsetOfPeriod >= 1
        BEGIN
            SET @tintWeekOffsetOfPeriod = @tintWeekOffsetOfPeriod - 1;
        END
     
        RETURN @tintWeekOffsetOfPeriod + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_WeekOfMonth', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_WeekOfMonth;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前月的周索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3、4、5
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintWeekOfMonth = dbo.ufn_WeekOfMonth('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_WeekOfMonth
    (
        @dtmDate DATETIME
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE @tintWeekOffsetOfMonth AS TINYINT;
        SET @tintWeekOffsetOfMonth = DATEDIFF(WEEK, dbo.ufn_BasedateOfMonth(@dtmDate), @dtmDate);
     
        IF dbo.ufn_DayOfWeek(@dtmDate) = 7 AND @tintWeekOffsetOfMonth >= 1
        BEGIN
            SET @tintWeekOffsetOfMonth = @tintWeekOffsetOfMonth - 1;
        END
     
        RETURN @tintWeekOffsetOfMonth + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_WeekOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_WeekOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前季的周索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、3、4、5、6、7、7、……。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintWeekOfQuarter = dbo.ufn_WeekOfQuarter('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_WeekOfQuarter
    (
        @dtmDate DATETIME
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        DECLARE @tintWeekOffsetOfQuarter AS TINYINT;
        SET @tintWeekOffsetOfQuarter = DATEDIFF(WEEK, dbo.ufn_BasedateOfQuarter(@dtmDate), @dtmDate);
     
        IF dbo.ufn_DayOfWeek(@dtmDate) = 7 AND @tintWeekOffsetOfQuarter >= 1
        BEGIN
            SET @tintWeekOffsetOfQuarter = @tintWeekOffsetOfQuarter - 1;
        END
     
        RETURN @tintWeekOffsetOfQuarter + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_WeekOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_WeekOfYear;
    END
    GO
     
    --==================================
    -- 功能: 获取指定日期属于当前年的周索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,一年最多1-53周。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_WeekOfYear('2016-01-07');
    --==================================
    CREATE FUNCTION dbo.ufn_WeekOfYear
    (
        @dtmDate DATETIME
    ) RETURNS TINYINT
        --$Encode$--
    AS
    BEGIN
        DECLARE @tintWeekOffsetOfYear AS TINYINT;
        SET @tintWeekOffsetOfYear = DATEDIFF(WEEK, dbo.ufn_BasedateOfYear(@dtmDate), @dtmDate);
     
        IF dbo.ufn_DayOfWeek(@dtmDate) = 7 AND @tintWeekOffsetOfYear >= 1
        BEGIN
            SET @tintWeekOffsetOfYear = @tintWeekOffsetOfYear - 1;
        END
     
        RETURN @tintWeekOffsetOfYear + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_WeekOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_WeekOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定日期属于当前日历的周索引
    -- 说明: 运行在SQL Server 2008+。
    --       结果值从1开始计数,包括1、2、3、4、……。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SELECT dbo.ufn_WeekOfDate('2016-01-07');
    --==================================
    CREATE FUNCTION dbo.ufn_WeekOfDate
    (
        @dtmDate DATETIME
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        DECLARE @intWeekOffsetOfDate AS INT;
        SET @intWeekOffsetOfDate = DATEDIFF(WEEK, dbo.ufn_GetMinDateTime(), @dtmDate);
     
        IF (@@DATEFIRST + DATEPART(WEEKDAY, @dtmDate)) % 7 = 1 AND @intWeekOffsetOfDate >= 1
        BEGIN
            SET @intWeekOffsetOfDate = @intWeekOffsetOfDate - 1;
        END
     
        RETURN @intWeekOffsetOfDate + 1;
    END
    GO
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-15';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Weeks(@dtmDate) AS 'Weeks'
        ,dbo.ufn_Weeks2Date(dbo.ufn_Weeks(@dtmDate)) AS 'Date Mapping Weeks'
        ,dbo.ufn_WeekOfPeriod(@dtmDate) AS 'Week Of The Current Period'
        ,dbo.ufn_WeekOfMonth(@dtmDate) AS 'Week Of The Current Month'
        ,dbo.ufn_WeekOfQuarter(@dtmDate) AS 'Week Of The Current Quarter'
        ,dbo.ufn_WeekOfYear(@dtmDate) AS 'Week Of The Current Year'
        ,dbo.ufn_WeekOfDate(@dtmDate) AS 'Week Of The Current Date';
     
    SET @dtmDate = '2016-01-31';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Weeks(@dtmDate) AS 'Weeks'
        ,dbo.ufn_Weeks2Date(dbo.ufn_Weeks(@dtmDate)) AS 'Date Mapping Weeks'
        ,dbo.ufn_WeekOfPeriod(@dtmDate) AS 'Week Of The Current Period'
        ,dbo.ufn_WeekOfMonth(@dtmDate) AS 'Week Of The Current Month'
        ,dbo.ufn_WeekOfQuarter(@dtmDate) AS 'Week Of The Current Quarter'
        ,dbo.ufn_WeekOfYear(@dtmDate) AS 'Week Of The Current Year'
        ,dbo.ufn_WeekOfDate(@dtmDate) AS 'Week Of The Current Date';
    GO
     
    测试以上函数的效果,如下图:
        旬时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_PeriodOfMonth', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_PeriodOfMonth;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间在当前月的旬索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,1、2、3分别对应上、中、下的旬索引。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intPeriods = dbo.ufn_PeriodOfMonth('2008-01-14')
    --==================================
    CREATE FUNCTION [dbo].[ufn_PeriodOfMonth] 
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    AS
    BEGIN
        --当前月的日索引,从1开始计数,,包括1、2、3、……、28、29、30、31
        DECLARE @tintDayOfMonth AS TINYINT;
        SET @tintDayOfMonth = DAY(@dtmDate);
        -- 旬偏移索引,0:上旬,1:中旬,2:下旬
        DECLARE @tintPeriodOffsetIndexID AS INT;
        SET @tintPeriodOffsetIndexID = DAY(@dtmDate) / 10
     
        IF @tintDayOfMonth IN (10, 20, 30, 31)
        BEGIN
            SET @tintPeriodOffsetIndexID = @tintPeriodOffsetIndexID - 1;
        END
     
        RETURN @tintPeriodOffsetIndexID + 1;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Periods', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Periods;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总旬数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intPeriods = dbo.ufn_Periods('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Periods
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEDIFF(MONTH, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate)) * 3 + (dbo.ufn_PeriodOfMonth(@dtmDate) - 1);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Periods2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Periods2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的旬基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0;
    --       如果指定的整数值大于“9999-12-31”对应的整数值时,则其值默认设置为“9999-12-31”对应的整数值;
    --       结果值为基于默认基准日期开始计数的日期;
    --       旬基准日期是指一个月份中第1天、第11天和第21天对应的日期,比如'2016-02'月份的3个旬基准日期分别为'2016-02-01','2016-02-11','2016-02-21'。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Periods2Date(2705) --'1975-02-21'
    --==================================
    CREATE FUNCTION dbo.ufn_Periods2Date 
    (
        @intPeriods INT        -- 指定的整数值
    ) RETURNS DATETIME
    AS
    BEGIN
        SET @intPeriods = dbo.ufn_GetValidDateNum(@intPeriods);
     
        DECLARE @intMaxPeriods AS INT;
        SET @intMaxPeriods = dbo.ufn_Periods(dbo.ufn_GetMaxDateTime());
     
        IF @intPeriods >= @intMaxPeriods
        BEGIN
            SET @intPeriods = @intMaxPeriods;
        END
     
        RETURN DATEADD(DAY, (@intPeriods - @intPeriods / 3 * 3) * 10, DATEADD(MONTH, @intPeriods / 3, dbo.ufn_GetDefaultBasedate()));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_PeriodOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_PeriodOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前季的旬索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、……、7、8、9。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintPeriodOfQuarter = dbo.ufn_PeriodOfQuarter('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_PeriodOfQuarter
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        RETURN (MONTH(@dtmDate) - dbo.ufn_FirstMonthOfQuarter(@dtmDate)) * 3 + dbo.ufn_PeriodOfMonth(@dtmDate);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_PeriodOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_PeriodOfYear;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前年的旬索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、……、34、35、36。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintPeriodOfYear = dbo.ufn_PeriodOfYear('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_PeriodOfYear
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        RETURN (MONTH(@dtmDate) - 1) * 3 + dbo.ufn_PeriodOfMonth(@dtmDate);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_PeriodOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_PeriodOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前日期的旬索引
    -- 说明: 运行在SQL Server 2008+。
    --       结果值从1开始计数,包括1、2、3.……、359962、359963、359964。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @inntDayOfDate = dbo.ufn_DayOfDate('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_PeriodOfDate
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    BEGIN
        SET @dtmDate = dbo.ufn_GetValidDate(@dtmDate);
     
        RETURN DATEDIFF(MONTH, dbo.ufn_GetMinDateTime(), @dtmDate) * 3 + dbo.ufn_PeriodOfMonth(@dtmDate);
    END
    GO
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-15';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Periods(@dtmDate) AS 'Periods'
        ,dbo.ufn_Periods2Date(dbo.ufn_Periods(@dtmDate)) AS 'Date Mapping Periods'
        ,dbo.ufn_PeriodOfMonth(@dtmDate) AS 'Period Of The Current Month'
        ,dbo.ufn_PeriodOfQuarter(@dtmDate) AS 'Period Of The Current Quarter'
        ,dbo.ufn_PeriodOfYear(@dtmDate) AS 'Period Of The Current Year'
        ,dbo.ufn_PeriodOfDate(@dtmDate) AS 'Period Of The Current Date';
     
    SET @dtmDate = '2016-01-31';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Periods(@dtmDate) AS 'Periods'
        ,dbo.ufn_Periods2Date(dbo.ufn_Periods(@dtmDate)) AS 'Date Mapping Periods'
        ,dbo.ufn_PeriodOfMonth(@dtmDate) AS 'Period Of The Current Month'
        ,dbo.ufn_PeriodOfQuarter(@dtmDate) AS 'Period Of The Current Quarter'
        ,dbo.ufn_PeriodOfYear(@dtmDate) AS 'Period Of The Current Year'
        ,dbo.ufn_PeriodOfDate(@dtmDate) AS 'Period Of The Current Date';
    GO
     
    测试以上函数的效果,如下图:
     
        月时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Months', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Months;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总月数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intMonths = dbo.ufn_Months('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Months 
    (
        @dtmDate DATETIME                -- 指定的日期时间
    ) RETURNS INT
    AS
    BEGIN
        RETURN DATEDIFF(MONTH, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Months2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Months2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的月基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0。
    --       如果指定的整数值大于最大日期时间对应的整数值时,则其值默认设置为最大日期时间对应的整数值。
    --       结果值为基于默认基准日期开始计数的日期。
    --       月基准日期是指一个月份中第1天对应的日期,比如'2016-02'月份的月旬基准日期为'2016-02-01'。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Months2Date(1296) --'2008-01-01'
    --==================================
    CREATE FUNCTION dbo.ufn_Months2Date 
    (
        @intMonths INT                -- 指定的整数值
    ) RETURNS DATETIME
    AS
    BEGIN
        SET @intMonths = dbo.ufn_GetValidDateNum(@intMonths);
     
        DECLARE @intMaxMonths AS INT;
        SET @intMaxMonths = dbo.ufn_Months(dbo.ufn_GetMaxDateTime());
     
        IF @intMonths >= @intMaxMonths
        BEGIN
            SET @intMonths = @intMaxMonths;
        END
     
        RETURN DATEADD(MONTH, @intMonths, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_MonthOfQuarter', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_MonthOfQuarter;
    END
    GO
     
    --==================================
    -- 功能: 获得一个日期时间的月份在当前季度的月索引
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL时,则其值默认设置为默认基准日期。
    --       结果值从1开始计数,包括1、2、3。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_MonthOfQuarter(2008-01-01);
    --==================================
    CREATE FUNCTION dbo.ufn_MonthOfQuarter
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
    AS
    BEGIN
        SET @dtmDate = dbo.ufn_GetValidDate(@dtmDate);
        DECLARE @tintMonthOfQuarter AS TINYINT;
        SET @tintMonthOfQuarter = 1;
     
        SET @tintMonthOfQuarter =  MONTH(@dtmDate) % 3;
     
        IF @tintMonthOfQuarter = 0
        BEGIN
            SET @tintMonthOfQuarter = 3;
        END
     
        RETURN @tintMonthOfQuarter;
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_MonthOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_MonthOfYear;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前年的月索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果值从1开始计数,包括1、2、……、9、10、11、12。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintMonthOfYear = dbo.ufn_MonthOfYear('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_MonthOfYear
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    BEGIN
        RETURN MONTH(@dtmDate);
    END
    GO
     
     
    IF OBJECT_ID(N'dbo.ufn_MonthOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_MonthOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前日期的月索引
    -- 说明: 运行在SQL Server 2008+。
    --       结果值从1开始计数,包括1、2、3.……、119986、119987、119988。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intMonthOfDate = dbo.ufn_MonthOfDate('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_MonthOfDate
    (
        @dtmDate DATETIME
    ) RETURNS INT
        --$Encode$--
    BEGIN
        RETURN DATEDIFF(MONTH, dbo.ufn_GetMinDateTime(), dbo.ufn_GetValidDate(@dtmDate)) + 1;
    END
    GO
     
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-15';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Months(@dtmDate) AS 'Months'
        ,dbo.ufn_Months2Date(dbo.ufn_Months(@dtmDate)) AS 'Date Mapping Months'
        ,dbo.ufn_MonthOfQuarter(@dtmDate) AS 'Month Of The Current Quarter'
        ,dbo.ufn_MonthOfYear(@dtmDate) AS 'Month Of The Current Year'
        ,dbo.ufn_MonthOfDate(@dtmDate) AS 'Month Of The Current Date';
     
    SET @dtmDate = '2016-09-30';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Months(@dtmDate) AS 'Months'
        ,dbo.ufn_Months2Date(dbo.ufn_Months(@dtmDate)) AS 'Date Mapping Months'
        ,dbo.ufn_MonthOfQuarter(@dtmDate) AS 'Month Of The Current Quarter'
        ,dbo.ufn_MonthOfYear(@dtmDate) AS 'Month Of The Current Year'
        ,dbo.ufn_MonthOfDate(@dtmDate) AS 'Month Of The Current Date';
    GO
     
    测试以上函数的效果,如下图:
     
        季时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Quarters', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Quarters;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总季数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期。
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intQuarters = dbo.ufn_Quarters('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Quarters
    (
        @dtmDate DATETIME                    -- 指定的日期时间
    ) RETURNS INT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEDIFF(QUARTER, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Quarters2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Quarters2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的季基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0。
    --       如果指定的整数值大于最大日期时间对应的整数值时,则其值默认设置为最大日期时间对应的整数值。
    --       结果值为基于默认基准日期开始计数的日期。
    --       季基准日期是指所在季度的第一个月份中第1天对应的日期,比如'2016-06-08'月份的姐旬基准日期为'2016-04-01'。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.fn_Quarters2Date(300) --'1975-02-21'
    --==================================
    CREATE FUNCTION dbo.ufn_Quarters2Date 
    (
        @intQuarters INT            -- 指定的整数值
    ) RETURNS DATETIME
        --$Encode$--
    AS
    BEGIN
        SET @intQuarters = dbo.ufn_GetValidDateNum(@intQuarters);
     
        DECLARE @intMaxQuarters AS INT;
        SET @intMaxQuarters = dbo.ufn_Quarters(dbo.ufn_GetMaxDateTime());
     
        IF @intQuarters >= @intMaxQuarters
        BEGIN
            SET @intQuarters = @intMaxQuarters;
        END
     
        RETURN DATEADD(QUARTER, @intQuarters, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_QuarterOfYear', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_QuarterOfYear;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前年内的旬索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果从1开始计数,1、2、3、4分别表示第1季度、第2季度、第3季度、第4季度。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @tintQuarterOfYear = dbo.ufn_QuarterOfYear('2016-01-11');
    --==================================
    CREATE FUNCTION dbo.ufn_QuarterOfYear
    (
        @dtmDate DATETIME                --指定的日期时间
    ) RETURNS TINYINT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEPART(QUARTER, @dtmDate);
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_QuarterOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_QuarterOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在当前日期的季索引
    -- 说明: 运行在SQL Server 2008+。
    --       结果值从1开始计数,包括1、2、3.……、39994、39995、39996。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @intQuarterOfDate = dbo.ufn_QuarterOfDate('2016-01-11')
    --==================================
    CREATE FUNCTION dbo.ufn_QuarterOfDate
    (
        @dtmDate DATETIME                --指定的日期时间
    ) RETURNS INT
        --$Encode$--
    BEGIN
        RETURN DATEDIFF(QUARTER, dbo.ufn_GetMinDateTime(), dbo.ufn_GetValidDate(@dtmDate)) + 1;
    END
    GO
     
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-15';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Quarters(@dtmDate) AS 'Quarters'
        ,dbo.ufn_Quarters2Date(dbo.ufn_Quarters(@dtmDate)) AS 'Date Mapping Quarters'
        ,dbo.ufn_QuarterOfYear(@dtmDate) AS 'Quarter Of The Current Year'
        ,dbo.ufn_QuarterOfDate(@dtmDate) AS 'Quarter Of The Current Date';
     
    SET @dtmDate = '2016-09-30';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Quarters(@dtmDate) AS 'Quarters'
        ,dbo.ufn_Quarters2Date(dbo.ufn_Quarters(@dtmDate)) AS 'Date Mapping Quarters'
        ,dbo.ufn_QuarterOfYear(@dtmDate) AS 'Quarter Of The Current Year'
        ,dbo.ufn_QuarterOfDate(@dtmDate) AS 'Quarter Of The Current Date';
    GO
     
    测试以上函数的效果,如下图:
     
        年时间粒度有关函数,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.ufn_Years', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Years;
    END
    GO
     
    --==================================
    -- 功能: 获得指定日期时间基于默认基准日期的总年数(一个整数值)
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的日期时间为NULL或者小于默认基准日期时,则其值为默认基准日期
    --       结果值为非负整数,从0开始计数。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @sintYears = dbo.ufn_Years('2008-01-14')
    --==================================
    CREATE FUNCTION dbo.ufn_Years 
    (
        @dtmDate DATETIME            -- 指定的日期时间
    ) RETURNS SMALLINT
        --$Encode$--
    AS
    BEGIN
        RETURN DATEDIFF(YEAR, dbo.ufn_GetDefaultBasedate(), dbo.ufn_GetValidDate(@dtmDate));
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_Years2Date', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_Years2Date;
    END
    GO
     
    --==================================
    -- 功能: 获得一个整数值基于默认基准日期对应的年基准日期
    -- 说明: 运行在SQL Server 2005+。
    --       如果指定的整数值为NULL或为负整数时,则其值默认为0;
    --       如果指定的整数值大于最大日期时间对应的整数值时,则其值默认设置为最大日期时间对应的整数值;
    --       结果值为基于默认基准日期开始计数的日期;
    --       年基准日期是指所在年的第一个月份中第1天对应的日期,比如'2016-06-08'月份的姐旬基准日期为'2016-01-01'。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @dtmDate = dbo.ufn_Years2Date(300) --'1975-02-21'
    --==================================
    CREATE FUNCTION dbo.ufn_Years2Date
    (
        @sintYears SMALLINT            -- 指定的整数值
    ) RETURNS DATETIME
        --$Encode$--
    AS
    BEGIN
        SET @sintYears = dbo.ufn_GetValidDateNum(@sintYears);
     
        DECLARE @sintMaxYears AS SMALLINT;
        SET @sintMaxYears = dbo.ufn_Years(dbo.ufn_GetMaxDateTime());
     
        IF @sintYears >= @sintMaxYears
        BEGIN
            SET @sintYears = @sintMaxYears;
        END
     
        RETURN DATEADD(YEAR, @sintYears, dbo.ufn_GetDefaultBasedate());
    END
    GO
     
    IF OBJECT_ID(N'dbo.ufn_YearOfDate', 'FN') IS NOT NULL
    BEGIN
        DROP FUNCTION dbo.ufn_YearOfDate;
    END
    GO
     
    --==================================
    -- 功能: 获取指定的日期时间所在日期内的年索引
    -- 说明: 运行在SQL Server 2005+。
    --       结果从1开始计数,1、2、3、……、9998、9999。
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    -- 调用: SET @sintYearOfDate = dbo.ufn_YearsOfDate('2016-01-11');
    --==================================
    CREATE FUNCTION dbo.ufn_YearOfDate
    (
        @dtmDate DATETIME                --指定的日期时间
    ) RETURNS SMALLINT
        --$Encode$--
    AS
    BEGIN
        RETURN YEAR(@dtmDate);
    END
    GO
     
     
    -- Test Code
    DECLARE @dtmDate AS DATETIME;
    SET @dtmDate = '2016-01-15';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Years(@dtmDate) AS 'Years'
        ,dbo.ufn_Years2Date(dbo.ufn_Years(@dtmDate)) AS 'Date Mapping Years'
        ,dbo.ufn_YearOfDate(@dtmDate) AS 'Year Of The Current Date';
     
    SET @dtmDate = '2016-09-30';
     
    SELECT
        @dtmDate AS 'The Current Date'
        ,dbo.ufn_Years(@dtmDate) AS 'Years'
        ,dbo.ufn_Years2Date(dbo.ufn_Years(@dtmDate)) AS 'Date Mapping Years'
        ,dbo.ufn_YearOfDate(@dtmDate) AS 'Year Of The Current Date';
    GO
     
    测试以上函数的效果,如下图:
     
    日历数据表
     
        
    根据以上各时间粒度有关的函数,汇总为一个日历数据表(Calendar),其表字段列如下表格:
    序号 字段列
    字段列类型
    字段列说明
    1
    CalendarDate
    datetime 日历日期[1900-01-01、1900-01-02、……、999-12-31]
    2
    Days
    int
    日期天数[0、1、2、……、最大值]
    3
    DayOfWeek
    tinyint 周内日索引[1、2、……、7]
    4
    WorkDayFlag bit
    工作日标志,1:工作日,0:非工作日
    5
    DayOfPeriod
    tinyint
    旬内日索引[1、2、……、8、9、10、11]
    6
    DayOfMonth
    tinyint
    月内日索引[1、2、……、28、29、30、31]
    7
    DayOfQuarter
    tinyint
    季内日索引[1、2、……88、89、90、91、92]
    8
    DayOfYear
    smallint
    年内日索引[1、2、……、364、365、366]
    9 DayOfDate
    int
    日期内日索引[1、2、……、3652059]
    10
    Weeks
    int
    日期周数[0、1、2、……、最大值]
    11 WeekOfPeriod
    tinyint
    旬内周索引[1、2、3]
    12
    WeekOfMonth
    tinyint
    月内周索引[1、2、3、4、5]
    13
    WeekOfQuarter
    tinyint
    季内周索引[1、2、……、34、35、36、37]
    14 WeekOfYear
    tinyint
    年内周索引[1、2、……、51、52、53]
    15
    WeekOfDate
    int
    日期内周索引[1、2、……、521723]
    16
    Periods
    int
    日期旬数[0、1、2、……、最大值]
    17 PeriodOfMonth
    tinyint
    月内旬索引[1、2、3]
    18
    PeriodOfQuarter
    tinyint
    季内旬索引[1、2、3、4、5、6、7、8、9]
    19
    PeriodOfYear
    tinyint
    年内旬索引[1、2、……、35、36]
    20
    PeriodOfDate
    int
    日期内旬索引[1、2、……、359964]
    21
    Months
    int
    日期月数[0、1、2、……、最大值]
    22
    MonthOfQuarter
    tinyint
    季内月索引[1、2、3]
    23
    MonthOfYear
    tinyint
    年内月索引[1、2、……、11、12]
    24
    MonthOfDate
    int
    日期内月索引[1、2、……、119988]
    25
    Quarters
    int
    日期季数[0、1、2、……、最大值]
    26
    QuarterOfYear
    tinyint
    年内季索引[1、2、3、4]
    27
    QuarterOfDate
    int
    日期内季索引[1、2、……、39996]
    28
    Years
    smallint
    日期年数[0、1、2、……、最大值]
    29
    YearOfDate smallint 日期内年索引[1、2、……、9999]
    日历数据表创建的T-SQL脚本如下:
    IF OBJECT_ID(N'dbo.Calendar', 'U') IS NOT NULL
    BEGIN    
        DROP TABLE dbo.Calendar;
    END
    GO
     
    CREATE TABLE dbo.Calendar (
        CalendarDate DATETIME NOT NULL,
        [Days] INT NOT NULL,
        [DayOfWeek] TINYINT NOT NULL,
        WorkDayFlag BIT NOT NULL,
        DayOfPeriod TINYINT NOT NULL,
        [DayOfMonth] TINYINT NOT NULL,
        DayOfQuarter TINYINT NOT NULL,
        [DayOfYear] SMALLINT NOT NULL,
        DayOfDate INT NOT NULL,
        Weeks INT NOT NULL,
        WeekOfPeriod TINYINT NOT NULL,
        WeekOfMonth TINYINT NOT NULL,
        WeekOfQuarter TINYINT NOT NULL,
        WeekOfYear TINYINT NOT NULL,
        WeekOfDate INT NOT NULL,
        Periods INT NOT NULL,
        PeriodOfMonth TINYINT NOT NULL,
        PeriodOfQuarter TINYINT NOT NULL,
        PeriodOfYear TINYINT NOT NULL,
        PeriodOfDate INT NOT NULL,
        Months INT NOT NULL,
        MonthOfQuarter TINYINT NOT NULL,
        MonthOfYear TINYINT NOT NULL,
        MonthOfDate INT NOT NULL,
        Quarters INT NOT NULL,
        QuarterOfYear TINYINT NOT NULL,
        QuarterOfDate INT NOT NULL,
        Years SMALLINT NOT NULL,
        YearOfDate SMALLINT NOT NULL,
        TagID INT NOT NULL,
        FlagID INT NOT NULL    
    );
     
    IF OBJECT_ID(N'PK_U_CL_Calendar_Days', N'PK') IS NULL
    BEGIN
        ALTER TABLE [dbo].[Calendar] ADD CONSTRAINT [PK_U_CL_Calendar_Days] PRIMARY KEY CLUSTERED 
        (
            [Days] ASC
        )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) 
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_U_NCL_Calendar_CalendarDate')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_U_NCL_Calendar_CalendarDate] ON [dbo].[Calendar]
        (
            [CalendarDate] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_Weeks')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_Weeks] ON [dbo].[Calendar]
        (
            [Weeks] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_Periods')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_Periods] ON [dbo].[Calendar]
        (
            [Periods] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_Months')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_Months] ON [dbo].[Calendar]
        (
            [Months] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_Quarters')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_Quarters] ON [dbo].[Calendar]
        (
            [Quarters] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_Years')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_Years] ON [dbo].[Calendar]
        (
            [Years] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[Calendar]', N'U') AND name = N'IX_NU_NCL_Calendar_YearOfDate')
    BEGIN
        CREATE NONCLUSTERED INDEX [IX_NU_NCL_Calendar_YearOfDate] ON [dbo].[Calendar]
        (
            [YearOfDate] ASC
        ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
        ON [PRIMARY];
    END
    GO
     
    EXEC sp_addextendedproperty N'MS_Description', N'日历数据表', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', NULL, NULL;
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日历日期', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'CalendarDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期天数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Days';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'周内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfWeek';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'工作日标志(1:工作日,0:非工作日)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WorkDayFlag';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'旬内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfPeriod';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'月内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfMonth';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'季内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfQuarter';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'年内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfYear';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内日索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'DayOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期周数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Weeks';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'旬内周索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WeekOfPeriod';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'月内周索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WeekOfMonth';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'季内周索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WeekOfQuarter';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'年内周索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WeekOfYear';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内周索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'WeekOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期旬数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Periods';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'月内旬索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'PeriodOfMonth';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'季内旬索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'PeriodOfQuarter';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'年内旬索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'PeriodOfYear';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内旬索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'PeriodOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期月数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Months';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'季内月索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'MonthOfQuarter';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'年内月索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'MonthOfYear';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内月索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'MonthOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期季数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Quarters';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'年内季索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'QuarterOfYear';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内季索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'QuarterOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期年数(从0开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'Years';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'日期内年索引(从1开始计数)', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'YearOfDate';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'标记ID,辅助扩展字段列', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'TagID';
    GO
    EXEC sp_addextendedproperty N'MS_Description', N'标志ID,辅助扩展字段列', 'SCHEMA', N'dbo', 'TABLE', N'Calendar', 'COLUMN', N'FlagID';
    GO
     
    日历数据表填充数据
        
    初始化日历表数据的功能封装在一个存储过程中,T-SQL代码如下:
    IF OBJECT_ID(N'dbo.usp_Calendar_Init', 'P') IS NOT NULL
    BEGIN
        DROP PROCEDURE dbo.usp_Calendar_Init;
    END
    GO
     
    --==================================
    -- 功能: 初始化日历表中的数据
    -- 说明: 具体实现阐述
    -- 作者: XXX
    -- 创建: yyyy-MM-dd
    -- 修改: yyyy-MM-dd XXX 修改内容描述
    --==================================
    CREATE PROCEDURE dbo.usp_Calendar_Init
    (
        @dtmEndDate DATETIME,                        -- 日历截止日期时间    
        @chvnErrMsg NVARCHAR(100) OUTPUT            -- 错误消息字符串
    )     --$Encode$--
    AS
    BEGIN
        SET NOCOUNT ON;
     
        SET @chvnErrMsg = N'';
     
        DECLARE @tintReturnValue AS TINYINT;
        SET @tintReturnValue = 1;
     
        IF @dtmEndDate IS NULL
        BEGIN
            SET @chvnErrMsg = N'日历截止日期时间不能为NULL。';
     
            RETURN @tintReturnValue;
        END
     
        DECLARE    @dtmDefaultBasedate AS DATETIME;
        SET @dtmDefaultBasedate = dbo.ufn_GetDefaultBasedate();
     
        IF @dtmDefaultBasedate > @dtmEndDate
        BEGIN
            SET @chvnErrMsg = N'日历截止日期时间不能小于默认基准日期时间【' + CONVERT(VARCHAR(10), @dtmEndDate, 120) + N'】';
     
            RETURN @tintReturnValue;
        END
     
        -- 插入数据
        INSERT INTO dbo.Calendar (
            CalendarDate
            ,Days
            ,DayOfWeek
            ,WorkDayFlag
            ,DayOfPeriod
            ,DayOfMonth
            ,DayOfQuarter
            ,DayOfYear
            ,DayOfDate
            ,Weeks
            ,WeekOfPeriod
            ,WeekOfMonth
            ,WeekOfQuarter
            ,WeekOfYear
            ,WeekOfDate
            ,Periods
            ,PeriodOfMonth
            ,PeriodOfQuarter
            ,PeriodOfYear
            ,PeriodOfDate
            ,Months
            ,MonthOfQuarter
            ,MonthOfYear
            ,MonthOfDate
            ,Quarters
            ,QuarterOfYear
            ,QuarterOfDate
            ,Years
            ,YearOfDate
            ,TagID
            ,FlagID)
        SELECT 
            T.CalendarDate
            ,T.[Days]
            ,T.[DayOfWeek]
            ,CASE WHEN T.[DayOfWeek] >= 6 THEN 0 ELSE 1 END AS WorkDayFlag
            ,T.DayOfPeriod
            ,T.[DayOfMonth]
            ,T.DayOfQuarter
            ,T.[DayOfYear]
            ,T.DayOfDate
            ,T.Weeks
            ,T.WeekOfPeriod
            ,T.WeekOfMonth
            ,T.WeekOfQuarter
            ,T.WeekOfYear
            ,T.WeekOfDate
            ,T.Periods
            ,T.PeriodOfMonth
            ,T.PeriodOfQuarter
            ,T.PeriodOfYear
            ,T.PeriodOfDate
            ,T.Months
            ,T.MonthOfQuarter
            ,T.MonthOfYear
            ,T.MonthOfDate
            ,T.Quarters
            ,T.QuarterOfYear
            ,T.QuarterOfDate
            ,T.Years
            ,T.YearOfDate
            ,0 AS TagID
            ,0 AS FlagID
        FROM (
            SELECT T.CalendarDate
                ,dbo.ufn_Days(T.CalendarDate) AS [Days]
                ,dbo.ufn_DayOfWeek(T.CalendarDate) AS [DayOfWeek]
                ,dbo.ufn_DayOfPeriod(T.CalendarDate) AS DayOfPeriod
                ,dbo.ufn_DayOfMonth(T.CalendarDate) AS [DayOfMonth]
                ,dbo.ufn_DayOfQuarter(T.CalendarDate) AS DayOfQuarter
                ,dbo.ufn_DayOfYear(T.CalendarDate) AS [DayOfYear]
                ,dbo.ufn_DayOfDate(T.CalendarDate) AS DayOfDate
                ,dbo.ufn_Weeks(T.CalendarDate) AS Weeks
                ,dbo.ufn_WeekOfPeriod(T.CalendarDate) AS WeekOfPeriod
                ,dbo.ufn_WeekOfMonth(T.CalendarDate) AS WeekOfMonth
                ,dbo.ufn_WeekOfQuarter(T.CalendarDate) AS WeekOfQuarter
                ,dbo.ufn_WeekOfYear(T.CalendarDate) AS WeekOfYear
                ,dbo.ufn_WeekOfDate(T.CalendarDate) AS WeekOfDate
                ,dbo.ufn_Periods(T.CalendarDate) AS Periods
                ,dbo.ufn_PeriodOfMonth(T.CalendarDate) AS PeriodOfMonth
                ,dbo.ufn_PeriodOfQuarter(T.CalendarDate) AS PeriodOfQuarter
                ,dbo.ufn_PeriodOfYear(T.CalendarDate) AS PeriodOfYear
                ,dbo.ufn_PeriodOfDate(T.CalendarDate) AS PeriodOfDate
                ,dbo.ufn_Months(T.CalendarDate) AS Months
                ,dbo.ufn_MonthOfQuarter(T.CalendarDate) AS MonthOfQuarter
                ,dbo.ufn_MonthOfYear(T.CalendarDate) AS MonthOfYear
                ,dbo.ufn_MonthOfDate(T.CalendarDate) AS MonthOfDate
                ,dbo.ufn_Quarters(T.CalendarDate) AS Quarters
                ,dbo.ufn_QuarterOfYear(T.CalendarDate) AS QuarterOfYear
                ,dbo.ufn_QuarterOfDate(T.CalendarDate) AS QuarterOfDate
                ,dbo.ufn_Years(T.CalendarDate) AS Years
                ,dbo.ufn_YearOfDate(T.CalendarDate) AS YearOfDate
            FROM (
                SELECT DATEADD(DAY, Num, @dtmDefaultBasedate) AS CalendarDate
                FROM dbo.ufn_GetNums(0, DATEDIFF(DAY, @dtmDefaultBasedate, @dtmEndDate))
            ) AS T
        ) AS T
        WHERE NOT EXISTS (SELECT 1 FROM dbo.Calendar WHERE [Days] = T.[Days]);
     
        IF @@ERROR <> 0
        BEGIN
            SET @chvnErrMsg = N'向日历表初始化数据时发生错误。';
     
            RETURN RETURN @tintReturnValue;
        END
     
        SET @tintReturnValue = 0;
     
        RETURN @tintReturnValue;
    END
    GO
     
    -- Test Code
    DECLARE 
        @dtmEndDate AS DATETIME,
        @chvnErrMsg NVARCHAR(100),
        @tintReturnValue AS TINYINT;
    SELECT
        @dtmEndDate = '1899-12-31',
        @chvnErrMsg = N'',
        @tintReturnValue = 0;
     
    EXEC @tintReturnValue = dbo.usp_Calendar_Init
        @dtmEndDate = @dtmEndDate,            -- datetime
        @chvnErrMsg = @chvnErrMsg OUTPUT;    -- nvarchar(100)
     
    SELECT
        @chvnErrMsg AS N'Error Message'
        ,@tintReturnValue AS 'Return Value(1:有错误,0:没有错误)';
     
    SELECT
        @dtmEndDate = '2099-12-31',
        @chvnErrMsg = N'',
        @tintReturnValue = 0;
     
    EXEC @tintReturnValue = dbo.usp_Calendar_Init
        @dtmEndDate = @dtmEndDate,            -- datetime
        @chvnErrMsg = @chvnErrMsg OUTPUT;    -- nvarchar(100)
     
    SELECT
        @chvnErrMsg AS N'Error Message'
        ,@tintReturnValue AS 'Return Value(1:有错误,0:没有错误)';
    GO
     
    以上测试代码的效果,如下图:
     
    查询日历数据表中2016年的数据,T-SQL代码如下:
    SELECT *
    FROM dbo.Calendar
    WHERE DAYS BETWEEN dbo.ufn_Days('2016-01-01') AND dbo.ufn_Days('2016-12-31');
    GO
     
    执行后的查询结果如下图:
     
    注意:usp_Calendar_Init存储使用到了数字辅助数字函数dbo.ufn_GetNums,该函数脚本请参考SQL Server数字辅助表的实现
     
    总结语
        
        本文断断续续写了两天,才将本系列之前涉及到每个时间粒度有关的内容在本文做个总结。每个时间粒度有关的函数,以及将时间粒度有关的封装在了日历数据表中。
    参考清单列表
  • 相关阅读:
    贪心+stack Codeforces Beta Round #5 C. Longest Regular Bracket Sequence
    暴力/DP Codeforces Beta Round #22 (Div. 2 Only) B. Bargaining Table
    DFS Codeforces Round #299 (Div. 2) B. Tavas and SaDDas
    二分搜索 Codeforces Round #299 (Div. 2) C. Tavas and Karafs
    水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas
    数学 2015百度之星初赛2 HDOJ 5255 魔法因子
    贪心/数学 2015百度之星资格赛 1004 放盘子
    模拟 2015百度之星资格赛 1003 IP聚合
    rails安装使用版本控制器的原因。
    ActiveStorage. 英文书Learnrails5.2的案例,看如何放到云上。
  • 原文地址:https://www.cnblogs.com/dzy863/p/5133333.html
Copyright © 2011-2022 走看看