views:

1344

answers:

7

I'm not even sure how to do this without using some horrible for loop/counter type solution. Here's the problem:

I'm given two dates, a start date and an end date and on a specified interval I need to take some action. For example: for every date between 3/10/2009 on every third day until 3/26/2009 I need to create an entry in a List. So my inputs would be:

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

and my output would be a list that has the following dates:

3/13/2009 3/16/2009 3/19/2009 3/22/2009 3/25/2009

So how the heck would I do something like this? I thought about using a for loop that would iterate between every day in the range with a separate counter like so:

int count = 0;

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

}

But it seems like there could be a better way?

+27  A: 

Well, you'll need to loop over them one way or the other. I prefer defining a method like this:

public IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
    for(var day = from.Date; day.Date <= thru.Date; day = day.AddDays(1))
        yield return day;
}

Then you can use it like this:

foreach (DateTime day in EachDay(StartDate, EndDate))
    // print it or whatever

In this manner you could hit every other day, every third day, only weekdays, etc. For example, to return every third day starting with the "start" date, you could just call AddDays(3) in the loop instead of AddDays(1).

mquander
You can even add another parameter for the interval.
Justin Drury
you sir, are my hero!
onekidney
This will be inclusive of the first date. If you dont want that, just change the 'var day = from.Date' to 'var day = from.Date.AddDays(dayInterval)'
SwDevMan81
A really nice solution for an interesting and real word problem. I like how this shows quite a few useful techniques of the language. And this reminds me that for loop is not only for (int i = 0;...) (-.
Audrius
A: 

You can use the DateTime .AddDays() function to add your DayInterval to the StartDate and check to make sure it is less than the EndDate.

TLiebe
+2  A: 

For your example you can try

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);
}
astander
That's the same thing I was thinking (though I like mquander's answer above too) but I can't figure out how you get a nice code sample posted so quickly!
TLiebe
@TLiebe: Practice.
Jason
+6  A: 

I have a Range class in MiscUtil which you could find useful. Combined with the various extension methods, you could do:

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

(You may or may not want to exclude the end - I just thought I'd provide it as an example.)

This is basically a ready-rolled (and more general-purpose) form of mquander's solution.

Jon Skeet
Certainly just a matter of taste whether you like such things to be extension methods or not. `ExcludeEnd()` is cute.
mquander
You can, of course, do all of that without using the extension methods. It'll just be a lot uglier and harder to read IMO :)
Jon Skeet
Wow - what a great resource MiscUtil is - thanks for your answer!
onekidney
+1  A: 
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
}
devnull
A: 
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))
{

}
gilbertc
+1  A: 

You might consider writing an iterator instead, which allows you to use normal 'for' loop syntax like '++'. I searched and found a similar question answered here on StackOverflow which gives pointers on making DateTime iterable.

REDace0
Great info - thanks!
onekidney