Разница в дате, игнорируя високосные дни

#c# #logic

#c# #Логические

Вопрос:

Пожалуйста, поделитесь некоторой логикой, чтобы найти разницу в дате между двумя датами, которые игнорировали бы високосные дни, метод вычитания c # включает високосные дни. Например. для startDat = 26-02-2016 и EndDate = 03-03-2016 Я хочу, чтобы ответ был 5, а не 6. Аналогично для любых других лет.

Спасибо!

Комментарии:

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

2. Вероятно, вы можете добавить некоторую условную логику, чтобы проверить, является ли это високосным годом, а затем перейти оттуда. Для начала попробуйте сделать что-то вроде startDat . isLeapYear()

3. Как я уже упоминал в своем квесте, я попробовал EndDate.Subtract(StartDate) . Всего дней 🙂

4. Если вы используете DateTime его, будут учитываться високосные дни, почему бы вам не захотеть, чтобы он это делал?

5. Я знаю, что с помощью длинных алгоритмов принудительной обработки я могу добиться этого. Но я хочу, чтобы это было сделано элегантно. например, в одном месте используется совпадающий трюк типа «int days = (end.year-start.year)* 365 end.DayOfYear — start.DayOfYear;» но это решение расходится с примером, приведенным в моем вопросе.

Ответ №1:

Один из способов сделать это заключается в следующем:

 public static int DayDiff(DateTime d1, DateTime d2)
{
    DateTime min, max;
    if(d1 < d2)
    {
        min = d1; max = d2;
    }
    else
    {
        min = d2; max = d1;
    }

    int nbOfDays = 0;
    while(max.Date != min.Date)
    {
        min = min.AddDays(1);
        if (min.Month != 2 || min.Day != 29) // Skip leap day
            nbOfDays  ;
    }
    return nbOfDays;
}
  

Комментарии:

1. Эта логика не выполняется для следующих значений var d1 = новое время даты (2016, 06, 30); var d2 = новое время даты (2021, 06, 30);

Ответ №2:

Это, вероятно, самый сложный способ сделать это, но он выдержал мои тестовые примеры и, похоже, справился с задачей.

  1. Вычислите разницу в общем количестве лет Years .
  2. Вычислите Days оставшийся интервал.
  3. Проверьте его на високосный день. Если он есть, вычислите --Days .
  4. Возврат Days Years * 365 .
 /// <summary>
/// Determines the ABSOLUTE difference of FULL years between two dates.
/// Leap days are ignored; the 29th of February is treated as if it was the 28th
/// (conforming with Aventurian calendars).
/// </summary>
/// <param name="Early">The earlier date</param>
/// <param name="Late">The later date</param>
/// <returns>Difference in full years (absolute value >= 0)</returns>
public static int AbsDeltaInYears(DateTime Early, DateTime Late)
{
    if (Early > Late) throw new ArgumentException("'Late' must be greater or equal to 'Early'");

    // Aventurian calendars do not have leap years: check for Feb, 29th
    const int Feb = 2;
    const int LeapDay = 29;
    if (Early.Day == LeapDay amp;amp; Early.Month == Feb) Early = Early.AddDays(-1);
    if (Late.Day == LeapDay amp;amp; Late.Month == Feb) Late = Late.AddDays(-1);

    int Delta = Late.Year - Early.Year;

    // correction if the one year is not a full year
    if (Late.Month < Early.Month || (Late.Month == Early.Month amp;amp; Late.Day < Early.Day))
        Delta--;

    return Delta;
}


/// <summary>
/// Calculate the difference in days (ignoring leap days which the Aventurian calendar does not have).
/// </summary>
/// <param name="time"></param>
/// <param name="reference"></param>
/// <returns></returns>
public static int DeltaInDays(DateTime time, DateTime reference)
{
    // Needed to determine leap years
    GregorianCalendar EarthCalendar = new();

    DateTime Early = time <= reference ? time : reference;
    DateTime Late = time > reference ? time : reference;
    int Years = AbsDeltaInYears(Early, Late);

    // skip leap days by using whole years
    int Days = Years * DaysInYear;
    // add remaining interval
    DateTime EarlyPlusYears = Early.AddYears(Years);
    Days  = (Late - EarlyPlusYears).Days;
    // One leap day may be left, remove if necessary
    if (EarthCalendar.IsLeapYear(EarlyPlusYears.Year) amp;amp; EarlyPlusYears.DayOfYear < 31   29)
        Days--;
    else
    {
        if (EarthCalendar.IsLeapYear(Late.Year) amp;amp; Late.DayOfYear > 31   28)
            Days--;
    }
    return Days;
}