I am facing a problem, logic written in my program is below
while (lastDate.Month < DateTime.Today.Month - 1)//
{
lastDate= lastDate.AddMonths(1);
list.Add(lastDate);
}
This code is failing when lastDate month is Dec and i am executing this code in Jan or Feb of new year because 12 would never be greater then 1 0r 2.
I need to write a logic where my loop could traverse through Nov, Dec, Jan , Feb and so on.
I have written below code which is working however i am not getting clue to exit, loop should exit when difference between lastDate and todays date is 2 months.
if (lastDate.Month > DateTime.Today.Month && lastDate.Year < DateTime.Today.Year)
{
while (lastDate.Year <= DateTime.Today.Year)
{
lastDate= lastDate.AddMonths(1);
list.Add(lastDate);
}
}
Please help me in this
You will always add 12 months to the list, so you can use a for-loop:
for(var i = 0; i < 12; i++)
{
lastDate = lastDate.AddMonths(1);
list.Add(lastDate);
}
As you know how many times you have to add one month, there is no need to have a condition depending on the month and year, but only a counter to execute this code exactly 12 times.
This may helps:
DateTime lastDate = DateTime.ParseExact("01/12/12", "dd/MM/yy", System.Globalization.CultureInfo.InvariantCulture);
List<DateTime> result = new List<DateTime>();
//iterate until the difference is two months
while (new DateTime((DateTime.Today - lastDate).Ticks).Month >= 2)
{
result.Add(lastDate);
lastDate = lastDate.AddMonths(1);
}
//result: 12/1/2012
// 1/1/2013
// 2/1/2013
// 3/1/2013
Hopefully this will solve your problem:
DateTime lastDate = new DateTime(2012, 1, 1);
List<DateTime> list = new List<DateTime>();
while (lastDate < (DateTime.Today.AddMonths(-3))) //difference between today and lastDate should be 2 month
{
lastDate = lastDate.AddMonths(1);
list.Add(lastDate);
}
This will add 12 DateTimes from lastDate to your list :)
list.AddRange(Enumerable.Range(0,12).Select(v => lastDate = lastDate.AddMonths(1)));
Related
How to calculate actual working days of my when user checkin in hotel? I want to count working days only except Saturday and Sunday. Please check below function its count working days but in parameter I entered startdate and enddate.
I want send only startdate its automatically count 15 working days and return me enddate.
//Days count
public static double GetBusinessDays(DateTime startD, DateTime endD)
{
double calcBusinessDays =
1 + ((endD - startD).TotalDays * 5 -
(startD.DayOfWeek - endD.DayOfWeek) * 2) / 7;
if (endD.DayOfWeek == DayOfWeek.Saturday) calcBusinessDays--;
if (startD.DayOfWeek == DayOfWeek.Sunday) calcBusinessDays--;
return calcBusinessDays;
}
I want like this:
public static Datetime GetBusinessDays(DateTime startDate)
{
Datetime After15WorkingDaysDate;
return After15WorkingDaysDate;
}
Here are two methods.
The idea is to generate each date in the range, decide whether it is a Business Day, and only then add it to the result list.
GetBusinessDaysInRange returns a list of the dates of the Business Days between the given start and end date. End date is exclusive, i.e. if the end date is a Business Day, it will not be part of the result.
// Returns a list of the dates of the Business Days between the given start and end date
public static IEnumerable<DateTime> GetBusinessDaysInRange(DateTime startDate, DateTime endDate, DayOfWeek[] closedOn) {
if (endDate < startDate) {
throw new ArgumentException("endDate must be before startDate");
}
var businessDays = new List<DateTime>();
var date = startDate;
while (date < endDate) {
if (!closedOn.Contains(date.DayOfWeek)) {
businessDays.Add(date);
}
date = date.AddDays(1);
}
return businessDays;
}
GetFixedNumberOfBusinessDays returns a list of the dates of the Business Days from the given start with the given number of days (the method you asked for).
// Returns a list of the dates of the Business Days from the given start with the given number of days
public static IEnumerable<DateTime> GetFixedNumberOfBusinessDays(DateTime startDate, int numberOfBusinessDays, DayOfWeek[] closedOn) {
if (numberOfBusinessDays < 0) {
throw new ArgumentException("numberOfBusinessDays must be zero or positive.");
}
var businessDays = new List<DateTime>();
var date = startDate;
while (businessDays.Count() < numberOfBusinessDays) {
if (!closedOn.Contains(date.DayOfWeek)) {
businessDays.Add(date);
}
date = date.AddDays(1);
}
return businessDays;
}
The parameter DayOfWeek[] closedOn was introduced because you do not want to hardcode the days of the week that are not Business Days.
The return type was changed to IEnumerable<DateTime> so this method is more universal. If you only want the number of days and are not interested in the actual dates, just run a .Count() on the result. If you want the end date, call .Last().
.Net Fiddle with usage examples:
var closedOn = new DayOfWeek[] { DayOfWeek.Saturday, DayOfWeek.Sunday };
var start = new DateTime(2018, 07, 23);
var numberOfDays = 10;
var businessDays = GetFixedNumberOfBusinessDays(end, numberOfDays, closedOn);
int actualNumberOfBusinessDays = businessDays.Count(); // 10
DateTime endDate = businessDays.Last(); // Friday, August 3, 2018
It should be generic method. You can add different work day in another place.
public static DateTime AddWorkdays(this DateTime originalDate, int workDays)
{
DateTime tmpDate = originalDate;
while (workDays > 0)
{
tmpDate = tmpDate.AddDays(1);
if (tmpDate.DayOfWeek == DayOfWeek.Saturday ||
tmpDate.DayOfWeek == DayOfWeek.Sunday )
workDays--;
}
return tmpDate;
}
DateTime endDate = startDate.AddWorkdays(15);
private void btnDateTime_Click(object sender, EventArgs e)
{
DateTime trdCurrentMonth = DateTime.Today.AddDays(-(DateTime.Today.Day - 3));
if (trdCurrentMonth !=
DateTime.Today.AddDays(-(DateTime.Today.Day)) &&
trdCurrentMonth != DateTime.Today.AddDays(-(DateTime.Today.Day - 1)))
{
MessageBox.Show(trdCurrentMonth.ToString());
}
}
How do I get the 3rd working day of current month, excluding Saturday and Sunday?
Get weekdays in a first 10 calendar dates and Skip 2 to get the third working day in a month.
DateTime dt = new DateTime(2016,6,1); // 1st Day of the Month.
var thirdWorkingDay = Enumerable.Range(0,10)
.Select(x=> dt.AddDays(x))
.Where(x=> x.DayOfWeek != DayOfWeek.Sunday && x.DayOfWeek != DayOfWeek.Saturday)
.Skip(2)
.FirstOrDefault() ;
Check this Demo
I prefer you to keep a List of DayOfWeek to represent the holidays(here Saturday and Sunday). we can easily check whether the day is Saturday or Sunday. Then the first line will find the First day of the current month, Iterate through the days until we find the third working day. Now consider the code:
List<DayOfWeek> holydays = new List<DayOfWeek>() { DayOfWeek.Sunday, DayOfWeek.Saturday };
DateTime firstDayOfMonth = new DateTime(DateTime.Now.Date.Year, DateTime.Now.Date.Month, 1); // first day of month
int thirdDay = 1;
int addDay = 0;
while (thirdDay <= 3)
{
if (!holydays.Contains(firstDayOfMonth.AddDays(addDay++).DayOfWeek))
{
thirdDay++;
}
}
DateTime thirdWorkingDay = firstDayOfMonth.AddDays(--addDay);
This will give
03/06/2016 for june - 2016
05/07/2016 for july- 2016
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Can anyone please help me. What I need to C# logic for the display in advance and sequence order six date list on Monday. In advance date list should change after 12.00PM. For example on Monday 28 March, date will display same day(28 March) till 12.00pm. After 12.01 pm, first date start from 11 April 2016. Also same sequence(attached screen). It is never display 4th April, 18th April etc.. (sequence order )..
This is my effort C# code, it's only display single date list.
public static void Main(string[] args)
{
DateTime time = new DateTime(2016, 3, 25);
var breaks = DateTime.Today.AddHours(12D);
if (breaks>=DateTime.Now)
{
}
else if (time<DateTime.Now)
{
}
DateTime anotherTime = DateTime.Now;
var allTimes = new HashSet<DateTime>();
for (int i = 0; i < 6; i++)
{
anotherTime = time.AddDays(14);
time = anotherTime;
Console.WriteLine(anotherTime.ToLongDateString());
allTimes.Add(time);
}
}
}
This is my final out put in advance six date list
Try this
static void Main(string[] args)
{
DateTime today = DateTime.Now;
if ((today.DayOfWeek == DayOfWeek.Monday) && (today > new DateTime(today.Year, today.Month, today.Day, 12, 0, 0)))
{
today.AddDays(1);
}
int offsetToMonday = 7 - (((int)today.DayOfWeek - 1) % 7);
DateTime nextMonday = today.AddDays(offsetToMonday);
DateTime startDate = (nextMonday.DayOfYear / 7 % 2) == 0 ? nextMonday : nextMonday.AddDays(7);
DateTime endDate = startDate.AddDays(83);
List<DateTime> dates = new List<DateTime>();
for (DateTime date = startDate; date <= endDate; date = date.AddDays(1))
{
dates.Add(date);
}
var groupedDays = dates.AsEnumerable()
.GroupBy(x => x.Subtract(startDate).Days % 14)
.OrderBy(x => x.Key)
.Where(x => x.Key == 0);
foreach (var group in groupedDays)
{
foreach (DateTime day in group)
{
Console.WriteLine(day.ToString("dddd, dd MMMM yyyy"));
}
Console.WriteLine();
}
Console.ReadLine();
}
I am not sure if I understand what you exactly want. But I have a similar function in my repository.
public static DateTime GetNextDayOfWeek(DateTime _date, DayOfWeek _dayOfWeek)
{
DateTime Result;
int diff = _date.DayOfWeek - _dayOfWeek;
if (diff == 0 && _date.Hour * 100 + _date.Minute <= 1200)
return _date;
if (diff < 0)
{
diff += 7;
}
Result = _date.AddDays(-1 * diff).Date;
if (Result <= _date)
Result = Result.AddDays(7);
return Result;
}
I added this part for your needs
if (diff == 0 && _date.Hour * 100 + _date.Minute <= 1200) return _date;
This functions takes a date and a desired day of week and returns the closest next date when the desired day of week will be present.
Since I understand you want 6 packs of these, you can put it in a loop like this:
DateTime next;
next=DateTime.Now;
foreach(DayOfWeek dow in Enum.GetValues(typeof(DayOfWeek)))
{
for(var n=0;n<6;n++)
{
next=GetNextDayOfWeek(next, dow);
//do something with your date
}
}
You could add another parameter for how many days you wand advance. Currently it if fixed to 7. In your case you would need 14.
I have a flag enum for representing every day of the week. (Sunday, Monday etc.). Lets call this the WeekDay enum. Now given a interval find all dates for the days in the WeekDaysvariable.
For eg: WeekDays daysAll = WeekDays.Sunday | WeekDays.Friday;
Now find the dates for all the Sunday and Friday dates in a given interval.
So i thought of the following logic: Find the first Sunday, Friday, as in the above example.
Add these dates to a temporary dictionary. Now iterate that dictionary and keep on adding 7 days till the end interval is reached.
int dayCounter = 0;
WeekDays daysAll = WeekDays.Sunday | WeekDays.Friday;
Dictionary<DayOfWeek, DateTime> tempDict = new Dictionary<DayOfWeek, DateTime>();
for (var day = intervalStartDate.Date; (dayCounter < 7 && day.Date <= intervalEndDate.Date); day = day.AddDays(1))
{
WeekDays check = GetWeekDayFromDayOfWeek(day.DayOfWeek); //This Function converts from the DateTime DayOfweek enum to the WeekDays enum.
if ((check & daysAll) == check)
{
tempDict.Add(day.DayOfWeek, day);
}
dayCounter++;
}
Now keep adding 7 days for every date in the dict till end interval is reached:
if (tempDict.Keys.Count > 0)
{
List<DateTime> allDates = new List<DateTime>();
var keys = new List<DayOfWeek>(tempDict.Keys);
bool opComplete = false;
while (!opComplete)
{
foreach (DayOfWeek dayOfWeek in keys)
{
if (tempDict[dayOfWeek] > intervalEndDate.Date) { opComplete = true; break; }
allDates.Add(tempDict[dayOfWeek]);
tempDict[dayOfWeek] = tempDict[dayOfWeek].AddDays(7);
}
}
}
So my question is: Can this algorithm be improved? Can LinQ be used to make the intent more clearer in the code itself?
Performance optimization and clearer code are not the same in most cases.
The clearer LINQ version would be like this:
public IEnumerable<DateTime> IntervalDays(DateTime start, DateTime end)
{
if (start > end)
yield break;
var d = start.Date;
while (d <= end.Date)
{
yield return d;
d = d.AddDays(1);
}
}
and the you write the query as in this example:
IntervalDays(startDate, endDate)
.Where(d=>d.DayOfWeek==DayOfWeek.Friday || d.DayOfWeek==DayOfWeek.Sunday);
The good thing here is you can easily query other days of the week etc.
For the optimized code, if you mean performance, you'd better not iterate one by one but find the first Friday or Sunday and move along by adding 2 or 5 days depending on the date
Few ways, as a general method, pass in the day of week you want with start and end dates.
private List<DateTime> GetDates(DateTime startDate, DateTime endDate, DayOfWeek dayOfWeek)
{
var returnDates = new List<DateTime>();
for (DateTime dateCounter = startDate; dateCounter < endDate; dateCounter = dateCounter.AddDays(1))
{
if (dateCounter.DayOfWeek == dayOfWeek)
{
returnDates.Add(dateCounter);
}
}
return returnDates;
}
Or return full date range and query that using linq.
private List<DateTime> GetDates(DateTime startDate, DateTime endDate)
{
var returnDates = new List<DateTime>();
for (DateTime dateCounter = startDate; dateCounter < endDate; dateCounter = dateCounter.AddDays(1))
{
returnDates.Add(dateCounter);
}
return returnDates;
}
query:
var myDates = GetDates(DateTime.Now, DateTime.Now.AddDays(30)).Where(i => i.DayOfWeek == DayOfWeek.Friday);
I have a what seems like simple date issue and I just can't wrap my head around trying to get it efficiently... I basically need to get the previous months date for a specific day.
For example: If today is the 3rd Thursday of the month, I want to get the 3rd Thursday's date of last month. Its important that its based of the number of the day...ie: First Monday, 4th Friday, 2nd Wednesday, etc.
What's the best way to get this done?
BTW...If there is not an equivalent previous months day that is fine. I can handle that. Also, currently I am counting the number or days ("Mondays", "Tuesdays", etc) manually to figure this out. I was just hoping there is a more elegant way to do it.
Here's what I would do:
static DateTime? GetLastMonthSameNthDayOfWeek(DateTime date)
{
int nth = (date.Day-1) / 7; // returns 0 if 1st, 1 if 2nd...
var prevMonthDay = date.AddMonths(-1);
// find the first date of month having the same day of week
var d = new DateTime(prevMonthDay.Year, prevMonthDay.Month, 1);
while(d.Day <= 7)
{
if (d.DayOfWeek == date.DayOfWeek)
break;
d = d.AddDays(1);
}
// go to nth day of week
d = d.AddDays(7 * nth);
// if we have passed the current month, there's no nth day of week
if (d.Month != prevMonthDay.Month)
return null;
return d;
}
Usage example:
// 3rd wednesday of August 2012
var a = new DateTime(2012, 8, 15);
var aPrev = GetLastMonthSameNthDayOfWeek(a);
// aPrev = July 18th 2012 (i.e. the 3rd wednesday of July 2012)
// 5th wednesday of August 2012
var b = new DateTime(2012, 8, 15);
var bPrev = GetLastMonthSameNthDayOfWeek(b);
// bPrev = null, because there's no 5th wednesday of July 2012
N.B. :
getting the ordinal position of the day of week inside a month is really easy:
int nth = ((date.Day-1) / 7) + 1; // 1 -> 1st, 2 -> 2nd, 3 -> 3rd ...
As I couldn't find a built-in way, I've written this simple extension method for DateTime, check it out:
public static class DateTimeExtension
{
public static DateTime GetPositionalDate(this DateTime BaseDate, DayOfWeek WeekDay, int position)
{
if (position < 1)
{
throw new Exception("Invalid position");
}
else
{
DateTime ReturnDate = new DateTime(BaseDate.Year, BaseDate.Month, BaseDate.Day);
int PositionControl = 1;
bool FoundDate = false;
while(ReturnDate.DayOfWeek != WeekDay)
{
ReturnDate = ReturnDate.AddDays(1);
}
while (!FoundDate && PositionControl <= position)
{
PositionControl++;
if (PositionControl == position)
{
FoundDate = true;
}
else
{
ReturnDate = ReturnDate.AddDays(7);
}
}
if (FoundDate)
{
return ReturnDate;
}
else
{
throw new Exception("Date not found");
}
}
}
}
Usage:
DateTime lastMonth = DateTime.Now.GetPositionalDate(DayOfWeek.Sunday, 2);
Regards
There is no, by default, a way that .Net understand this specific logic for dates. So using the following, you can get what you're looking for:
var now = DateTime.Now.Date;
Use DateTime.AddMonth(-1) to get last month.
Use DateTime.AddDays(now.Days * -1 + 1) to get the first of the month.
Use DateTime.DayOfWeek to determine the day and subtract or add days as necessary
Ok, what you can do is determine the day of the week of the first day of the month last month, take the difference between the day of the week you want and that day of the week, then add 7 * the weeks you want (less one week)...
// Let's get the 3rd Friday of last month:
// get starting date
DateTime date = new DateTime();
// get first day of last month
DateTime firstOfLastMonth = date.AddMonths(-1).AddDays(-1 * (date.Day + 1));
// subtract out the day of the week (get the previous Sunday, even if it is last month)
DateTime justBeforeMonth = firstOfLastMonth.AddDays((int)firstOfLastMonth.DayOfWeek);
// Add in the DayOfWeek number we are looking for
DateTime firstFridayOfMonth = justBeforeMonth.AddDays(DayOfWeek.Friday);
// if we are still in last month, add a week to get into this month
if (firstFridayOfMonth.Month != date.AddMonth(-1).Month) { firstFridayOfMonth.AddDays(7); }
// add in 2 weeks to get the third week of the month
DateTime thirdFridayOfMonth = firstFridayOfMonth.AddDays(14);
Here's the solution I came up with. If the day doesn't exist (e.g. 8th Saturday), GetDate() will return null:
{
DateTime lastMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(-1);
DateTime? date = GetDate(lastMonth.Month, lastMonth.Year, DayOfWeek.Thursday, 2);
}
private static DateTime? GetDate(int month, int year, DayOfWeek dayOfWeek, int which)
{
DateTime firstOfMonth = new DateTime(year, month, 1);
DateTime date;
for (date = firstOfMonth; date.DayOfWeek != dayOfWeek; date = date.AddDays(1))
;
date = date.AddDays(7 * (which - 1));
return date.Month == month && date.Year == year ? (DateTime?)date : null;
}