Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if selected date is within three days of a predefined holiday

This is for a program at work. I don't have access to the code right now, but I really want to figure this out, so I wrote a quick program at home that is a mimic of my work project.

I need to know if that date is within 3 working days of a "holiday". If it is, then the selected date must be incremented by one to skip over the holiday. Example:

If there is a holiday on "01/19/2018" and a user selects "01/16/2018", then the program must skip the 19th and then set the closing date as "01/20/2018". Now if I do pure if/then statements, I can get it to work as expected, but the problem then becomes: "what if both 01/19/2018 AND 01/20/2018 are holidays?" This is where I'm stuck.

At work, I'm using a SQL table that already has a column for dates in "MM/dd/yyyy" format (so those dates are my list source that I am checking against.) The user opens a calendar and selects a date. I'm actually parsing an XML file that is created by another method that actually touches the database then using XElement for an iteration that puts all those dates in a string list.)

This is the code in my pseudo work program:

        private void button1_Click(object sender, EventArgs e)
        {
        DateTime dt = DateTime.Now;
        txtLog.Text = dt.ToString("MM/dd/yy") + Environment.NewLine;
        List<string> allexemptdays = new List<string>();
        string[] days = { "11/19/2018", "11/20/2018" };

        foreach (string a in days)
        {
            allexemptdays.Add(a);
        }

        foreach (string a in allexemptdays)
        {
            ToLog(a);
        }

        DateTime eq = DateTime.Parse(txtDate.Text);
        string thefrustrationisreal = eq.ToString("MM/dd/yy");

        if (Math.Abs(DateTime.Now.Subtract(eq).Days) <= 3)
        {
            MessageBox.Show("Date exemption found.");
        }

    }

    private void ToLog(string a)
    {
        txtLog.Text += ("Array value to list: " + a + Environment.NewLine);
    }

    private void monthCalendar1_DateSelected(object sender, DateRangeEventArgs e)
    {
        txtDate.Text = monthCalendar1.SelectionStart.ToString("MM/dd/yy");
    }

Obviously I understand "DateTime.Now" doesn't reflect what I require, but I was just playing more with the DateTime class.

So in short: I'm creating an array with the dates (similar to my real program) Iterating through them, adding them to a list. Now I need to check if the selected date falls within 3 days of the predefined date from a returned value from my sql table.

If a date is found, move the closing date up a day; however, if holidays in a row are found, then skip those two dates altogether. I can do this on a one by one basis (using if/then) but this doesn't work well if two holidays are back to back of each other.

As a side note, I want to be able to tell if the selected date is within 3 days AND moves over to another month, but I think I can handle that with DateTime, checking the days in a month and incrementing when needed (or I'm sure DateTime could do that for me actually.) I'm not too worried about this concern though at this point.


I did accept Mike's answer as it does work as intended, but! I now have a different issue

Now the "days.count()" holds a persistent number after the user selects a date beyond the holidays. Example: Selecting January 21 2017 returns "Janurary 26 2017" as the closing date because it's still counting the 20th and 21st as holidays affected by the range, when it should just set the closing date now at "Janurary 24th 2017"

I've played around with the code provided; I can't find a good way to fix it. I was thinking something along the lines of:

If(selectedDate.AddDays(3) >= holidaydate) then do a check for another day through the datetime list, but I'd still be making that way more complicated than it should be (I think.)


Last entry I'll do to this post (I'm considering this post solved now):

Matt's answer I selected does work to an extent and I appreciate his help. Problem is, the .Count() never resets, so if you go past the holiday(s) dates, it always holds onto the skipped days (so instead of going to 3 days ahead of the selected date, it'll go (3+the total number of days counted))

In the event someone else comes across a situation like this, here's what I ended up doing:

Downloaded the "WorkingDaysManagement" reference, instructions from:

https://github.com/Opturne/WorkingDaysManagement

the code I ultimately used is:

        private void button1_Click(object sender, EventArgs e)
    {
        txtLog.Text = null;
        DateTime dt = DateTime.Now;
        var sd = (DateTime.Parse(txtDate.Text));

        Console.WriteLine(sd.ToShortDateString());
        var listHolidays = new List<DateTime>
        {
            new DateTime(2017, 12, 24),
            new DateTime(2017, 12, 25)
        };

        var listWeekEnd = new List<DayOfWeek>
        {
            DayOfWeek.Saturday,
            DayOfWeek.Sunday
        };

        var helper = new WorkingDayHelper(listHolidays,listWeekEnd);
        foreach(DateTime s in helper.GetSpanDates(sd,3))
        {
            Console.WriteLine("Current iteration date: "+s.ToShortDateString());
        }
        var nextworkday = (helper.GetSpanDates(sd, 3).Last().ToString());
        txtLog.Text += ("Next working day available: " + nextworkday + Environment.NewLine);
        if(helper.IsWorkingDay(sd)==true)
        {
            txtLog.Text += ("It is a working a day." + Environment.NewLine);
        }
        else
        {
            txtLog.Text += ("NOT a working day!" + Environment.NewLine);
        }

        txtEndDate.Text = nextworkday;
    }

The author of the plugin was gracious enough to put his work under the MIT license as well.

like image 611
Michael Tucker Avatar asked Dec 22 '25 10:12

Michael Tucker


1 Answers

Let's say you have parsed all the date strings from the database into a List<DateTime> namely holidays. Then you can do something like

// Parsed holidays in a list, we will use LINQ against it.
var holidays = new List<DateTime> {
    new DateTime(2017, 1, 19),
    new DateTime(2017, 1, 20),
};
// Selected Date. In your case it would be: DateTime.Parse(txtDate.Text);
var selectedDate = new DateTime(2017, 1, 16);

// Count how many holidays there are within 3 days from the selcted date.
var count = holidays.Count(holiday => holiday - selectedDate <= TimeSpan.FromDays(3));

// Then add the count and 3 to the selected date
var closingDate = selectedDate.AddDays(count + 3);

// Now we have to make sure the closing date is not a holiday.
if (count > 0)
{
    int skipDays = 0;
    while (holidays.Any(holiday => holiday == closingDate.AddDays(skipDays)))
    {
        // holidays list contains the date. Skip it.
        skipDays++;
    }

    closingDate = closingDate.AddDays(skipDays);
}
like image 51
Mike Mat Avatar answered Dec 23 '25 22:12

Mike Mat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!