Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test if a DateTime is between 2 days of week (DayOfWeek)

In C#, given an arbitrary set of DayOfWeek end points (like, DayOfWeek.Friday and DayOfWeek.Sunday) how would one test if an arbitrary date falls between those two days, inclusive?

Example:

// result == true; Oct 23, 2010 is a Saturday
var result = InBetweenDaysInclusive(new DateTime(2010, 10, 23),
                                    DayOfWeek.Friday,
                                    DayOfWeek.Sunday);

// result == true; Oct 22, 2010 is a Friday
result = InBetweenDaysInclusive(new DateTime(2010, 10, 22),
                                DayOfWeek.Friday,
                                DayOfWeek.Sunday);

// result == true; Oct 24, 2010 is a Sunday
result = InBetweenDaysInclusive(new DateTime(2010, 10, 24),
                                DayOfWeek.Friday,
                                DayOfWeek.Sunday);

// result == false; Oct 25, 2010 is a Monday
result = InBetweenDaysInclusive(new DateTime(2010, 10, 25),
                                DayOfWeek.Friday,
                                DayOfWeek.Sunday);

Thanks!

like image 602
russcollier Avatar asked Oct 27 '10 12:10

russcollier


2 Answers

This function is going to need two separate branches depending on whether the difference between start and end date is negative or positive/zero.

I could be totally off-base, but I think this works for all cases:

// No state in method, so made it static
public static bool InBetweenDaysInclusive(DateTime date, DayOfWeek start, DayOfWeek end)
{
    DayOfWeek curDay = date.DayOfWeek;

    if (start <= end)
    {
        // Test one range: start to end
        return (start <= curDay && curDay <= end);
    }
    else
    {
        // Test two ranges: start to 6, 0 to end
        return (start <= curDay || curDay <= end);
    }
}

For reference, your test data returned the following when I ran it and added Console.WriteLine for each result:

True
True
True
False

Edit: My last explanation was too vague. Here's a fixed one.

The trick is that if end < start, then you have two valid ranges: start to upper bound and lower bound to end. This would result in (start <= curDay && curDay <= upperBound) || curDay <= end && lowerBound <= curDay)

However, since they are bounds, curDay is always <= upperBound and >= lowerBound, thus we omit that code.

like image 108
Powerlord Avatar answered Sep 23 '22 03:09

Powerlord


Every date falls between any two given days of the week (think about it)...

You would need to get the endpoint dates for the dayOfWeek closest to the date in question (where day difference < 7). Then, you do a simple comparison.


NOTE: the following solution assumes a week is Sunday to Saturday

Given the following extension methods:

    /// <summary>
    /// Gets the date of the next occurrence of the day of week provided
    /// </summary>
    /// <param name="value"></param>
    /// <param name="nextDay"></param>
    /// <returns></returns>
    public static DateTime NextOccurance(this DateTime value, DayOfWeek nextDay)
    {
        if (value.DayOfWeek == nextDay) { return value; }
        else if (value.DayOfWeek > nextDay) { return value.AddDays(7 - (value.DayOfWeek - nextDay)); }
        else { return value.AddDays(nextDay - value.DayOfWeek); }
    }

    /// <summary>
    /// Gets the date of the last occurrence of the day of week provided
    /// </summary>
    /// <param name="value"></param>
    /// <param name="lastDay"></param>
    /// <returns></returns>
    public static DateTime LastOccurance(this DateTime value, DayOfWeek lastDay)
    {
        if (value.DayOfWeek == lastDay) { return value; }
        else if (value.DayOfWeek > lastDay) { return value.AddDays(-(value.DayOfWeek - lastDay)); }
        else { return value.AddDays((lastDay - value.DayOfWeek) - 7); }
    }

    /// <summary>
    /// Gets the date of the closest occurrence of the day of week provided
    /// </summary>
    /// <param name="value"></param>
    /// <param name="day"></param>
    /// <returns></returns>
    public static DateTime ClosestOccurance(this DateTime value, DayOfWeek day)
    {
        DateTime before = value.LastOccurance(day);
        DateTime after = value.NextOccurance(day);
        return ((value - before) < (after - value))
            ? before
            : after;
    }

You can find out if the dayOfWeek in question falls within two dates like this: (this is the part that assumes a week is Sunday to Saturday)

DayOfWeek dayOne = DayOfWeek.Tuesday;
DayOfWeek dayTwo = DayOfWeek.Friday;
DateTime doesDateFallWithin = DateTime.Today;
bool fallsWithin =
   doesDateFallWithin.ClosestOccurance(dayOne) <= doesDateFallWithin
   && doesDateFallWithin <= doesDateFallWithin.ClosestOccurance(dayTwo);

My results:

dayOne = Friday, dayTwo = Tuesday

10/27/2010 (Wednesday) does not fall within the closest occurrences of Friday (10/29/2010) and Tuesday (10/26/2010)
10/28/2010 (Thursday) does not fall within the closest occurrences of Friday (10/29/2010) and Tuesday (10/26/2010)
10/29/2010 (Friday) does not fall within the closest occurrences of Friday (10/29/2010) and Tuesday (10/26/2010)
10/30/2010 (Saturday) falls within the closest occurrences of Friday (10/29/2010) and Tuesday (11/2/2010)
10/31/2010 (Sunday) falls within the closest occurrences of Friday (10/29/2010) and Tuesday (11/2/2010)
11/1/2010 (Monday) falls within the closest occurrences of Friday (10/29/2010) and Tuesday (11/2/2010)
11/2/2010 (Tuesday) does not fall within the closest occurrences of Friday (11/5/2010) and Tuesday (11/2/2010)
11/3/2010 (Wednesday) does not fall within the closest occurrences of Friday (11/5/2010) and Tuesday (11/2/2010) 

dayOne = Monday, dayTwo = Wednesday

10/27/2010 (Wednesday) falls within the closest occurrences of Monday (10/25/2010) and Wednesday (10/27/2010)
10/28/2010 (Thursday) does not fall within the closest occurrences of Monday (10/25/2010) and Wednesday (10/27/2010)
10/29/2010 (Friday) does not fall within the closest occurrences of Monday (11/1/2010) and Wednesday (10/27/2010)
10/30/2010 (Saturday) does not fall within the closest occurrences of Monday (11/1/2010) and Wednesday (10/27/2010)
10/31/2010 (Sunday) does not fall within the closest occurrences of Monday (11/1/2010) and Wednesday (11/3/2010)
11/1/2010 (Monday) falls within the closest occurrences of Monday (11/1/2010) and Wednesday (11/3/2010)
11/2/2010 (Tuesday) falls within the closest occurrences of Monday (11/1/2010) and Wednesday (11/3/2010)
11/3/2010 (Wednesday) falls within the closest occurrences of Monday (11/1/2010) and Wednesday (11/3/2010) 
like image 39
Brad Avatar answered Sep 24 '22 03:09

Brad