开发者

How to calculate number of leap years between two years in C#

Is there a better way to calculate number of leap years between two years. Assuming I have start date and end date.

I have my code, but I think there should be more elegant way.

calling code:

var numberOfLeapYears = NumberOfLeapYears(startDate.Year + 1, endDate.Year - 1);

function itself:

    private static int NumberOfLeapYears(int startYear, int endYear)
    {
        var counter = 0;

        for (var year = startYear; year <= endYear; year++)
            counter += DateTime.IsLeapYear(year) ? 1 : 0;

        return counter;
    }

So if I have startDate = "10/16/2006" and endDate = "4/18/2004" I should only have 1 leap year (2000) in result. Another words startDate's Year and endDate's year should not be calculated, only years in between.

Thanks in advance for 开发者_如何学运维your help.


You can count it using analytic approach. A year is a leap year if it can be divided by 4, but can't be divided by 100, except of case when it can be divided by 400. Assuming that you can count such number by following code:

static int LeapYearsBetween(int start, int end)
{
    System.Diagnostics.Debug.Assert(start < end);
    return LeapYearsBefore(end) - LeapYearsBefore(start + 1);
}

static int LeapYearsBefore(int year)
{
    System.Diagnostics.Debug.Assert(year > 0);
    year--;
    return (year / 4) - (year / 100) + (year / 400);
}

Some kind of math magic. It is much effective solution than using LINQ.


You can do it with LINQ simply as bellow:

var leepYears = Enumerable.Range(startYear, endYear - startYear + 1)
                              .Count(x => DateTime.IsLeapYear(x));


This should perform much better for large spans of time:

public int LeapYearsBetween(int year1, int year2)
{
    var y1 = new DateTime(year1, 1, 1);
    var y2 = new DateTime(year2, 1, 1);
    var nonLeapDays = 365 * (y2.Year - y1.Year);
    var leapDays = (y2 - y1).Days - nonLeapDays;
    return leapDays;
}

Note that this counts the earlier year if it is a leap year, but not the later year. You'll need to modify the function if you need different behavior.


Another Linq :-)

int start = 1980;
int end = 2000;
var count = Enumerable.Range(start, end - start + 1)
                      .Aggregate(0, (a, b) => DateTime.IsLeapYear(b) ? a + 1 : a);


Just another code with primitives types

    public static int CountLeapYears(int startYear, int endYear) 
    {
        int acc = 0;

        while (true)
        {
            if ((startYear % 4 == 0 && startYear % 100 != 0) || startYear % 400 == 0)
                acc++;
            if (startYear + 1 == endYear) break;
            startYear++;
        }

        return acc;
    }


On your maths (divisible by 100 are not leap years unless they are also evenly divisible by 400) this would mean 1900 was not a leap year? wrong

This means the following is correct: Couldn't you just test the first 4 years and find the first leap year and subtract that from the total years and mod 4? basically: end_year - first_leap_year_found mod 4 = 0 is a leap year


Couldn't you just test the first 4 years and find the first leap year and subtract that from the total years and mod 4?

basically:

end_year - first_leap_year_found mod 4.

I wouldn't be surprised if there are a few tweaks in there to account for the fact that the entire date is specified, not just the year, but those alterations should be simple as well.

You end up only having to use the DateTime.IsLeapYear(year) statement at most 4 times, and then it's simple math after that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