Run through loop for week and don't select weekends - c#

So the user can select 2 different dates, a start date and an end date from 2 calendars, when they click add the dates between&including the dates selected will be added to the Database, each date as a separate record.
This works fine however I don't want weekends to be added to the Database.
I've updated the UI of datepicker http://www.kelvinluck.com/assets/jquery/datePicker/v2/demo/datePickerCustomCellRender.html
but if a user selects fri-mon for example fri,sat,sun and mon will be added to the Database.
I've tried to only run the code if datyofweek is not saturday or sunday
public ActionResult listHolidays(Holiday holiday, int? PersonId, string HolidayDate, string endDate)
{
DateTime startDates = Convert.ToDateTime(HolidayDate),
endDates = Convert.ToDateTime(endDate);
while (startDates <= endDates)
{
if (startDates.DayOfWeek != DayOfWeek.Saturday || startDates.DayOfWeek != DayOfWeek.Sunday)
{
Holiday holiday1 = new Holiday();
holiday1.PersonId = PersonId.Value;
holiday1.HolidayDate = startDates;
db.Holidays.AddObject(holiday1);
db.SaveChanges();
startDates = startDates.AddDays(1);
}
}
return RedirectToAction("Index");
}
any help?
Thanks

You need to use AND instead of OR:
if (startDates.DayOfWeek != DayOfWeek.Saturday && startDates.DayOfWeek != DayOfWeek.Sunday)
Your current condition will always be true. If startDates is DayOfWeek.Saturday, it is not DayOfWeek.Sunday and vice versa.
After that, you need to put the startDates = startDates.AddDays(1); outside the if.
Otherwise, you would have an endless loop, because as soon as startDates is DayOfWeek.Saturday, it will no longer be incremented.

Change
if (startDates.DayOfWeek != DayOfWeek.Saturday || startDates.DayOfWeek != DayOfWeek.Sunday)
To
if (startDates.DayOfWeek != DayOfWeek.Saturday && startDates.DayOfWeek != DayOfWeek.Sunday)
You'll then need to move this line
startDates = startDates.AddDays(1);
To outside of the if block (otherwise the startDates variable will never change if the date is a weekend date).

If statement is wrong and day increment in wrong place.
while (startDates <= endDates)
{
if (startDates.DayOfWeek != DayOfWeek.Saturday **&&** startDates.DayOfWeek != DayOfWeek.Sunday)
{
Holiday holiday1 = new Holiday();
holiday1.PersonId = PersonId.Value;
holiday1.HolidayDate = startDates;
db.Holidays.AddObject(holiday1);
db.SaveChanges();
}
**startDates = startDates.AddDays(1);**
}

Just as an alternative solution for you for calculating how many week days you have selected
List<DateTime> allDates = New List<DateTime>();
for (DateTime date = startingDate; date <= endingDate; date = date.AddDays(1))
allDates.Add(date);
var days = allDates.Where(x => x.IsWeekday()).Count();
Using the following DateTime extension.
public static class DateTimeExtensions
{
public static bool IsWeekday(this DateTime dt)
{
return dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday;
}
}
As per my comment, you can extend this to an IsWorkday if it is for a holiday system and encorporate some logic for checking if the day is a bank holiday.

Related

How can I get total number of days in selected month with/without the weekends in WPF?

I am hoping to find a way to get the total number of days in a month with and without the weekends using LINQ in my ViewModel. For example, September would count for 20 days without weekends and 30 days with the weekends.
I also have a datepicker binding to MDate and I have no idea were to start.
Can someone please suggest an easy method? I am just an amateur.
private DateTime _mDate = DateTime.Now;
public DateTime MDate
{
get { return _mDate; }
set
{
if (value == _mDate)
{
return;
}
else
{
_mDate = value;
OnPropertyChanged("MDate");
SetDaysInMonth();
}
}
}
private void SetDaysInMonth()
{
???
}
Thank you.
DateTime.DayOfWeek method could come handy, and this answer by Ani shows how to get all days in a given month.
borrowing from the answer mentioned above:
public static List<DateTime> GetDates(int year, int month)
{
var dates = new List<DateTime>();
// Loop from the first day of the month until we hit the next month, moving forward a day at a time
for (var date = new DateTime(year, month, 1); date.Month == month; date = date.AddDays(1))
{
if(date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday)
{
dates.Add(date);
}
}
return dates;
}
int count = Enumerable.Range(1, DateTime.DaysInMonth(2017, 10)) // year and month
.Select(day => new DateTime(2017, 10, day)) // year and month
.Where(d => d.DayOfWeek != DayOfWeek.Sunday && d.DayOfWeek != DayOfWeek.Saturday) // check each day for weekend
.ToList().Count;
Hope you need only the no of working days in a month
Find the number of days in month then enumerate and excluded Saturday and Sunday.
private static void SetDaysInMonth(DateTime mDate)
{
int numberOfBusinessDays = Enumerable.Range(1, DateTime.DaysInMonth(mDate.Year, mDate.Month))
.Select(day => new DateTime(2017, mDate.Month, day))
.Count(d => d.DayOfWeek != DayOfWeek.Sunday && d.DayOfWeek != DayOfWeek.Saturday);
}

