如何测试DateTime是否在一周的2天之间(DayOfWeek)

时间:2010-10-27 12:39:33

标签: c# datetime dayofweek

在C#中,给定一组任意DayOfWeek终点(如DayOfWeek.Friday和DayOfWeek.Sunday),如何测试任意日期是否在这两天之间,包括在内?

示例:

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

谢谢!

6 个答案:

答案 0 :(得分:13)

此功能需要两个独立的分支,具体取决于开始日期和结束日期之间的差异是负数还是正数/零。

我可能完全偏离基础,但我认为这适用于所有情况:

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

作为参考,当我运行它并为每个结果添加Console.WriteLine时,您的测试数据返回以下内容:

True
True
True
False

编辑:我的上一个解释太模糊了。这是一个固定的。

诀窍在于,如果end < start,则您有两个有效范围:start到上限,下限到end。这将导致(start <= curDay && curDay <= upperBound) || curDay <= end && lowerBound <= curDay)

但是,由于它们是边界,curDay 总是 <= upperBound>= lowerBound,因此我们省略了该代码。

答案 1 :(得分:7)

每个日期都在一周的任意两天之间(想一想)......

您需要获取最接近相关日期的dayOfWeek的端点日期(日差<7)。然后,你做一个简单的比较。


注意:以下解决方案假设一周是星期日到星期六

给出以下扩展方法:

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

您可以查看有问题的dayOfWeek是否属于以下两个日期:(这是假设一周是星期日到星期六的部分)

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

我的结果:

dayOne =星期五,dayTwo =星期二

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 =星期一,dayTwo =星期三

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) 

答案 2 :(得分:5)

@Brad的观点是,一周中的任何一天都在一周的任何两天之间有效。但是,我们假设一周中的两天是订购

也就是说,当我们说“是星期五到星期日的2010年10月30日(星期六)?”,我们真的在问,“是2010年10月30日星期五,星期六或星期天?“

这一观察结果使我们能够将问题分解为两个组成部分并轻松解决问题:

1)确定一周中的某一天是否是一周中特定日期之一(这是微不足道的)。

2)确定从一天到另一天的一周中的天数。也就是说,当给出“星期五”和“星期日”时,我们想要一个返回“星期五,星期六,星期日”的功能,当给出“星期一”和“星期五”时,返回“星期一,星期二,星期三,星期四,星期五”。这是问题的棘手部分。

为了解决第二个问题,我们基本上从第一天走到第二天,返回中间的所有日子。为了正确地做到这一点,我们必须考虑到第二天可能小于第一天的事实(在星期日= 0的表示意义上小于星期五= 5)。因此,我们在整数空间中执行“walk”,如果小于第一天,则在第二天添加7。我们在“出路”上转换为星期几的空间(模数为7的整数)。

以下是解决此问题的代码和一系列测试。 “GetDaysBetweenInclusive”方法解决了问题#2,“IsDayOfWeekBetween”为问题#1添加了解决方案并解决了OP的问题。

享受。

