[英]Check number of Dates in Date Range that are sequential in c#?
我正在尝试创建一个函数,该函数返回从特定日期开始的日期范围内的连续日期数。
例子:
开始日期:2022 年 9 月 1 日
日期范围:9/1/2022、9/2/2022、9/3/2022、9/4/2022、9/7/2022
在这种情况下,我正在寻找的函数将返回 4。
假设日期可以是无序的,并且它们可以滚动到下个月,因此 StartDate 9/29/2022:
9/29/2022、9/30/2022、10/1/2022、10/4/2022 将返回 3。
我知道我可以遍历从特定日期开始的日期并检查连续天数,但我想知道是否有一种干净的方法可以使用 Linq 来完成。
这是我能想到的最干净的解决方案......
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;
}
}
}
输出是:01.09.2022 0:00:00 02.09.2022 0:00:00 03.09.2022 0:00:00 04.09.2022 0:00:00
如果你想要计数,你可以在结果上调用 .Count() 或者只修改方法......应该很容易。
计算给定日期范围内连续日期的数量。
TakeWhile
方法从列表的开头获取一系列连续的日期。public class Program
{
private static void Main(string[] args)
{
var dateRange = "9/29/2022, 9/30/2022, 10/1/2022, 10/4/2022";
var dates = dateRange
.Split(", ")
.Select(dateStr =>
{
var dateData = dateStr.Split("/");
var month = int.Parse(dateData[0]);
var day = int.Parse(dateData[1]);
var year = int.Parse(dateData[2]);
return new DateTime(year, month, day);
})
.OrderBy(x => x)
.ToList();
var consecutiveDatesCounter = dates
.TakeWhile((date, i) => i == 0 || dates[i - 1].AddDays(1) == date)
.Count();
Console.WriteLine(consecutiveDatesCounter);
}
}
输出: 3
演示: https ://dotnetfiddle.net/tYdWvz
使用循环可能是最干净的方法。 我会使用类似下面的东西:
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;
}
另一种使用循环的方法。 (我同意其他人的说法,循环比使用 Linq 完成此任务更干净。)
public static int NumConsecutiveDays(IEnumerable<DateTime> dates)
{
var previous = DateTime.MinValue;
var oneDay = TimeSpan.FromDays(1);
int result = 0;
foreach (var current in dates.OrderBy(d => d))
{
if (current.Date - previous.Date == oneDay)
++result;
previous = current;
}
return result > 0 ? result + 1 : 0; // Need to add 1 to result if it is not zero.
}
var dates = new List<DateTime>() {new DateTime(2014,1,1), new DateTime(2014, 1, 2), new DateTime(2014, 1, 3) , new DateTime(2014, 1, 5), new DateTime(2014, 1, 6), new DateTime(2014, 1, 8) };
var startDate = new DateTime(2014,1,2);
var EarliestContiguousDates = dates.Where(x => x>=startDate).OrderBy(x => x)
.Select((x, i) => new { date = x, RangeStartDate = x.AddDays(-i) })
.TakeWhile(x => x.RangeStartDate == dates.Where(y => y >= startDate).Min()).Count();
您要么对日期进行排序并找到连续的日期,要么不对其进行排序并重复遍历该集合以寻找匹配项。
这是后一种愚蠢的方法,将其保持未排序并重复调用“IndexOf”:
public static int CountConsecutiveDays(DateTime startingFrom, List<DateTime> data)
{
int count = 0;
int index = data.IndexOf(startingFrom);
while(index != -1) {
count++;
startingFrom = startingFrom.AddDays(1);
index = data.IndexOf(startingFrom);
}
return count;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.