【问题标题】:how to calculate number of leap years between two dates in t-sql?如何计算t-sql中两个日期之间的闰年数?
【发布时间】:2014-05-23 08:15:36
【问题描述】:

我在 SSRS 中做报告,我需要数据集列来计算 t-SQL 中两个日期之间的闰年数。我找到了单个输入参数的函数,无论它是否是闰年,但对于我的要求,函数或任何 t-SQL 语句中的两个参数。

谢谢..等待任何人回复

【问题讨论】:

  • 这些日期的性质是什么?他们会一直在一年中的某个固定日子出现吗?如果不是,您想如何处理闰年 3 月或更晚的开始日期?那一年应该算吗?对于闰年 2 月 29 日之前的结束日期,反之亦然?
  • Damien_The_Unbeliever,感谢您的回复。实际上,我的表中有 2 个不同的日期时间列。我要数没有。这两个输入列日期之间的闰年。这是从年明智意味着一月到十二月..thanks
  • Damien_The_Unbeliever,我错了,闰年从三月开始......任何建议

标签: sql sql-server tsql reporting-services


【解决方案1】:

我想,将添加作为另一个答案。

DECLARE @A DATE = '2008-03-23',
    @B DATE = '2012-04-20'

DECLARE @AM INT,@AY INT,@BM INT,@BY INT
SET @AM = DATEPART(MONTH,@A),   --3
    @AY = DATEPART(YEAR,@A),    --2008
    @BM = DATEPART(MONTH,@B),   --4
    @BY = DATEPART(YEAR,@B)     --2012

DECLARE @COUNT INT = 0

WHILE (@AY <= @BY)
BEGIN
    SET @COUNT = @COUNT + 
                (CASE   WHEN (@AY%4 = 0 AND @AY%100 !=0) OR @AY%400 = 0 
                        THEN 1 
                        ELSE 0 END)
    SET @AY = @AY + 1
END

SET @COUNT = @COUNT + CASE WHEN @AM >= 3 THEN -1 ELSE 0 END

SELECT @A BEGIN_DATE,@Y END_DATE,@COUNT NO_OF_LEAP_YEARS

由于我现在没有可用的 sql server 实例,因此我没有测试代码..但是您会了解我想要实现的目标。 我声明了@BM,以防您也想在月底进行检查..

【讨论】:

  • Jithin,这段代码还有一个问题。当它是闰年和三月或一个月以上时,它工作正常。但它也需要非闰年月。例如:开始日期:2007-05-15,结束日期:2007-10-06 计数显示 -1。你能帮我解决一下吗..谢谢
  • 用上面的代码声明日期为开始日期:2007-05-15,结束日期:2007-10-06,你会得到-1。请检查一次。谢谢
  • @user3583912 我知道这已经晚了 5 年,但看到改进的答案。
【解决方案2】:
DECLARE @year int
SET @year = 2008
if (((@year % 4 = 0) AND (@year % 100 != 0)) OR (@year % 400 = 0))
print 'Leap year'
ELSE
print 'No'

【讨论】:

  • mohan111,感谢您的回复,但我想计算两个日期之间的闰年数。我认为在您的代码中我们只能输入一年,但我想输入两个日期和这些日期之间的闰年计数..谢谢
【解决方案3】:

不清楚您想对第一年和最后一年做什么取决于您的日期参数。 这是一个如何使用递归查询的示例:

with cte as
(
     select YEAR('1900-01-01') as [year]
     union all
     select [year] + 1
     from    cte   
     where   [year] + 1 <= YEAR('2100-01-01')
 )
 SELECT COUNT(*)
 FROM cte WHERE
           ([YEAR]%4=0) AND (([YEAR]%100<>0) OR ([YEAR]%400=0))
 OPTION(MAXRECURSION 1000)

SQLFiddle demo

