11

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

谢谢!

4

6 回答 6

14

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

我可能完全不在基地,但我认为这适用于所有情况:

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

于 2010-10-27T13:46:36.573 回答
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) 
于 2010-10-27T12:47:34.827 回答
6

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

也就是说,当我们说“是 2010 年 10 月 30 日(星期六)在星期五和星期日之间吗?” ,我们真的要问,“2010 年 10 月 30 日是星期五、星期六还是星期日?” .

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

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

2) 确定一周中的一组日子,让你从一天到另一天。也就是说,我们想要一个函数,在给定“星期五”和“星期日”时返回“星期五、星期六、星期日”,并在给定“星期一”和“星期五”时返回“星期一、星期二、星期三、星期四、星期五”。这是问题的棘手部分。

为了解决第二个问题,我们基本上是从第一天走到第二天,中间的所有天都返回。为了正确地做到这一点,我们必须考虑这样一个事实,即第二天可能小于第一天(在代表性意义上,星期日 = 0 小于星期五 = 5)。因此,我们在整数空间中执行“步行”,如果小于第一天,则将第二天加 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));
        }
    }
}
于 2010-10-27T17:22:24.317 回答
0

Thomas Levesque 的回答在这里很好。请记住,DayOfWeek.Sunday在这个枚举中是 0 而不是 6。

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

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

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

于 2010-10-27T12:46:34.243 回答
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要解决减去两天的问题并没有文化意识。代码可能会更简洁一些,但我认为你明白了。

于 2010-10-27T13:44:34.347 回答
0

Stuart Lauge 说:……在整数空间中进行“行走”。我明白:

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);
}
于 2011-05-12T13:29:31.057 回答