#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:
Это, вероятно, самый сложный способ сделать это, но он выдержал мои тестовые примеры и, похоже, справился с задачей.
- Вычислите разницу в общем количестве лет
Years
. - Вычислите
Days
оставшийся интервал. - Проверьте его на високосный день. Если он есть, вычислите
--Days
. - Возврат
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;
}