using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace DayOfWeekUtilities
{
    public static class DayOfWeekHelpers
    {
        /// <summary>
        /// returns all days of the week, inclusive, from day1 to day2
        /// </summary>
        public static IEnumerable<DayOfWeek> GetDaysBetweenInclusive(DayOfWeek day1,
                                                                     DayOfWeek day2)
        {
            var final = (int)day2;
            if(day2 < day1)
            {
                final += 7;
            }
            var curr = (int)day1;
            do
            {
                yield return (DayOfWeek) (curr%7);
                curr++;
            } while (curr <= final);
        }

        /// <summary>
        /// returns true if the provided date falls on a day of the 
        /// week between day1 and day2, inclusive
        /// </summary>
        public static bool IsDayOfWeekBetween(this DateTime date,
                                              DayOfWeek day1,
                                              DayOfWeek day2)
        {
            return GetDaysBetweenInclusive(day1, day2).Contains(date.DayOfWeek);
        }
    }

    [TestFixture]
    public class Tests
    {
        [Test]
        public void Test()
        {
            Assert.IsTrue(new DateTime(2010, 10, 22).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsTrue(new DateTime(2010, 10, 23).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsTrue(new DateTime(2010, 10, 24).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsFalse(new DateTime(2010, 10, 25).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsFalse(new DateTime(2010, 10, 26).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsFalse(new DateTime(2010, 10, 27).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsFalse(new DateTime(2010, 10, 28).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));
            Assert.IsTrue(new DateTime(2010, 10, 29).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Sunday));

            Assert.IsTrue(new DateTime(2010, 10, 22).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 23).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 24).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 25).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 26).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 27).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 28).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 29).IsDayOfWeekBetween(DayOfWeek.Friday, DayOfWeek.Friday));

            Assert.IsTrue(new DateTime(2010, 10, 22).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 23).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsFalse(new DateTime(2010, 10, 24).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 25).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 26).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 27).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 28).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));
            Assert.IsTrue(new DateTime(2010, 10, 29).IsDayOfWeekBetween(DayOfWeek.Monday, DayOfWeek.Friday));

            Assert.IsTrue(new DateTime(2010, 10, 22).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 23).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 24).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 25).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 26).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsFalse(new DateTime(2010, 10, 27).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 28).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
            Assert.IsTrue(new DateTime(2010, 10, 29).IsDayOfWeekBetween(DayOfWeek.Thursday, DayOfWeek.Tuesday));
        }
    }
}

答案 3 :(得分:0)

托马斯·莱维斯克的回答很好。请记住DayOfWeek.Sunday在此枚举中为0而不是6。

这对我来说是个问题,因为在挪威星期一是本周的第一天,而不是星期天。

在这种情况下,您应该考虑检查枚举是否等于DayOfWeek.Sunday,以及在进行比较之前是否要将值加7以确保以正确的方式考虑星期日。

如果您将星期日视为您居住的第一天,那么无论如何都不是问题;)

答案 4 :(得分:0)

我认为这应该有效。无论你认为是一周的第一天,它也应该有效:

private bool InBetweenDaysInclusive(DateTime dateToCheck, DayOfWeek lowerLimit, DayOfWeek upperLimit)
{
    CultureInfo ci = CultureInfo.CurrentCulture;

    int diffDateToCheckFirstDayOfWeek = dateToCheck.DayOfWeek - ci.DateTimeFormat.FirstDayOfWeek;
    if (diffDateToCheckFirstDayOfWeek < 0)
        diffDateToCheckFirstDayOfWeek += 7;

    int diffLowerLimitFirstDayOfWeek = lowerLimit - ci.DateTimeFormat.FirstDayOfWeek;
    if (diffLowerLimitFirstDayOfWeek < 0)
        diffLowerLimitFirstDayOfWeek += 7;

    int diffUpperLimitFirstDayOfWeek = upperLimit - ci.DateTimeFormat.FirstDayOfWeek;
    if (diffUpperLimitFirstDayOfWeek < 0)
        diffUpperLimitFirstDayOfWeek += 7;

    if (diffUpperLimitFirstDayOfWeek < diffLowerLimitFirstDayOfWeek)
        throw new Exception("The lower-limit day must be earlier in the week than the upper-limit day");

    return diffDateToCheckFirstDayOfWeek >= diffLowerLimitFirstDayOfWeek && diffDateToCheckFirstDayOfWeek <= diffUpperLimitFirstDayOfWeek;
}

编辑:
万一你想知道,if < 0+= 7是为了解决这两天减去文化的问题。代码可能会变得更清晰,但你认为我认为这一点。

答案 5 :(得分:0)

Stuart Lauge说:...在整数空间中执行“walk”。 我明白了:

private bool InBetweenDaysInclusive(DateTime date, DayOfWeek day1, DayOfWeek day2)
{
    int d1 = (int)day1;
    int d2 = (int)day2;
    int dx = (int)date.DayOfWeek;
    if (d2 < d1) d2 += 7;
    if (dx < d1) dx += 7;
    return (dx >= d1 && dx <= d2);
}