Подтвердить что ты не робот

Как рассчитать число високосных лет между двумя годами в С#

Есть ли лучший способ рассчитать число високосных лет между двумя годами. Предполагая, что у меня есть дата начала и дата окончания.

У меня есть код, но я думаю, что должен быть более элегантный способ.

код вызова:

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

:

    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;
    }

Итак, если у меня есть startDate = "10/16/2006" и endDate = "4/18/2004", я должен получить только 1 високосный год (2000). Другие слова startDate Year и endDate year не должны вычисляться, только между годами.

Заранее благодарим за помощь.

4b9b3361

Ответ 1

Вы можете считать это с помощью аналитического подхода. Год - это високосный год, если его можно разделить на 4, но его нельзя разделить на 100, за исключением случая, когда его можно разделить на 400. Предполагая, что вы можете считать такое число следующим кодом:

        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);
        }

Какая-то математическая магия. Это эффективное решение, чем использование LINQ.

Ответ 2

Вы можете сделать это с помощью LINQ просто как ниже:

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

Ответ 3

Это должно быть намного лучше для больших промежутков времени:

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;
}

Обратите внимание, что это считается годом ранее, если это високосный год, но не более поздний год. Вам нужно будет изменить функцию, если вам нужно другое поведение.

Ответ 4

Другой 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);

Ответ 5

Еще один код с типами примитивов

    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;
    }

Ответ 6

Не могли бы вы просто проверить первые 4 года и найти первый високосный год и вычесть это из общих лет и мод 4?

в основном

end_year - first_leap_year_found mod 4.

Я бы не удивился, если бы там было несколько настроек, чтобы учесть тот факт, что вся дата указана не только на год, но эти изменения также должны быть простыми.

В конечном итоге вам нужно использовать инструкцию DateTime.IsLeapYear(год) не более 4 раз, а затем после этого простую математику.

Ответ 7

В вашей математике (делится на 100 не високосные годы, если они также равномерно не делятся на 400), это означает, что 1900 год не был високосным годом? неправильно

Это означает следующее: Не могли бы вы просто проверить первые 4 года и найти первый високосный год и вычесть это из общего числа лет и мод 4? в основном: end_year - first_leap_year_found mod 4 = 0 - високосный год