How to corectly Loop over days - c#

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

Related

How to check current date is greater then or equal to stored in data base date and time in C#

'Following is the code, I want to be check stored in database date and time if greater or equal then current date and time, if current date is greater then stored date then how to compare Time in this check
DateTime sysDate = DateTime.Now.Date;
int sysMinute = DateTime.Now.Minute;
int sysHour = DateTime.Now.Hour;
DateTime scheduledDate = Convert.ToDateTime(item.Scheduled_Start_Date.ToString()).Date;
int scheduledMinute = Convert.ToDateTime(item.Scheduled_Start_Time.ToString()).Minute;
int scheduledHour = Convert.ToDateTime(item.Scheduled_Start_Time.ToString()).Hour;
if (sysDate >= scheduledDate && sysMinute >= scheduledMinute && sysHour >= scheduledHour)
{
var currency = GetEventCurrency(evDB.EventID);
ev.PriceRange = currency.GetFormattedAmount(item.ScheduledPrice.ToString());
isScheduledPrice = true;
}
When getting system datetime with DateTime.Now you have to be aware that several calls may produce incoherent results. This is specially important on the change of the minute, hour or even day.
Do just one call and operate with that result.
In your question is not necessary to segregate DateTime components.
DateTime sysDate = DateTime.Now;
DateTime scheduledDate = Convert.ToDateTime(item.Scheduled_Start_Date.ToString()).Date;
DateTime scheduledTime = Convert.ToDateTime(item.Scheduled_Start_Time.ToString()).Time;
DateTime scheduledDateTime = scheduledDate + scheduledTime;
Once scheduled datetime is in C# format you can just compare them:
if (sysDate >= scheduledDateTime)
{
var currency = GetEventCurrency(evDB.EventID);
ev.PriceRange = currency.GetFormattedAmount(item.ScheduledPrice.ToString());
isScheduledPrice = true;
}
Datetimes in C# are stored in ticks (100 ns) from 00:00:00 of January 1st of year 1 up to the expressed date and time.
Comparison thus is easy as those are just scalars (internally).

Remove '0' Number from time 9:00 AM

I have time format like 9:00AM - 10:00AM.
string startTime = "9:00AM";
string endTime = "10:00AM";
I want to display it like 9-10 AM.
How can I achieve it?
Parse your times
var sdt = DateTime.ParseExact(startTime, "h:mmtt", CultureInfo.InvariantCulture);
var edt = ...
Compare the meridian designators or check if the start is before 12 and the end is after:
if(sdt.Hour < 12 && edt.Hour >= 12)
If the times are in the same day half, use format ${sdt:h}-{edt:htt}"
If the times are in different day halves use format ${sdt:htt}-{edt:htt}"
If you have datetime, use datetime.ToString("HH");
If you don't, you can also write like that (remove AM before doing it)
Convert.ToDateTime(starttime).ToString("HH");
There are also easier ways to do it if you have fixed numbers;
starttime.Replace(":00","")
string starttime = "9:00AM";
string Endtime = "10:00AM";
starttime = starttime.Replace(":00AM","");
Endtime = Endtime.Replace(":00","");
var result = starttime + "-" + Endtime;
But i think you must change the Format of starttime and endtime to a TimeSpan or DateTime

How to compare a given date from today

I want to compare a given date to today and here is the condition: If provided date is greater than or equal to 6 months earlier from today, return true else return false
Code:
string strDate = tbDate.Text; //2015-03-29
if (DateTime.Now.AddMonths(-6) == DateTime.Parse(strDate)) //if given date is equal to exactly 6 months past from today (change == to > if date has to be less 6 months)
{
lblResult.Text = "true"; //this doesn't work with the entered date above.
}
else //otherwise give me the date which will be 6 months from a given date.
{
DateTime dt2 = Convert.ToDateTime(strDate);
lblResult.Text = "6 Months from given date is: " + dt2.AddMonths(6); //this works fine
}
If 6 months or greater than 6 months is what I would like for one
condition
If less than 6 months is another condition.
Your first problem is that you're using DateTime.Now instead of DateTime.Today - so subtracting 6 months will give you another DateTime with a particular time of day, which is very unlikely to be exactly the date/time you've parsed. For the rest of this post, I'm assuming that the value you parse is really a date, so you end up with a DateTime with a time-of-day of midnight. (Of course, in my very biased view, it would be better to use a library which supports "date" as a first class concept...)
The next problem is that you are assuming that subtracting 6 months from today and comparing it with a fixed date is equivalent to adding 6 months to the fixed date and comparing it with today. They're not the same operation - calendar arithmetic just doesn't work like that. You should work out which way you want it to work, and be consistent. For example:
DateTime start = DateTime.Parse(tbDate.Text);
DateTime end = start.AddMonths(6);
DateTime today = DateTime.Today;
if (end >= today)
{
// Today is 6 months or more from the start date
}
else
{
// ...
}
Or alternatively - and not equivalently:
DateTime target = DateTime.Parse(tbDate.Text);
DateTime today = DateTime.Today;
DateTime sixMonthsAgo = today.AddMonths(-6);
if (sixMonthsAgo >= target)
{
// Six months ago today was the target date or later
}
else
{
// ...
}
Note that you should only evaluate DateTime.Today (or DateTime.Now etc) once per set of calculations - otherwise you could find it changes between evaluations.
Try with this
DateTime s = Convert.ToDateTime(tbDate.Text);
s = s.Date;
if (DateTime.Today.AddMonths(-6) == s) //if given date is equal to exactly 6 months past from today (change == to > if date has to be less 6 months)
{
lblResult.Text = "true"; //this doesn't work with the entered date above.
}
replace == with >= or <= according to your needs

Calculate End Date Given Start Date & duration (in days)

I am developing a c#.net solution with a Store Procedure in oracle that calculates End Date based on provided Start date and Duration with weekends.
i.e. Start Date: 01/3/2013 Forward days: 10
Start Date = (05/5/2011) - 10 days (includes weekends)
Start Date = 06/02/2013
thank you,
Use of AddDays method of DateTime
DateTime startDate = new DateTime(2013,3,1);
var endDate = startDate.AddDays(10);
You can do this a bunch of ways in Oracle. I'd suggest the INTERVAL way because it's standard-ish:
SELECT yourdate + INTERVAL '10' DAY, ...
The single quote around the 10 is required.
The "old" way is to just add 10 to the date; Oracle treats this as days:
SELECT yourdate + 10, ...
//DateTime start_date = ...
DateTime end_date = start_date.AddDays(10);

Iterate over each Day between StartDate and EndDate [duplicate]

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

Categories