Home > Enterprise >  Check number of Dates in Date Range that are sequential in c#?
Check number of Dates in Date Range that are sequential in c#?

Time:10-03

I'm trying to create a function that returns the number of Dates in a Date Range that are sequential, starting on a specific date.

Example:

StartDate: 9/1/2022

Date Range: 9/1/2022, 9/2/2022, 9/3/2022, 9/4/2022, 9/7/2022

In this scenario the function I'm looking for would return 4.

Assume dates could be unordered and they can roll over into the next month, so with StartDate 9/29/2022:

9/29/2022, 9/30/2022, 10/1/2022, 10/4/2022 would return 3.

I know I can loop through the dates starting at the specific date and check the number of consecutive days, but I'm wondering if there's a clean way to do it with Linq.

CodePudding user response:

Here's a LINQ solution that will do that job:

var sortedDates = originalDates.OrderBy(dt => dt).ToArray();
var firstDate = sortedDates.First();
var sequentialDateCount = Enumerable.Range(0, sortedDates.Length)
                                    .Max(i => sortedDates[i] == firstDate.AddDays(i))   1;

It sorts the dates into an array, then finds the maximum index where the value is equal to the first value plus the index as a number of days. As soon as there's a gap, those values will not be equal. Adding 1 to that index gives the length of that initial series of sequential dates.

Without using LINQ:

var sortedDates = originalDates.OrderBy(dt => dt).ToArray();
var firstDate = sortedDates[0];
var sequentialDateCount = 0;

for (var i = 0; i < sortedDates.Length; i  )
{
    if (sortedDates[i] == firstDate.AddDays(i))
    {
        sequentialDateCount  ;
    }
    else
    {
        break;
    }
}

CodePudding user response:

To count the number of consecutive dates in a date range:

class Program
{
    private static void Main(string[] args)
    {
        string dateRange = "10/4/2022, 9/29/2022, 10/1/2022, 9/30/2022";
        List<DateTime> dates = new List<DateTime>();

        foreach (var dateStr in dateRange.Split(", "))
        {
            // split date string to individual parts
            var dateData = dateStr.Split("/");
            
            // parse to DateTime
            int month = int.Parse(dateData[0]);
            int day = int.Parse(dateData[1]);
            int year = int.Parse(dateData[2]);
            var date = new DateTime(year, month, day);
            
            // add date to list
            dates.Add(date);
        }
        
        // order the dates
        dates = dates.OrderBy(x => x).ToList();
        
        // count for consecutive days in the date range
        var consecutiveDatesCounter = 1; // 1 to count for start date
        dates.Aggregate((last, next) =>
        {
            if (last.AddDays(1) == next)
                consecutiveDatesCounter  ;
            else
                return last; // to prevent counting later consecutive dates
            return next;
        });
        
        // Display result
        Console.WriteLine(consecutiveDatesCounter);
    }
}

Output:

3

CodePudding user response:

Using a loop would probably be the cleanest way to go. I would use something like the following:

List<DateTime> GetConsecutiveDates(IEnumerable<DateTime> range, DateTime startDate)
{
    var orderedRange = range.OrderBy(d => d).ToList();
    int startDateIndex = orderedRange.IndexOf(startDate);
    if (startDateIndex == -1) return null;

    var consecutiveDates = new List<DateTime> { orderedRange[startDateIndex] };
    for (int i = startDateIndex   1; i < orderedRange.Count; i  )
    {
        if (orderedRange[i] != orderedRange[i - 1].AddDays(1)) break;

        consecutiveDates.Add(orderedRange[i]);
    }
    return consecutiveDates;
}

CodePudding user response:

This is the cleanest solution I can come up with...

var startDate = new DateTime(2022, 9, 1);

var days = new List<DateTime>()
{
    new(2022, 8, 28),
    new(2022, 9, 1),
    new(2022, 9, 2),
    new(2022, 9, 3),
    new(2022, 9, 4),
    new(2022, 9, 7)
};

var consecutiveDays = GetConsecutiveDays(startDate, days);

foreach (var day in consecutiveDays)
{
    Console.WriteLine(day);
}

Console.ReadKey();

static IEnumerable<DateTime> GetConsecutiveDays(DateTime startDate, IEnumerable<DateTime> days)
{
    var wantedDate = startDate;
    foreach (var day in days.Where(d => d >= startDate).OrderBy(d => d))
    {
        if (day == wantedDate)
        {
            yield return day;
            wantedDate = wantedDate.AddDays(1);
        }
        else
        {
            yield break;
        }
    }
}

Output is: 01.09.2022 0:00:00 02.09.2022 0:00:00 03.09.2022 0:00:00 04.09.2022 0:00:00

If you wanted the count, you can call .Count() on the result or just modify the method... Should be easy.

CodePudding user response:

Case: start; { 9/1/2022 }

Case: finish; { 9/7/2022 }

  • Related