11

C# では、DayOfWeek エンドポイント (DayOfWeek.Friday や DayOfWeek.Sunday など) の任意のセットが与えられた場合、任意の日付がこれら 2 日間 (両端を含む) に含まれるかどうかをテストするにはどうすればよいでしょうか?

例:

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

この関数は、開始日と終了日の差が負か正/ゼロかによって、2 つの別々の分岐が必要になります。

私は完全にオフベースである可能性がありますが、これはすべてのケースで機能すると思います:

// 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、2 つの有効な範囲があることです。start上限と下限endです。これにより、(start <= curDay && curDay <= upperBound) || curDay <= end && lowerBound <= curDay)

ただし、それらは境界でcurDayあるため、常に <= upperBound>= lowerBoundであるため、そのコードは省略します。

于 2010-10-27T13:46:36.573 に答える
7

すべての日付は、特定の 2 つの曜日の間にあります(考えてみてください)...

問題の日付に最も近い dayOfWeek のエンドポイントの日付を取得する必要があります (日差 < 7)。次に、簡単な比較を行います。


注:次の解決策では、1 週間が日曜日から土曜日であると想定しています

次の拡張メソッドがあるとします。

    /// <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 が次のように 2 つの日付に含まれるかどうかを調べることができます(これは、1 週間が日曜日から土曜日であると想定している部分です)。

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のポイントは、曜日が任意の2日間の間にあるという点が有効です。ただし、問題の週の2日が注文されていると想定しています。

つまり、「2010年10月30日(土曜日)は金曜日と日曜日の間にあるのでしょうか?」ということです。、私たちは本当に「2010年10月30日は金曜日、土曜日、または日曜日のいずれかですか?」と尋ねています。

この観察により、問題を2つのコンポーネントに分解し、問題全体を簡単に解決できます。

1)特定の曜日が特定の曜日のセットの1つであるかどうかを判別します(これは些細なことです)。

2)ある日から別の日に移動する曜日のセットを決定します。つまり、「Friday」と「Sunday」を指定すると「Friday、Saturday、Sunday」を返し、「Monday」と「Friday」を指定すると「Monday、Tuesday、Wednesday、Thursday、Friday」を返す関数が必要です。これは問題のトリッキーな部分です。

2番目の問題を解決するために、私たちは基本的に1日目から2日目まで歩き、その間のすべての日を返します。これを正しく行うには、2日目が1日目よりも少ない可能性があるという事実を考慮する必要があります(日曜日=0は金曜日=5よりも少ないという表現の意味で)。したがって、整数空間で「ウォーク」を実行し、1日目よりも小さい場合は2日目に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

これはうまくいくはずだと思います。また、週の最初の日と見なすものに関係なく機能するはずです。

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 < 0and+= 7は、2 日を差し引くことは文化に対応していないことを回避するためのものです。コードはおそらくもう少しきれいにすることができますが、私が思う要点は理解できます。

于 2010-10-27T13:44:34.347 に答える
0

Thomas Levesque の答えはここで良いです。DayOfWeek.Sundayこの列挙型内では 6 ではなく 0 であることに注意してください。

ノルウェーでは日曜日ではなく月曜日が週の最初の日であるため、これは私にとって問題です。

その場合、enum が に等しいかDayOfWeek.Sundayどうかを確認し、比較を行う前に値に 7 を追加して、Sunday が正しい方法で考慮されていることを確認することを検討する必要があります。

あなたが住んでいる週の最初の日が日曜日なら、とにかく問題ありません ;)

于 2010-10-27T12:46:34.243 に答える
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 に答える