【讨论】:

    【解决方案4】:

    希望这也有效。

    DECLARE @X INT = 1590
    DECLARE @Y INT = 1603
    
    DECLARE @COUNT INT = 0,@Z INT = @X
    
    WHILE (@X <= @Y)
    BEGIN
        SET @COUNT = @COUNT + 
                    (CASE   WHEN (@X%4 = 0 AND @X%100 !=0) OR @X%400 = 0 
                            THEN 1 
                            ELSE 0 END)
        SET @X = @X + 1
    END
    
    SELECT @Z BEGIN_YEAR,@Y END_YEAR,@COUNT NO_OF_LEAP_YEARS
    

    结果

    【讨论】:

    • Jithin,上面的代码工作正常,但我想在这里再补充一点,如果我的开始日期是在 2012 年 3 月或更晚的那个闰年开始的,它不应该被视为闰年。例如:2008-03-01 到 214-05-01,计数应该是 1。但根据上面的代码,它的到来是 2。它正在考虑 2008 年,2012 年作为闰年。但我的开始日期是 2008 年 3 月。希望你能理解
    【解决方案5】:

    这是一个基于上面一些答案的 sql 函数,应该这样做 -

    CREATE FUNCTION [dbo].[LeapDayCount]
    (
        @StartDate as datetime,
        @EndDate as datetime
    )
    RETURNS int as
    BEGIN
    
        DECLARE @StartYear int
        DECLARE @EndYear int
        DECLARE @Year int
    
        SELECT @StartYear = YEAR(@StartDate)
        SELECT @EndYear = YEAR(@EndDate)
    
        DECLARE @Count int
    
        SET @Count = 0
    
        SET @Year = @StartYear
    
        WHILE (@Year <= @EndYear)
        BEGIN
            SET @Count = @Count + 
                        (CASE WHEN (@Year%4 = 0 AND @Year%100 !=0) OR @Year%400 = 0 
                                THEN 1 ELSE 0 END)
    
            SET @Year = @Year + 1
        END
    
        --remove one leap day if start date is a leap year but after february
        IF ((@StartYear%4 = 0 AND @StartYear%100 !=0) OR @StartYear%400 = 0) AND MONTH(@StartDate) > 2 SET @Count = @Count -1
    
            --remove one leap day if end date is a leap year but less than 29th Feb
        IF ((@EndYear%4 = 0 AND @EndYear%100 !=0) OR @EndYear%400 = 0) AND (MONTH(@EndDate) = 1 OR (MONTH(@EndDate) = 2 AND DAY(@EndDate) < 29)) SET @Count = @Count -1
    
    RETURN @Count
    END
    

    【讨论】:

      【解决方案6】:

      两个日期之间的闰日数。

      DECLARE
          @StartDate DATETIME = '2000-02-28',
          @EndDate DATETIME = '2017-02-28'
      
      SELECT ((CONVERT(INT,@EndDate-58)) / 1461 - (CONVERT(INT,@StartDate-58)) / 1461)
      

      -58 从 1900 年 3 月 1 日开始计数,/1461 是 2 月 29 日之间的天数。 注意:在 Excel 中,-58 将是 -60,因为 Excel 中的 1900 年 1 月 1 日是第 1 天,但在 SQL 中是第 0 天,SQL 不能识别 1900 年 2 月 29 日,而 Excel 可以。 另请注意:这个公式每 400 年就会出错一次,因为每 400 年我们跳过一个闰年。 希望这对某人有所帮助。

      【讨论】:

        【解决方案7】:

        对原始答案的改进

        这有 2 个改进

        • 修复了一个与开始日期在 2 月之后甚至开始年份不是闰年时减去 -1 相关的错误
        • 底部的 -1 函数也应该检查原始开始月份而不是变化的 1。
        CREATE FUNCTION riskstore.GetLeapYearCount (@Start Date, @End Date)
        RETURNS INT
        AS
        BEGIN
            DECLARE @StartMonth INT = DATEPART(MONTH,@Start)
            DECLARE @StartYear INT = DATEPART(YEAR,@Start)
            DECLARE @OriginalStartYear INT = DATEPART(YEAR,@Start)
            DECLARE @EndMonth INT = DATEPART(MONTH,@End)
            DECLARE @EndYear INT = DATEPART(YEAR,@End)
            DECLARE @COUNT INT = 0
            WHILE (@StartYear <= @EndYear)
            BEGIN
                SET @COUNT = @COUNT + 
                        (CASE   WHEN (@StartYear%4 = 0 AND @StartYear%100 !=0) OR @StartYear%400 = 0 
                                THEN 1 
                                ELSE 0 END)
                SET @StartYear = @StartYear + 1
            END
            SET @COUNT = @COUNT + CASE WHEN @StartMonth >= 3 AND ((@OriginalStartYear%4 = 0 AND @OriginalStartYear%100 !=0) OR @OriginalStartYear%400 = 0) THEN -1 ELSE 0 END
            RETURN (@COUNT)
        END
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-18
          • 2017-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-04
          • 2012-01-06
          相关资源
          最近更新 更多