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

我有两个日期,一个开始日期和一个结束日期,在指定的时间间隔内,我需要采取一些行动。例如:对于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;
     }

}

但似乎还有更好的办法?


当前回答

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

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

使用

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 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
}

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

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 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
 }

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

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

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

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

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