C# Check given date and time

Good day everyone. I'm new to C# but I can't seem to understand how DateTime work.
All I wanted to do is to check If a (givenday) = today and time is 7pm I wanted to return true. Is this the right way to do it?
Take note ActionDate is a field which is inputed by the user.
DateTime dateA = Convert.ToDateTime(ActionDate);
int a = dateA.Year;
int b = dateA.Month;
int c = dateA.Day;
int d = timeA.Hour;
int e = timeA.Minute;
var newDate = new DateTime(a, b, c, d, e, 0);
DateTime end = Convert.ToDateTime(newDate);
DateTime start = Convert.ToDateTime(A);
TimeSpan span = end.Subtract(start);
Decimal minutes = Convert.ToDecimal(span.TotalMinutes);
if
{
return true;
} else
{
return false;
}
Thank you in advance.
The way to check if a give date is today and is at 7pm is to use DateTime.Now.
Note that 19 is 7pm and 7 is 7am, the Hour property uses 24 hour format.
bool IsCurrentDayAnd7(DateTime dt) => dt.Date == DateTime.Now.Date && dt.Hour == 19;
As #TimSchmelter commented you could use DateTime.Today:
bool IsCurrentDayAnd7(DateTime dt) => dt.Date == DateTime.Today && dt.Hour == 19;
You can use Date property to compare date with current date.
if (newDate.Date == DateTime.Now.Date && newDate.Hour == 19)
{
return true;
}
You have made your code a bit too complicated. First, convert that user input to date, and compate it with current date and time.
DateTime dateA = Convert.ToDateTime(ActionDate);
if (dateA.Date == DateTime.Today && dateA.Hour == 19)
{
//it is current date and hour is 7pm
}
Alternatively, check if user's imput is ok, like this:
DateTime dateA;
if (!DateTime.TryParse(ActionDate, out dateA))
{
//alert user that he's entered wrong date
}
EDIT:
as Tim Schmelter noted, code's a bit more readable using DateTime.Today instead of DateTime.Now.Date

Check if this Monday is last Monday in a month

