我如何循环通过日期范围?

我甚至不知道如何做到这一点,而不使用一些可怕的循环/计数器类型的解决方案。问题是这样的:

我有两个日期,一个开始日期和一个结束日期,在指定的时间间隔内,我需要采取一些行动。例如:对于3/10/2009之间的每个日期,每隔三天直到3/26/2009,我需要在列表中创建一个条目。所以我的输入是:

DateTime StartDate = "3/10/2009";
DateTime EndDate = "3/26/2009";
int DayInterval = 3;

我的输出将是一个具有以下日期的列表:

< p > 3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009 < / p >

那我要怎么做这种事呢?我考虑过使用一个for循环,它会在每天的范围内迭代,并使用一个单独的计数器,如下所示:

int count = 0;


for(int i = 0; i < n; i++)
{
count++;
if(count >= DayInterval)
{
//take action
count = 0;
}


}

但似乎还有更好的办法?

205967 次浏览

不管怎样,你都需要对它们进行循环。我喜欢这样定义一个方法:

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)

您可以使用DateTime.AddDays()函数将您的DayInterval添加到StartDate中,并检查以确保它小于EndDate

举个例子,你可以试试

DateTime StartDate = new DateTime(2009, 3, 10);
DateTime EndDate = new DateTime(2009, 3, 26);
int DayInterval = 3;


List<DateTime> dateList = new List<DateTime>();
while (StartDate.AddDays(DayInterval) <= EndDate)
{
StartDate = StartDate.AddDays(DayInterval);
dateList.Add(StartDate);
}

我在MiscUtil中有一个Range类,你可以发现它很有用。结合各种扩展方法,你可以做到:

foreach (DateTime date in StartDate.To(EndDate).ExcludeEnd()
.Step(DayInterval.Days())
{
// Do something with the date
}

(你可能想要也可能不想要排除结尾——我只是想提供它作为一个例子。)

这基本上是现成的(更通用的)mquander解决方案形式。

DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;


while ((startDate = startDate.AddDays(interval)) <= stopDate)
{
// do your thing
}
DateTime startDate = new DateTime(2009, 3, 10);
DateTime stopDate = new DateTime(2009, 3, 26);
int interval = 3;


for (DateTime dateTime=startDate;
dateTime < stopDate;
dateTime += TimeSpan.FromDays(interval))
{


}

你可以考虑写一个迭代器,这样你就可以使用普通的for循环语法,比如++。我搜索并在StackOverflow上找到了一个类似的问题回答,它给出了使DateTime可迭代的指针。

来自@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);
}

根据问题你可以试试这个…

// looping between date range
while (startDate <= endDate)
{
//here will be your code block...


startDate = startDate.AddDays(1);
}

谢谢……

在这里,你必须小心不要错过日期,因为在循环中,一个更好的解决方案是。

这为您提供了startdate的第一个日期,并在递增之前在循环中使用它,它将处理所有日期,包括enddate的最后一个日期,因此<= enddate。

所以上面的答案是正确的。

while (startdate <= enddate)
{
// do something with the startdate
startdate = startdate.adddays(interval);
}

一年后,希望它能帮助到某人,

为了更加灵活,这个版本包含了谓词

使用

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,可以抛出异常,但我更喜欢返回一个空范围而不是[]

DateTime begindate = Convert.ToDateTime("01/Jan/2018");
DateTime enddate = Convert.ToDateTime("12 Feb 2018");
while (begindate < enddate)
{
begindate= begindate.AddDays(1);
Console.WriteLine(begindate + "  " + enddate);
}

你可以用这个。

 DateTime dt0 = new DateTime(2009, 3, 10);
DateTime dt1 = new DateTime(2009, 3, 26);


for (; dt0.Date <= dt1.Date; dt0=dt0.AddDays(3))
{
//Console.WriteLine(dt0.Date.ToString("yyyy-MM-dd"));
//take action
}

每15分钟迭代一次

DateTime startDate = DateTime.Parse("2018-06-24 06:00");
DateTime endDate = DateTime.Parse("2018-06-24 11:45");


while (startDate.AddMinutes(15) <= endDate)
{


Console.WriteLine(startDate.ToString("yyyy-MM-dd HH:mm"));
startDate = startDate.AddMinutes(15);
}

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

以下是我对2020年的看法。

Enumerable.Range(0, (endDate - startDate).Days + 1)
.ToList()
.Select(a => startDate.AddDays(a));

如果你将日期转换为OADate,你可以像处理任何double数字一样循环遍历它们。

DateTime startDate = new DateTime(2022, 1, 1);
DateTime endDate = new DateTime(2022, 12, 31);


for (double loopDate = startDate.ToOADate(); loopDate <= endDate.ToOADate(); loopDate++)
{
DateTime selectedDate;
selectedDate = DateTime.FromOADate(loopDate);
}