检查“循环日期”是否为“;位于两个DateTime实例之间

本文关键字:于两个 DateTime 实例 之间 是否 日期 循环 循环日期 检查 | 更新日期: 2023-09-27 17:49:38

我们有一个叫做ABDate的类,其中包含Month, nullable YearDay。在创建ABDate实例时,如果年份为null,则认为该日期是循环的。还有一个IsRecurring属性

现在我们有一个IList<ABDate>,我们有一个开始和结束的DateTime。我们如何检查列表中是否有ABDate位于开始和结束间隔

检查“循环日期”是否为“;位于两个DateTime实例之间

对于非重复出现的情况,解决方案是显而易见的。给定一个集合abDatesstartend实例:

var anyInBetween = abDates
    .Select(ab => new DateTime(ab.Year.Value, ab.Month, ab.Day))
    .Any(d => d >= start && d <= end);

对于重复出现的情况,我们可以观察到,由于没有一个月有超过31天,像f(month, day) = month * 100 + day这样的函数将把每个不同的(月、日)元组投影成一个唯一的整数。比较两个这样的整数可以让我们确定哪个源元组代表一年中的早一天:

// Note: m * 100 is "random". Multiplying by any factor > 31 will work as well.
Func<int, int, int> customTotalOrder = (m, d) => m * 100 + d;
var startIndex = customTotalOrder(start.Month, start.Day);
var endIndex = customTotalOrder(end.Month, end.Day);
var spanningYears = end.Year - start.Year;
var anyInBetween = false;
switch (spanningYears)
{
    default:
    case 2:
        // start => end contains at least one whole year, so obviously...
        anyInBetween = abDates.Any();
    case 1:
        var projection = abDates.Select(ab => customTotalOrder(ab.Month, ab.Day));
        anyInBetween = startIndex < endIndex
            ? projection.Any(i => i >= startIndex && i <= endIndex)
            : projection.Any(i => i >= startIndex || i <= endIndex);
    case 0:
        anyInBetween = abDates
            .Select(ab => customTotalOrder(ab.Month, ab.Day))
            .Any(i => i >= startIndex && i <= endIndex);
}
 foreach (ABDate a in AbDateList)
  {
    for ( in checkYear = startDate.Year ;checkYear <= EndDate.Year; checkYear ++)
    {
         if ((new DateTime(checkYear ,a.Month,a.Day) >= startDate) && (new DateTime(checkYear ,a.Month,a.Day) <= endDate))
           {
              // I AM IN BETWEEN
           }
        }
    }
}