Check whether a "Recurring Date" lies between two DateTime instances

We have a class called ABDate which contains among other things a Month, a nullable Year and a Day. When creating an instance of ABDate if the year is given as null, the date is considered recurring. There is an IsRecurring property as well.

Now we have a IList<ABDate>, and we are given a start and an end DateTime. How do we check to see whether any ABDate in the list lies in the start and end interval.

Upvotes: 1

Views: 221

Answers (2)

Jon
Jon

Reputation: 437336

For the non-recurring case the solution is obvious. Given a collection abDates and start and end instances:

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

For the recurring case, we can observe that since no month has more than 31 days, a function such as f(month, day) = month * 100 + day will project each distinct (month, day) tuple into a unique integer. Comparing two such integers allows us to determine which of the source tuples represents a day earlier in the year:

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

Upvotes: 2

Traci
Traci

Reputation: 908

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

Upvotes: 1

Related Questions