2013-05-07 117 views
0

我需要拆分在一个月的日期明智的给定的起始日期和结束日期在C#日期范围拆分

实例用户输入:

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

我要分割给定的时间差在一个月

输出:

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 
+2

你能用一些代码和细节来说明你的问题吗? – 2013-05-07 23:08:47

+2

为什么5-20-2013 - 5-31-2013定义为.5个月,而不是更精确? – 2013-05-07 23:14:01

+2

您是否已经尝试自行解决问题?如果是,发布一些代码。如果没有,在你问之前就这么做。 – filipko 2013-05-07 23:20:27

回答

2

我会在这坐刺...你可以使用LINQ生成所有日期范围一次。这不是最漂亮的查询,但它的工作原理。

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

它重复多年来从startend,然后在几个月迭代每年,与边缘的情况下(isStartisEnd)特殊处理。这个基本的算法可以被封装在这样一个函数中:

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