简体   繁体   中英

how to calculate number of leap years between two dates in t-sql?

I am doing report in SSRS, I need dataset column for calculating the number of leap years between two dates in t-SQL. I found the function for single input parameter whether it is the leap year or not but for my requirement two parameters in function or any t-SQL statement.

Thanks..waiting for anybody reply

DECLARE @year int
SET @year = 2008
if (((@year % 4 = 0) AND (@year % 100 != 0)) OR (@year % 400 = 0))
print 'Leap year'
ELSE
print 'No'

It's not clear what you want to do with the first and last year depend on your date parameters. Here is an example how to do it with the recursive query:

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

Hope this too works.

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

Result

在此处输入图片说明

I thought, will add as another answer.

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

As I dont have an instance of sql server available now,I did not test the code..But you will get the an idea about what I was trying to achieve. I declared @BM, in case you want to do the checking with the end month too..

Here's a sql function based on some of the answers above that should do this -

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

An improvement on the original answer

This has 2 improvements

  • Fixed a bug relating to subtracting -1 when a start date is after feb EVEN when the start year is not a leap year
  • Also the -1 function at the bottom should check the original start month NOT the changing 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 

Number of leap days between two dates.

DECLARE
    @StartDate DATETIME = '2000-02-28',
    @EndDate DATETIME = '2017-02-28'

SELECT ((CONVERT(INT,@EndDate-58)) / 1461 - (CONVERT(INT,@StartDate-58)) / 1461)

-58 to start counting from 1st March 1900 and / 1461 being the number of days between 29th Februaries. NOTE: in Excel, the -58 would be -60 as 1st Jan 1900 in Excel is day 1 but in SQL is day zero and SQL doesn't recognise 29th Feb 1900 whereas Excel does. ALSO NOTE: This formula will go wrong every 400 years as every 400 years we skip a leap year. Hope this helps someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM