This question already has answers here:
How do I loop through a date range?
(17 answers)
Closed 6 years ago.
I have a DateTime StartDate and EndDate.
How can I, irrespective of times, iterate across each Day between those two?
Example: StartDate is 7/20/2010 5:10:32 PM and EndDate is 7/29/2010
1:59:12 AM.
I want to be able to iterate across 7/20, 7/21, 7/22 .. 7/29.
for(DateTime date = StartDate; date.Date <= EndDate.Date; date = date.AddDays(1))
{
...
}
The .Date is to make sure you have that last day, like in the example.
An alternative method that might be more reusable is to write an extension method on DateTime and return an IEnumerable.
For example, you can define a class:
public static class MyExtensions
{
public static IEnumerable EachDay(this DateTime start, DateTime end)
{
// Remove time info from start date (we only care about day).
DateTime currentDay = new DateTime(start.Year, start.Month, start.Day);
while (currentDay <= end)
{
yield return currentDay;
currentDay = currentDay.AddDays(1);
}
}
}
Now in the calling code you can do the following:
DateTime start = DateTime.Now;
DateTime end = start.AddDays(20);
foreach (var day in start.EachDay(end))
{
...
}
Another advantage to this approach is that it makes it trivial to add EachWeek, EachMonth etc. These will then all be accessible on DateTime.
You have to be careful about end-date. For example, in
Example: StartDate is 7/20/2010 5:10:32 PM and EndDate is 7/29/2010 1:59:12 AM.
I want to be able to iterate across 7/20, 7/21, 7/22 .. 7/29.
date < endDate will not include 7/29 ever. When you add 1 day to 7/28 5:10 PM - it becomes 7/29 5:10 PM which is higher than 7/29 2 AM.
If that is not what you want then I'd say you do
for (DateTime date = start.Date; date <= end.Date; date += TimeSpan.FromDays(1))
{
Console.WriteLine(date.ToString());
}
or something to that effect.
The loops of #Yuriy Faktorovich, #healsjnr and #mho will all throw a System.ArgumentOutOfRangeException: The added or subtracted value results in an un-representable DateTime
exception if EndDate == DateTime.MaxValue.
To prevent this, add an extra check at the end of the loop
for(DateTime date = StartDate; date.Date <= EndDate.Date; date = date.AddDays(1))
{
...
if (date.Date == DateTime.MaxValue.Date)
{
break;
}
}
(I would have posted this as a comment to #Yuriy Faktorovich's answer, but I lack reputation)
DateTime date = DateTime.Now;
DateTime endDate = date.AddDays(10);
while (date < endDate)
{
Console.WriteLine(date);
date = date.AddDays(1);
}
Related
I would like to get dates between two dates. Instead of expected 9 different dates, I get 875287 and run out of memory. What would be the problem with the code below?
StartDate value is 01/04/2016 00:00:00
EndDate value is 10/04/2016 00:00:00
var selectedDates = new List<DateTime?>();
for (var date = StartDate; date <= EndDate; date.Value.AddDays(1))
{
selectedDates.Add(date);
}
You aren't assigning the value of date.Value.AddDays(1) to anything, so it ends up in an infinite loop. You'd need to change your code so that date is set to the result of AddDays.
for (var date = StartDate; date <= EndDate; date = date.AddDays(1))
{
selectedDates.Add(date);
}
LINQ solution (let's generate selectedDates):
var selectedDates = Enumerable
.Range(0, int.MaxValue)
.Select(index => new DateTime?(StartDate.AddDays(index)))
.TakeWhile(date => date <= EndDate)
.ToList();
As far as I can see, since AddDays method returns a new instance of a DateTime, it does not change the current instance since DateTime is immutable.
Looks like your date is DateTime?, you can change this part as;
for (var date = StartDate; date <= EndDate; date = date.Value.AddDays(1))
{
selectedDates.Add(date);
}
As usr pointed, this might be affected on DST. You might wanna check Dmitry's answer as well.
A shorter notation using Linq's Range method uses the ability to already figure out the number of days using the TimeSpan.Days property after subtracting start from end.
Assuming the start is before end you'd end up with:
DateTime StartDate = new DateTime(1979, 10, 4);
DateTime EndDate = new DateTime(2016, 10, 4);
var dates = Enumerable.Range(0, (EndDate - StartDate).Days + 1)
.Select(day => StartDate.AddDays(day))
If you need it to be Nullable, add:
.Cast<DateTime?>()
If you need this to be a List, add:
.ToList()
It's probably quite a bit more efficient than the other LINQ based solution.
Decided to change it up with a do/while
var selectedDates = new List<DateTime?>();
DateTime? StartDate = DateTime.Parse("01/04/2016 00:00:00");
DateTime? EndDate = DateTime.Parse("10/04/2016 00:00:00");
do
{
selectedDates.Add(StartDate);
StartDate = StartDate.Value.AddDays(1);
}while(StartDate < EndDate);
This question already has answers here:
How can I get the DateTime for the start of the week?
(34 answers)
Closed 8 years ago.
I was wondering if you guys know how to get the date of currents week's monday based on todays date?
i.e 2009-11-03 passed in and 2009-11-02 gets returned back
/M
This is what i use (probably not internationalised):
DateTime input = //...
int delta = DayOfWeek.Monday - input.DayOfWeek;
DateTime monday = input.AddDays(delta);
The Pondium answer can search Forward in some case. If you want only Backward search I think it should be:
DateTime input = //...
int delta = DayOfWeek.Monday - input.DayOfWeek;
if(delta > 0)
delta -= 7;
DateTime monday = input.AddDays(delta);
Something like this would work
DateTime dt = DateTime.Now;
while(dt.DayOfWeek != DayOfWeek.Monday) dt = dt.AddDays(-1);
I'm sure there is a nicer way tho :)
public static class DateTimeExtension
{
public static DateTime GetFirstDayOfWeek(this DateTime date)
{
var firstDayOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
while (date.DayOfWeek != firstDayOfWeek)
{
date = date.AddDays(-1);
}
return date;
}
}
International here. I think as extension it can be more useful.
What about:
CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek
Why don't use native solution?
var now = System.DateTime.Now;
var result = now.AddDays(-((now.DayOfWeek - System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek + 7) % 7)).Date;
Probably will return you with Monday. Unless you are using a culture where Monday is not the first day of the week.
Try this:
public DateTime FirstDayOfWeek(DateTime date)
{
var candidateDate=date;
while(candidateDate.DayOfWeek!=DayOfWeek.Monday) {
candidateDate=candidateDate.AddDays(-1);
}
return candidateDate;
}
EDIT for completeness: overload for today's date:
public DateTime FirstDayOfCurrentWeek()
{
return FirstDayOfWeek(DateTime.Today);
}
I am trying to make a string with start dates and end dates. That can loop over X number of days.
int nrOfDaysToLoopBy = 3;
List<string> Dates = new List<string>();
string startDate = "2014-01-01"; //this date is given to me by an api I am just hard codeing for testing
string endDate = "2014-01-30";
DateTime StartDate = DateTime.ParseExact(startDate, "yyyy-MM-dd", CultureInfo.InvariantCulture);
DateTime EndDate = DateTime.ParseExact(endDate, "yyyy-MM-dd", CultureInfo.InvariantCulture);
DateTime myDate = StartDate; // setting the initial date
for (DateTime date = StartDate.AddDays(nrOfDaysToLoopBy); date.Date <= EndDate.Date; date = date.AddDays(nrOfDaysToLoopBy))
{
Dates.Add("start-date=" + myDate.ToString("yyyy-MM-dd") + "&end-date=" + date.ToString("yyyy-MM-dd"));
myDate = date.AddDays(1);
}
// Dealing with any left over days.
if (myDate != EndDate && EndDate > myDate)
{
Dates.Add("start-date=" + myDate.ToString("yyyy-MM-dd") + "&end-date=" + EndDate.ToString("yyyy-MM-dd"));
}
My results:
start-date=2014-01-01&end-date=2014-01-04
start-date=2014-01-05&end-date=2014-01-07
The problem here is that there is 4 days between 2014-01-01 and 2014-01-04 not 3.
Results I am trying to get:
start-date=2014-01-01&end-date=2014-01-03
start-date=2014-01-04&end-date=2014-01-06
Update:
Can we agree that the days between 2014-01-01&end-date=2014-01-04 are
2014-01-01, 2014-01-02, 2014-01-03, and 2014-01-04 That's 4
I have been playing with this for a few hours now and nothing I have done has fixed the problem.
The problem here is that there is 4 days between 2014-01-01 and 2014-01-04 not 3.
One could argue that there's 3 days between 2014-01-01 and 2014-01-04: Between 2014-01-01 and 2014-01-04, three 24h periods pass:
2014-01-01 -- 2014-01-02
2014-01-02 -- 2014-01-03
2014-01-03 -- 2014-01-04
You see, the problem is how you define between. If you want to include the start and the end date, you need to adjust the number of dates you add.
Edit:
This fixed the problem. nrOfDaysToLoopBy-1
for (DateTime date = StartDate.AddDays(nrOfDaysToLoopBy-1); date.Date <= EndDate.Date; date = date.AddDays(nrOfDaysToLoopBy))
{
}
Simply change the statement:
DateTime date = StartDate.AddDays(nrOfDaysToLoopBy);
in your for loop initialization to
DateTime date = StartDate.AddDays(nrOfDaysToLoopBy-1);
The issue is that when you add days, the number of days "between" as you're calling it is actually the number of days you add + 1. So monday->monday (zero days added) is 1 day, monday->tuesday (one day added) is 2 days, etc. That's why you need the -1 modification for the start date.
The reason you don't need this alteration on every other iteration on the loop is because of the myDate = date.AddDays(1) line. This reduces the difference between myDate and date by one, bringing it back to the correct difference
I have two dates:
DateTime fromDate = new DateTime(2013,7,27,12,0,0);
DateTime toDate = new DateTime(2013,7,30,12,0,0);
I want to iterate from fromDate to toDate by incrementing fromDate with a single day and the loop should break when fromDate becomes equal to or greater than the toDate. I have tried this:
while(fromDate < toDate)
{
fromDate.AddDays(1);
}
But this is an infinite loop and won't stop. How can I do this ?
Untested but should work:
for(DateTime date = fromDate; date < toDate; date = date.AddDays(1)) {
}
Modify the comparison to <= if you want to include toDate as well.
DateTime.AddDays indeed adds the specified number of days to the date - but the resulting date is returned as a new DateTime value; the original DateTime value is not changed.
Therefore, make sure you assign the result of the your operation back to the variable you inspect in your loop condition:
while (fromDate < toDate)
{
fromDate = fromDate.AddDays(1);
}
I need to find the difference in days between two dates.
For example:
Input: **startDate** = 12-31-2012 23hr:59mn:00sec, **endDate** = 01-01-2013 00hr:15mn:00sec
Expected output: 1
I tried the following:
(dt1-dt2).TotalDays and convert to integer but didn't give me appropriate answer as double has to be converted to int - tried Math.Ceiling, Convert.To...
dt1.day - dt2.day does not work across months
dt.Substract() has the same output as option 1 mentioned above.
None of the above worked, so I ended up writing the following code. The code works well, but I feel that there must be a solution with only a couple of lines of code.
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
//Initializing with 0 as default return value
int difference = 0;
//If either of the dates are not set then return 0 instead of throwing an exception
if (startDate == default(DateTime) | endDate == default(DateTime))
return difference;
//If the dates are same then return 0
if (startDate.ToShortDateString() == endDate.ToShortDateString())
return difference;
//startDate moving towards endDate either with increment or decrement
while (startDate.AddDays(difference).ToShortDateString() != endDate.ToShortDateString())
{
difference = (startDate < endDate) ? ++difference : --difference;
}
return difference;
}
Note: I do not have any performance issue in the while-loop iteration as the max difference will not be more than 30 to 45 days.
Well, it sounds like you want the difference in the number of days, ignoring the time component. A DateTime with the time component reset to 00:00:00 is what the Date property gives you:
(startDate.Date - endDate.Date).TotalDays
If you use the DateTime.Date property this will eliminate the time
date1.Date.Subtract(date2.Date).Days
Use TimeStamp. Just subtract two dates (using DateTime.Date property), get the difference in time span and return TotalDays
TimeSpan ts = endDate.Date - startDate.Date;
double TotalDays = ts.TotalDays;
So your extension method can be as simple as:
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
return (int) (endDate.Date - startDate.Date).TotalDays;
// to return just a int part of the Total days, you may round it according to your requirement
}
EDIT: Since the question has been edited, you may check the following example.
Consider the following two dates.
DateTime startDate = new DateTime(2012, 12, 31, 23, 59, 00);
DateTime endDate = new DateTime(2013, 01, 01, 00, 15, 00);
You can write the extension method as:
public static int GetDifferenceInDaysX(this DateTime startDate, DateTime endDate)
{
TimeSpan ts = endDate - startDate;
int totalDays = (int) Math.Ceiling(ts.TotalDays);
if (ts.TotalDays < 1 && ts.TotalDays > 0)
totalDays = 1;
else
totalDays = (int) (ts.TotalDays);
return totalDays;
}
For the above dates it will give you 1