How to calculate number of leap years between two

2020-03-01 08:28发布

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.

7条回答
The star\"
2楼-- · 2020-03-01 08:42

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);
查看更多
家丑人穷心不美
3楼-- · 2020-03-01 08:44

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

查看更多
▲ chillily
4楼-- · 2020-03-01 08:48

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.

查看更多
Anthone
5楼-- · 2020-03-01 08:49

You can do it with LINQ simply as bellow:

var leepYears = Enumerable.Range(startYear, endYear - startYear + 1)
                              .Count(x => DateTime.IsLeapYear(x));
查看更多
forever°为你锁心
6楼-- · 2020-03-01 08:52

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.

查看更多
叼着烟拽天下
7楼-- · 2020-03-01 08:53

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.

查看更多
登录 后发表回答