如何遍历日期范围?

时间:2009-12-04 15:13:18

标签: c# asp.net datetime loops

如果不使用一些可怕的循环/计数器类型解决方案,我甚至不确定如何做到这一点。这是问题所在:

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

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

我的输出将是一个包含以下日期的列表:

2009年3月13日 2009年3月16日 3/19/2009 2009年3月22日 2009年3月25日

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

int count = 0;

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

}

但似乎有更好的方法?

16 个答案:

答案 0 :(得分:415)

嗯,你需要以某种方式循环它们。我更喜欢定义这样的方法:

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)

答案 1 :(得分:28)

我在MiscUtil中有Range个课程,您可以找到它。结合各种扩展方法,您可以:

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

(你可能想也可能不想排除结尾 - 我只是想把它作为一个例子。)

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

答案 2 :(得分:19)

对于您的示例,您可以尝试

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

答案 3 :(得分:12)

来自@mquander和@Yogurt的代码扩展中使用的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);
}

答案 4 :(得分:7)

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))
{

}

答案 5 :(得分:6)

1年后,可能对某人有帮助,

此版本包含谓词,更灵活。

用法

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,您可以抛出异常,但我更愿意返回空范围[]

答案 6 :(得分:3)

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
}

答案 7 :(得分:2)

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

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

    startDate = startDate.AddDays(1);
}

感谢......

答案 8 :(得分:1)

您可以使用DateTime.AddDays()功能将DayInterval添加到StartDate并检查以确保它低于EndDate

答案 9 :(得分:1)

您可以考虑编写一个迭代器,它允许您使用普通的'for'循环语法,如'++'。我在StackOverflow上搜索并发现了类似的问题answered,它提供了使DateTime可迭代的指示。

答案 10 :(得分:1)

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

答案 11 :(得分:0)

你必须要小心,不要错过在循环中更好的解决方案的日期。

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

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

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

答案 12 :(得分:0)

你可以使用它。

 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
 }

答案 13 :(得分:0)

每15分钟进行一次迭代

okhttp

答案 14 :(得分:0)

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

答案 15 :(得分:0)

这是我2020年的2美分。

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