我甚至不知道如何做到这一点,而不使用一些可怕的循环/计数器类型的解决方案。问题是这样的:
我有两个日期,一个开始日期和一个结束日期,在指定的时间间隔内,我需要采取一些行动。例如:对于3/10/2009之间的每个日期,每隔三天直到3/26/2009,我需要在列表中创建一个条目。所以我的输入是:
DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;
我的输出将是一个具有以下日期的列表:
3/13/2009
3/16/2009
3/19/2009
3/22/2009
3/25/2009
那我要怎么做这种事呢?我考虑过使用一个for循环,它会在每天的范围内迭代,并使用一个单独的计数器,如下所示:
int count = 0;
for(int i = 0; i < n; i++)
{
count++;
if(count >= DayInterval)
{
//take action
count = 0;
}
}
但似乎还有更好的办法?
不管怎样,你都需要对它们进行循环。我喜欢这样定义一个方法:
public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
yield return day;
}
然后你可以这样使用它:
foreach (DateTime day in EachDay(StartDate, EndDate))
// print it or whatever
以这种方式,你可以每隔一天,每三天,只有工作日,等等。例如,要每三天返回一次“开始”日期,你可以在循环中调用AddDays(3)而不是AddDays(1)。
来自@mquander和@Yogurt The Wise的代码用于扩展:
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<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date || month.Month == thru.Month; month = month.AddMonths(1))
yield return month;
}
public static IEnumerable<DateTime> EachDayTo(this DateTime dateFrom, DateTime dateTo)
{
return EachDay(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachMonthTo(this DateTime dateFrom, DateTime dateTo)
{
return EachMonth(dateFrom, dateTo);
}
一年后,希望它能帮助到某人,
为了更加灵活,这个版本包含了一个谓词。
使用
var today = DateTime.UtcNow;
var birthday = new DateTime(2018, 01, 01);
每天到我生日
var toBirthday = today.RangeTo(birthday);
每月到我生日,第2步
var toBirthday = today.RangeTo(birthday, x => x.AddMonths(2));
每年我的生日
var toBirthday = today.RangeTo(birthday, x => x.AddYears(1));
使用RangeFrom代替
// same result
var fromToday = birthday.RangeFrom(today);
var toBirthday = today.RangeTo(birthday);
实现
public static class DateTimeExtensions
{
public static IEnumerable<DateTime> RangeTo(this DateTime from, DateTime to, Func<DateTime, DateTime> step = null)
{
if (step == null)
{
step = x => x.AddDays(1);
}
while (from < to)
{
yield return from;
from = step(from);
}
}
public static IEnumerable<DateTime> RangeFrom(this DateTime to, DateTime from, Func<DateTime, DateTime> step = null)
{
return from.RangeTo(to, step);
}
}
临时演员
你可以抛出一个异常,如果fromDate > toDate,但我更喜欢返回一个空范围,而不是[]
@jacob-sobus和@mquander和@Yogurt不完全正确。如果我需要第二天,我通常等待00:00的时间
public static IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = from.Date; day.Date <= thru.Date; day = day.NextDay())
yield return day;
}
public static IEnumerable<DateTime> EachMonth(DateTime from, DateTime thru)
{
for (var month = from.Date; month.Date <= thru.Date || month.Year == thru.Year && month.Month == thru.Month; month = month.NextMonth())
yield return month;
}
public static IEnumerable<DateTime> EachYear(DateTime from, DateTime thru)
{
for (var year = from.Date; year.Date <= thru.Date || year.Year == thru.Year; year = year.NextYear())
yield return year;
}
public static DateTime NextDay(this DateTime date)
{
return date.AddTicks(TimeSpan.TicksPerDay - date.TimeOfDay.Ticks);
}
public static DateTime NextMonth(this DateTime date)
{
return date.AddTicks(TimeSpan.TicksPerDay * DateTime.DaysInMonth(date.Year, date.Month) - (date.TimeOfDay.Ticks + TimeSpan.TicksPerDay * (date.Day - 1)));
}
public static DateTime NextYear(this DateTime date)
{
var yearTicks = (new DateTime(date.Year + 1, 1, 1) - new DateTime(date.Year, 1, 1)).Ticks;
var ticks = (date - new DateTime(date.Year, 1, 1)).Ticks;
return date.AddTicks(yearTicks - ticks);
}
public static IEnumerable<DateTime> EachDayTo(this DateTime dateFrom, DateTime dateTo)
{
return EachDay(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachMonthTo(this DateTime dateFrom, DateTime dateTo)
{
return EachMonth(dateFrom, dateTo);
}
public static IEnumerable<DateTime> EachYearTo(this DateTime dateFrom, DateTime dateTo)
{
return EachYear(dateFrom, dateTo);
}