6

I'm looking to count the number of dates covered (inclusive) between two DateTimes.

This is not .TotalDays as periods less than 24 hours may still return "2" by overlapping two different days. Likewise, two dates minutes apart should still return "1".

For example:

2012-2-1 14:00 to 2012-2-2 23:00 -> 2 (1st and 2nd Feb)
2012-2-1 14:00 to 2012-2-2 10:00 -> 2 (1st and 2nd Feb)
2012-2-1 23:00 to 2012-2-2 00:00 -> 2 (1st and 2nd Feb)
2012-2-1 23:00 to 2012-2-3 00:00 -> 3 (1st, 2nd, 3rd Feb)
2012-2-1 14:00 to 2012-2-1 15:00 -> 1 (1st Feb)
2012-2-1 14:00 to 2012-2-1 14:00 -> 1 (1st Feb)
2012-1-1 00:00 to 2012-12-31 23:59 -> 366 (All of 2012)

I can get this functionality with the code below:

DateTime dt1 = new DateTime(2000,1,2,12,00,00);
DateTime dt2 = new DateTime(2000,1,3,03,00,00);

int count = 0;
for (DateTime date = dt1; date.Date <= dt2.Date; date = date.AddDays(1))
    count++;

return count;

Is there a better way?

Matt Mitchell
  • 40,943
  • 35
  • 118
  • 185
  • What about d1.Date.Subtract(d2.Date).TotalDays + 1 – Adriaan Stander Dec 20 '12 at 11:01
  • 1
    Not sure how it's a duplicate. Two dates on the same day should still return 1. A period less than 24 hours crossing two days should return two days. – Matt Mitchell Dec 20 '12 at 11:03
  • 1
    NodaTime is great for this sort of thing, refer to: [How to use NodaTime to calculate an inclusive days period][1] [1]: http://stackoverflow.com/questions/10336863/how-to-use-nodatime-to-calculate-an-inclusive-days-period – Chris Fulstow Dec 20 '12 at 11:04
  • This is not a duplicate as evidenced by the fact it has a different answer from the nominated duplicate... – Matt Mitchell Dec 21 '12 at 02:55

4 Answers4

19

Why not just:

int count = dt1.Date.Subtract(dt2.Date).Duration().Days + 1;

Using .Date normalizes the Date to midnight (0:00), add 1 to the Days to get the number of different dates, not just the number of days in between.

Using Duration makes sure you always get a positive answer.

Davio
  • 4,609
  • 2
  • 31
  • 58
  • That'll do it. Will accept when I can. I didn't notice that it was always off by 1 for all tests so good spot. – Matt Mitchell Dec 20 '12 at 11:10
  • 1
    You can use a minus rather than `.Subtract` to simplify it a bit (as per @Tim Schmelter's answer) – Matt Mitchell Dec 20 '12 at 11:21
  • 2
    @MattMitchell Yes, it's a question of preference, I like using Subtract when I'm chaining like this. – Davio Dec 20 '12 at 11:22
  • Incidentally, your `Duration()` should be a method call not a property. It actually handles misordered dates which my original sample doesn't. – Matt Mitchell Dec 20 '12 at 11:23
7

Perhaps simply

TimeSpan duration = dt2.Date - dt1.Date;
int days = duration.Days + 1;

Demo

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
0
DateTime d1=DateTime.MinValue;
DateTime d2=DateTime.MaxValue;
TimeSpan span=d2-d1;
int counter = span.Days + 1;
Nipun Gogia
  • 1,846
  • 1
  • 11
  • 17
0

Math.Ceiling((d2 - d1.Date).TotalDays)

Tried all cases you mentioned. And results are expected! Hope it helps.

Yahya
  • 3,386
  • 3
  • 22
  • 40
  • Good effort but it won't handle 2000/1/1 23:00 to 2000/1/2 00:00 (it returns 1 and should be 2 as there are 2 dates there). See @Davio's accepted answer for a working solution. – Matt Mitchell Dec 20 '12 at 11:25
  • 2
    @MattMitchell This demonstrates that mathematically "taking `Ceiling`" is not the same as "taking `Floor` and adding `1`". The latter would give a correct behavior. – Jeppe Stig Nielsen Dec 21 '12 at 19:28