user1784973
user1784973

Reputation: 95

Date range Split in C#

I need to split the date in month wise for the given start date and end date in C#

Example User Input:

Start date : 5/20/2013
End date : 11/11/2013

I want to split the give date difference in month

Output:

StartDate    EndDate     NumberOfMonth
 5/20/2013   5/31/2013     .5
 6/1/2013    6/30/2013      1
 7/1/2013    7/31/2013      1
 8/1/2013    8/31/2013      1
 9/1/2013    9/30/2013      1
 10/1/2013   10/31/2013     1
 11/1/2013   11/11/2013    .5

Upvotes: 0

Views: 1260

Answers (1)

p.s.w.g
p.s.w.g

Reputation: 149020

I'll take a stab at this... You can use Linq to generate all the date ranges at once. It's not exactly the prettiest query, but it works.

DateTime start = ...
DateTime end = ...
var cal = System.Globalization.CultureInfo.CurrentCulture.Calendar;

var range =
    from y in Enumerable.Range(start.Year, end.Year - start.Year + 1)
    let maxMonth = y < end.Year ? cal.GetMonthsInYear(y) : end.Month
    let minMonth = y > start.Year ? 1 : start.Month
    from m in Enumerable.Range(minMonth, maxMonth - minMonth + 1)
    let isStart = (y == start.Year && m == start.Month) 
    let isEnd = (y == end.Year && m == end.Month) 
    select new
    {
        StartDate = isStart ? start : new DateTime(y, m, 1),
        EndDate = isEnd ? end : new DateTime(y, m, cal.GetDaysInMonth(y, m)),
        NumberOfMonths = isStart || isEnd ? .5 : 1
    };

It iterates over the years from start to end, then iterates over the months in each year, with special handling on the edge cases (isStart and isEnd). This basic algorithm can be encapsulated in a function like this:

public class DateTimeRange
{
    Date StartDate { get; set; }
    Date EndDate { get; set; }
    float NumberOfMonths { get; set; }
}

public static IEnumerable<DateTimeRange> SplitByMonths(DateTime start, 
                                                       DateTime end, 
                                                       Calendar cal)
{
    return (
        from y in Enumerable.Range(start.Year, end.Year - start.Year + 1)
        let maxMonth = y < end.Year ? cal.GetMonthsInYear(y) : end.Month
        let minMonth = y > start.Year ? 1 : start.Month
        from m in Enumerable.Range(minMonth, maxMonth - minMonth + 1)
        let isStart = (y == start.Year && m == start.Month) 
        let isEnd = (y == end.Year && m == end.Month) 
        select new DateTimeRange
        {
            StartDate = isStart ? start : new DateTime(y, m, 1),
            EndDate = isEnd ? end : new DateTime(y, m, cal.GetDaysInMonth(y, m)),
            NumberOfMonths = isStart || isEnd ? .5 : 1
        });
}

Upvotes: 2

Related Questions