我借鉴了 PiJei 的建议。然后使用方法扩展它以获取起始范围内的天数,并使用一种方法来构建日期的最终范围。
首先,让我们构建示例数据:
var month = EachDay(start, end);
var start1 = new DateTime(2018, 06, 04);
var end1 = new DateTime(2018, 06, 06);
var sub1 = EachDay(start1, end1);
var start2 = new DateTime(2018, 06, 11);
var end2 = new DateTime(2018, 06, 14);
var sub2 = EachDay(start2, end2);
var start3 = new DateTime(2018, 06, 17);
var end3 = new DateTime(2018, 06, 20);
var sub3 = EachDay(start3, end3);
为此,我使用了从 this answer 借来的 EachDay 方法。
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
要获得我称之为withoutExcluded 的最终列表,我只需运行以下命令:
var withoutExcluded = month.Except(sub1).Except(sub2).Except(sub3);
最后,我采用此列表并构建结果范围。
var ranges = GetRanges(withoutExcluded);
为此,我创建了一个简单的帮助器 Range 类和 GetRanges 方法来分析日期,如果它们是连续的日期,则构建一个范围。
助手Range类:
public class Range
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
助手GetRanges方法:
public static IEnumerable<Range> GetRanges(IEnumerable<DateTime> dates)
{
var start = dates.First();
var end = dates.First();
var prev = dates.First();
var next = DateTime.Now;
foreach(var d in dates.Skip(1))
{
next = d;
var diff = next - prev;
if (diff.TotalDays > 1)
{
yield return new Range { Start = start, End = end };
start = d;
}
prev = d;
end = d;
}
yield return new Range { Start = start, End = end };
}
最终的结果是这样的:
range: 01/06/2018 00:00:00 03/06/2018 00:00:00
range: 07/06/2018 00:00:00 10/06/2018 00:00:00
range: 15/06/2018 00:00:00 16/06/2018 00:00:00
range: 21/06/2018 00:00:00 30/06/2018 00:00:00
我会将结果的适当格式留给您。但逻辑是正确的。
如果您忘记了在下面粘贴整个解决方案时会发生什么:
class Program
{
static void Main(string[] args)
{
var start = new DateTime(2018, 06, 01);
var end = new DateTime(2018, 06, 30);
var month = EachDay(start, end);
var start1 = new DateTime(2018, 06, 04);
var end1 = new DateTime(2018, 06, 06);
var sub1 = EachDay(start1, end1);
var start2 = new DateTime(2018, 06, 11);
var end2 = new DateTime(2018, 06, 14);
var sub2 = EachDay(start2, end2);
var start3 = new DateTime(2018, 06, 17);
var end3 = new DateTime(2018, 06, 20);
var sub3 = EachDay(start3, end3);
var withoutExcluded = month.Except(sub1).Except(sub2).Except(sub3);
var ranges = GetRanges(withoutExcluded);
foreach (var r in ranges)
{
Console.WriteLine($"range: {r.Start} {r.End}");
}
}
//https://stackoverflow.com/a/1847601/3330348
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
public static IEnumerable<Range> GetRanges(IEnumerable<DateTime> dates)
{
var start = dates.First();
var end = dates.First();
var prev = dates.First();
var next = DateTime.Now;
foreach (var d in dates.Skip(1))
{
next = d;
var diff = next - prev;
if (diff.TotalDays > 1)
{
yield return new Range { Start = start, End = end };
start = d;
}
prev = d;
end = d;
}
yield return new Range { Start = start, End = end };
}
public class Range
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
}