我需要你的帮助。我想弄清楚如何找到 EndDate 和下一个 StartDate 之间的差距。如果存在差距,我需要返回差距所在的值。你能帮我吗?
我有一个包含开始日期和结束日期的列表。 示例:
1 和 2 之间没有间隙。 2 (Enddate) 和 3 (Stardate) 之间是一个 Gap,需要返回这样的结果:Gap found between 2/16/2021 and 2/19/2021.
我已经尝试过这个,但对我来说效果不佳,你们中有人可以帮助我吗?
static void Main(string[] args)
{
List<DateRanges> DateRanges = new List<DateRanges>();
DateRanges.Add(new DateRanges() { StartDate = new DateTime(2021, 01, 01), EndDate = new DateTime(2021, 01, 31) });
DateRanges.Add(new DateRanges() { StartDate = new DateTime(2021, 02, 10), EndDate = new DateTime(2021, 02, 25) });
var missing = DateRangeEnumerable.GetDates(DateRanges);
var ranges = missing.GetRanges();
}
public class DateRanges
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
//public DateRanges(DateTime Start, DateTime End)
//{
// StartDate = Start;
// EndDate = End;
//}
}
public static class DateRangeEnumerable
{
public static IEnumerable<DateTime> GetDates(this IEnumerable<DateRanges> source)
{
var sortedSource = source.OrderBy(r => r.StartDate);
foreach (var range in sortedSource)
{
var d = range.StartDate;
while (d < range.EndDate)
{
yield return d;
d = d.AddDays(1);
}
}
}
public static IEnumerable<DateRanges> GetRanges(this IEnumerable<DateTime> source)
{
var sortedSource = source.OrderBy(d => d);
var enumerator = sortedSource.GetEnumerator();
if (!enumerator.MoveNext())
yield break;
DateTime from = enumerator.Current;
DateTime prev = from;
while (true)
{
while (true)
{
if (enumerator.MoveNext())
{
if (enumerator.Current == prev.AddDays(1))
prev = enumerator.Current;
else
break;
}
else
{
yield return new DateRanges() { StartDate = from, EndDate = prev.AddDays(1) };
yield break;
}
}
yield return new DateRanges() { StartDate = from, EndDate = prev.AddDays(1) };
from = enumerator.Current;
prev = enumerator.Current;
}
}
}
答案 0 :(得分:2)
示例
var dateRanges = new List<DateRanges>
{
new() {StartDate = new DateTime(2021, 2, 01), EndDate = new DateTime(2021, 2, 10)},
new() {StartDate = new DateTime(2021, 02, 11), EndDate = new DateTime(2021, 02, 15)},
new() {StartDate = new DateTime(2021, 02, 20), EndDate = new DateTime(2021, 02, 25)}
};
var end = dateRanges.First().EndDate;
foreach (var range in dateRanges.Skip(1))
{
if(end.AddDays(1) < range.StartDate )
Console.WriteLine($"{end.AddDays(1):d} - {range.StartDate.AddDays(-1):d}");
end = range.EndDate;
}
输出
16/02/2021 - 19/02/2021
免责声明:这不包含错误检查、排序、代码中没有暗示的内容,并假设日期没有时间值。它只是复制你的描述
答案 1 :(得分:1)
使用链表怎么样?
代码:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
var ranges = new List<DateRange>();
ranges.Add(
new DateRange
{
StartDate = new DateTime(2021, 01, 01),
EndDate = new DateTime(2021, 01, 31)
}
);
ranges.Add(
new DateRange
{
StartDate = new DateTime(2021, 02, 10),
EndDate = new DateTime(2021, 02, 25)
}
);
var list = new LinkedList<DateRange>(ranges);
var gaps = new List<LinkedListNode<DateRange>>();
var current = list.First;
while (current != null)
{
var next = current.Next;
if (next != null && next.Value.StartDate > current.Value.EndDate)
gaps.Add(current);
current = next;
}
Console.WriteLine("Gaps found:");
foreach (var gap in gaps)
{
Console.WriteLine("---------------------------");
Console.WriteLine("Date Range 1:");
Console.WriteLine(gap.Value);
Console.WriteLine("Date Range 2:");
Console.WriteLine(gap.Next!.Value);
Console.WriteLine(
$"Gap length in minutes: {(gap.Next.Value.StartDate - gap.Value.EndDate).TotalMinutes}");
Console.WriteLine("---------------------------");
}
}
}
public class DateRange
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public override string ToString()
{
return $"{nameof(StartDate)}: {StartDate}, {nameof(EndDate)}: {EndDate}";
}
}
}
结果:
Gaps found:
---------------------------
Date Range 1:
StartDate: 1/1/2021 12:00:00 AM, EndDate: 1/31/2021 12:00:00 AM
Date Range 2:
StartDate: 2/10/2021 12:00:00 AM, EndDate: 2/25/2021 12:00:00 AM
Gap length in minutes: 14400
---------------------------
答案 2 :(得分:1)
好吧,您可以像这样枚举差距:
private static IEnumerable<DateRanges> Gaps(IEnumerable<DateRanges> dates) {
var source = dates
.OrderBy(range => range.StartDate);
DateTime last = DateTime.MinValue;
bool first = true;
foreach (var range in source) {
if (!first && range.StartDate.AddDays(1) > last)
yield return new DateRanges() {
StartDate = last.AddDays(1),
EndDate = range.StartDate.AddDays(-1))
};
// In case of overlapping periods we have to pick the latest date
last = first || range.EndDate > last
? range.EndDate
: last;
first = false;
}
}
如果你想打印它们,你所要做的就是循环:
foreach (var gap in Gaps(dateRanges))
Console.WriteLine($"Gap found between {gap.StartDate} and {gap.EndDate}");
答案 3 :(得分:1)
我喜欢使用返回后续项对的通用扩展方法:
public static IEnumerable<(T Previous, T Next)> PreviousAndNext<T>(this IEnumerable<T> self)
{
using (var iter = self.GetEnumerator())
{
if (!iter.MoveNext())
yield break;
var previous = iter.Current;
while (iter.MoveNext())
{
var next = iter.Current;
yield return (previous, next);
previous = next;
}
}
}
这允许非常紧凑的 linq 查询
DateRanges.PreviousAndNext()
.Where(p => p.Previous.EndDate.AddDays(1) < p.Next.StartDate)
.Select(p => (p.Previous.EndDate, p.Next.StartDate));