I use this code from another question:
private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){
int d = date.Day;
return date.DayOfWeek == dow && (d-1)/7 == (n-1);
}
It works fine. But it not checks a last day ( for me it's when n = 5). How to modify it?
Thanks.
The method below checks the given date is the last date of week of month.
private bool IsLastOfMonth(DateTime date)
{
var oneWeekAfter = date.AddDays(7);
return oneWeekAfter.Month != date.Month;
}
So there is new method, it just checks mondays
private bool IsLastMonday(DateTime date)
{
if (date.DayOfWeek != DayOfWeek.Monday)
return false; // it is not monday
// the next monday is...
var oneWeekAfter = date.AddDays(7);
// and is it in same month?, if it is, that means its not last monday
return oneWeekAfter.Month != date.Month;
}
Lets take March 30,
d = 30,
(date.DayOfWeek == DayOfWeek.Friday) == true,
(30-1)=29, 29/7 = 4
4 == (5-1)
So it works
To only check if DayOfWeek is last in mothth you can use
return date.AddDays(7).Month != date.Month;

How to add a number of days to a Date while skipping weekends and other holidays

Given a Date. How can I add a number of days to it while skipping weekends and other holidays coming between the range?
List <DateTime> holidays = new List<DateTime>()
{
new DateTime(2012, 01, 03),
new DateTime(2012, 01, 26)
};
dateTimeReview.Value = CalculateFutureDate(dateTimeStart.Value, 7,holidays);
static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
for (var i = 0; i < numberofWorkDays; i++ )
{
if (futureDate.DayOfWeek == DayOfWeek.Saturday
|| futureDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(futureDate)))
{
futureDate = futureDate.AddDays(1); // Increase FutureDate by one because of condition
futureDate = futureDate.AddDays(1); // Add a working day
}
}
return futureDate;
}
To skip holidays you will first need to create your own list of holidays. Holidays are different in every country and also subject to other factors.
Then you should add days one by one in a loop with a check if the added day is not a weekend day and does not occur in the list of holidays, until the given number of days has been added.
Unfortunately, there is no easier way to do this.
I tried the code above and didn't work. The returned date will somehow includes the holidays and weekends as well. I also want to check that the returned date to be on Workdays only.
So, below are my modified codes.
Basically it will calculate the number of workdays to be added and if the end date falls on holidays/weekends, shift the date to the next day.
Do take note that this is on an assumption that the start date is not on weekends/holidays.
static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays,
ICollection<DateTime> holidays)
{
var futureDate = fromDate;
for (var i = 0; i < numberofWorkDays; i++ )
{
if (futureDate.DayOfWeek == DayOfWeek.Saturday
|| futureDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(futureDate)))
{
futureDate = futureDate.AddDays(1);
numberofWorkDays++;
}
else
{
futureDate = futureDate.AddDays(1);
}
}
while(futureDate.DayOfWeek == DayOfWeek.Saturday
|| futureDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(futureDate)))
{
futureDate = futureDate.AddDays(1);
}
return futureDate;
}
I've built something similar to check for Office Hours:
public static DateTime AddBusinessHours(DateTime date, long hours)
{
int i = 0;
DateTime tmpDate = date;
do
{
tmpDate = tmpDate.AddHours(1);
if (!IsWeekend(tmpDate) && !IsHoliday(tmpDate) && IsOfficeHours(tmpDate))
i++;
}
while (i < hours);
return tmpDate;
}
public static bool IsWeekend(DateTime date)
{
return (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday);
}
public static bool IsHoliday(DateTime date)
{
//All dates in the holiday calendar are without hours and minutes.
//With the normal date object, the Contains does not work.
DateTime tmp = new DateTime(date.Year, date.Month, date.Day);
HolidayCalendar calendar = HolidayCalendar.Instance;
return (calendar.Dates.Contains(tmp));
}
public static bool IsOfficeHours(DateTime date)
{
return (date.Hour >= 8 && date.Hour < 20); //Office Hours are between 8AM and 8PM
}
But as mentioned above, you need to run your own holiday calendar.
public static DateTime AddBusinessDays(DateTime pActualDate, int pNumberofWorkDays)
{
ICollection<DateTime> holidays = GetAllHolidays();
int i = default(int);
while (i < pNumberofWorkDays)
{
pActualDate = pActualDate.AddDays(1);
if (pActualDate.DayOfWeek == DayOfWeek.Saturday || pActualDate.DayOfWeek == DayOfWeek.Sunday
|| (holidays != null && holidays.Contains(pActualDate))) { }
else
{ i++; }
}
return pActualDate;
}
private static ICollection<DateTime> GetAllHolidays()
{
ICollection<DateTime> holidays = GetPublicHolidays().Select(s => s.Holidays).ToList();
HashSet<DateTime> finalHolidays = new HashSet<DateTime>();
//if sunday holiday then the following monday will be holiday
bool isMonday = GetCalendar().Any(s => s.Type == "KR" && s.IsMonday);
foreach (var hol in holidays)
{
if (hol.DayOfWeek == DayOfWeek.Sunday && isMonday)
{
//adding monday following day holiday to the list
finalHolidays.Add(hol.AddDays(1));
}
}
//exclude weekends from the holiday list
var excludeWeekends = holidays.Where(s => s.DayOfWeek == DayOfWeek.Sunday || s.DayOfWeek == DayOfWeek.Saturday);
//adding monday to the existing holiday collection
finalHolidays.UnionWith(holidays.Except(excludeWeekends));
return finalHolidays;
}

How do I get the missing dates from a range

I'm doing this test-app and what it has to do is go through a long list of dates from a text file and get the missing ones (excluding weekend days) and write the results to an output file. If the missing date is a single day the output should be ccyy/mm/dd , if it's more than one day it should be ccyy/mm/dd - ccyy/mm/dd , so this is what I've come up with and it doesn't seem to work as it should, I think I'm not doing the test right.
List<string> missigDateStrings = new List<string>();
for (int i = 0; i < dateList.Count; i++ )
{
DateTime firstDate = dateList[i];
DateTime secondDate = dateList[i + 1];
if (firstDate.DayOfWeek != DayOfWeek.Saturday &&
firstDate.DayOfWeek != DayOfWeek.Sunday)
{
if (secondDate.DayOfWeek != DayOfWeek.Saturday &&
secondDate.DayOfWeek != DayOfWeek.Sunday)
{
if (firstDate.AddDays(1) != secondDate)
{
string sFirstMissingDate = firstDate.ToShortDateString();
DateTime testDate = firstDate;
while (testDate != secondDate)
{
testDate.AddDays(1);
if (testDate == secondDate)
{
string sLastMissingDate = firstDate.AddDays(1).ToShortDateString();
string range = String.Format("{0}-{1}", sFirstMissingDate, sLastMissingDate);
missigDateStrings.Add(range);
}
}
}
}
}
}
}
Any help would be appreciated.
P.S. all the dates have been converted to DateTime
EXCELLENT ! THANKS ALL
If the gap is longer than 7 days you get weekend days also. I assume that is your problem. So you should add another check for Sat/Sun in
while (testDate != secondDate)
and break the loop on Friday, skip weekend and start loop on Monday again.
EDIT:
Below is always false in your case probably. That's why you don't get any output.
if (firstDate == secondDate)
Change
testDate.AddDays(1);
to
testDate = testDate.AddDays(1);
DateTime is an immutable value-type, AddDays() returns a new instance but does not (cannot) change the original value.
And just for fun, to answer the title-question,
var missing = Enumerable.Range(0, 10)
.Select(i => baseDate.AddDays(i))
.Except(datesFromFile);

Categories

Resources