25

日付範囲を指定すると、その範囲内の月曜日(または火曜日、水曜日など)の数を知る必要があります。

私は現在C#で働いています。

4

14 に答える 14

50

これを試して:

static int CountDays(DayOfWeek day, DateTime start, DateTime end)
{
    TimeSpan ts = end - start;                       // Total duration
    int count = (int)Math.Floor(ts.TotalDays / 7);   // Number of whole weeks
    int remainder = (int)(ts.TotalDays % 7);         // Number of remaining days
    int sinceLastDay = (int)(end.DayOfWeek - day);   // Number of days since last [day]
    if (sinceLastDay < 0) sinceLastDay += 7;         // Adjust for negative days since last [day]

    // If the days in excess of an even week are greater than or equal to the number days since the last [day], then count this one, too.
    if (remainder >= sinceLastDay) count++;          

    return count;
}
于 2008-10-29T21:40:02.273 に答える
22

C# を使用しているため、C#3.0 を使用している場合は LINQ を使用できます。

日付を DateTime 型として含む Array/List/IQueryable などがあるとします。

DateTime[] dates = { new DateTime(2008,10,6), new DateTime(2008,10,7)}; //etc....

var mondays = dates.Where(d => d.DayOfWeek == DayOfWeek.Monday); // = {10/6/2008}

追加した:

それらをグループ化して数えることを意図しているかどうかはわかりませんが、LINQ でも同様に行う方法を次に示します。

var datesgrouped = from d in dates
                   group d by d.DayOfWeek into grouped
                   select new { WeekDay = grouped.Key, Days = grouped };

foreach (var g in datesgrouped)
{
    Console.Write (String.Format("{0} : {1}", g.WeekDay,g.Days.Count());
}
于 2008-10-29T20:47:32.053 に答える
20

曜日を計算するためのさまざまなアルゴリズムを見るのは楽しいです.@Gabe Hollombeがこの件に関してWPを指摘したことは素晴らしいアイデアでした(そして、約20年前にCOBOLでZellerの合同を実装したことを覚えています)が、むしろ誰かに時計の設計図を渡して、今何時ですかと尋ねられました。

C# の場合:

    private int CountMondays(DateTime startDate, DateTime endDate)
    {
        int mondayCount = 0;

        for (DateTime dt = startDate; dt < endDate; dt = dt.AddDays(1.0))
        {
            if (dt.DayOfWeek == DayOfWeek.Monday)
            {
                mondayCount++;
            }
        }

        return mondayCount;
    }

もちろん、これは「Mondayness」の終了日を評価しません。したがって、これが必要な場合は、for ループを評価します。

dt < endDate.AddDays(1.0)
于 2008-10-29T20:50:10.800 に答える
5

ここにいくつかの擬似コードがあります:

DifferenceInDays(Start, End) / 7   // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End)   >= DayImLookingFor
- 1

Whereは日数をDifferenceInDays返し、曜日を整数で返します。マッピングが増加し、 と一致する限り、マッピングが何を使用するかは問題ではありません。End - StartDayOfWeekDayOfWeekDayImLookingFor

このアルゴリズムは、日付範囲が包括的であると想定していることに注意してください。範囲の一部であってはならない場合Endは、アルゴリズムを少し調整する必要があります。

C# への変換は、読者の演習として残されています。

于 2008-10-29T20:48:29.883 に答える
3

特定の言語、したがって日付形式はありますか?

日付が日数として表される場合、2つの値に1(日)を加えた値の差を7で割ると、ほとんどの答えが得られます。両方の終了日が問題の日である場合は、1つ追加します。

編集:「モジュロ7」を「7で割る」に修正-ありがとう。そしてそれは整数除算です。

于 2008-10-29T20:24:24.253 に答える
2
2つの日付の間の特定の曜日を取得したい場合は、これを試すことができます
public List<DateTime> GetSelectedDaysInPeriod(DateTime startDate, DateTime endDate, List<DayOfWeek> daysToCheck)
{
    var selectedDates = new List<DateTime>();

    if (startDate >= endDate)
        return selectedDates; //No days to return

    if (daysToCheck == null || daysToCheck.Count == 0)
        return selectedDates; //No days to select

    try
    {
        //Get the total number of days between the two dates
        var totalDays = (int)endDate.Subtract(startDate).TotalDays;

        //So.. we're creating a list of all dates between the two dates:
        var allDatesQry = from d in Enumerable.Range(1, totalDays)
                             select new DateTime(
                                                  startDate.AddDays(d).Year,
                                                  startDate.AddDays(d).Month,
                                                  startDate.AddDays(d).Day);

        //And extracting those weekdays we explicitly wanted to return
        var selectedDatesQry = from d in allDatesQry
                                  where daysToCheck.Contains(d.DayOfWeek)
                                  select d;

        //Copying the IEnumerable to a List
        selectedDates = selectedDatesQry.ToList();
    }
    catch (Exception ex)
    {
        //Log error
        //...

        //And re-throw
        throw;
    }
    return selectedDates;
}
于 2011-12-06T09:02:07.740 に答える
1

これにより、日付範囲内で各曜日が何回発生するかを示す整数のコレクションが返されます。

    int[] CountDays(DateTime firstDate, DateTime lastDate)
    {
        var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
        var weeks = (int)Math.Floor(totalDays / 7);

        var result = Enumerable.Repeat<int>(weeks, 7).ToArray();
        if (totalDays % 7 != 0)
        {
            int firstDayOfWeek = (int)firstDate.DayOfWeek;
            int lastDayOfWeek = (int)lastDate.DayOfWeek;
            if (lastDayOfWeek < firstDayOfWeek)
                lastDayOfWeek += 7;
            for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
                result[dayOfWeek % 7]++;
        }
        return result;
    }

または、FirstDate.TotalDaysOfWeeks(SecondDate)を実行して、辞書を返すわずかなバリエーション

    public static Dictionary<DayOfWeek, int> TotalDaysOfWeeks(this DateTime firstDate, DateTime lastDate)
    {
        var totalDays = lastDate.Date.Subtract(firstDate.Date).TotalDays + 1;
        var weeks = (int)Math.Floor(totalDays / 7);

        var resultArray = Enumerable.Repeat<int>(weeks, 7).ToArray();
        if (totalDays % 7 != 0)
        {
            int firstDayOfWeek = (int)firstDate.DayOfWeek;
            int lastDayOfWeek = (int)lastDate.DayOfWeek;
            if (lastDayOfWeek < firstDayOfWeek)
                lastDayOfWeek += 7;
            for (int dayOfWeek = firstDayOfWeek; dayOfWeek <= lastDayOfWeek; dayOfWeek++)
                resultArray[dayOfWeek % 7]++;
        }
        var result = new Dictionary<DayOfWeek, int>();
        for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
            result[(DayOfWeek)dayOfWeek] = resultArray[dayOfWeek];
        return result;
    }
于 2012-02-23T18:01:36.940 に答える
1

可能な限り小さい数を追加して、最初の日を月曜日にします。可能な限り最小の数を引いて、最終日を月曜日にします。日数の差を計算し、7で割ります。

于 2008-10-29T20:33:06.917 に答える
1

日付をユリウス日番号に変換してから、少し計算します。月曜日はゼロ mod 7 なので、次のように計算できます。

JD1=JulianDayOf(the_first_date)
JD2=JulianDayOf(the_second_date)
Round JD1 up to nearest multiple of 7
Round JD2 up to nearest multiple of 7
d = JD2-JD1
nMondays = (JD2-JD1+7)/7    # integer divide
于 2008-10-29T20:50:37.040 に答える
1

今日も同じ必要がありました。JonB関数が理解できず、Cyber​​herbalist 関数が線形でないため、cjm 関数から始めました。

正さなければならなかった

DifferenceInDays(Start, End) / 7   // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End)   >= DayImLookingFor
- 1

DifferenceInDays(Start, End) / 7   // Integer division discarding remainder
+ 1 if DayImLookingFor is between Start.Day and End.Day 

開始日から始まり、endDay の前に dayImLookingFor に最初に出会った場合に true を返す between 関数を使用します。

startDay から他の 2 日間までの日数を計算して between 関数を実行しました。

private int CountDays(DateTime start, DateTime end, DayOfWeek selectedDay)
{
    if (start.Date > end.Date)
    {
        return 0;
    }
    int totalDays = (int)end.Date.Subtract(start.Date).TotalDays;
    DayOfWeek startDay = start.DayOfWeek;
    DayOfWeek endDay = end.DayOfWeek;
    ///look if endDay appears before or after the selectedDay when we start from startDay.
    int startToEnd = (int)endDay - (int)startDay;
    if (startToEnd < 0)
    {
        startToEnd += 7;
    }
    int startToSelected = (int)selectedDay - (int)startDay;
    if (startToSelected < 0)
    {
        startToSelected += 7;
    }
    bool isSelectedBetweenStartAndEnd = startToEnd >= startToSelected;
    if (isSelectedBetweenStartAndEnd)
    {
        return totalDays / 7 + 1;
    }
    else
    {
        return totalDays / 7;
    }
}
于 2009-08-24T14:45:39.650 に答える
0
private System.Int32 CountDaysOfWeek(System.DayOfWeek dayOfWeek, System.DateTime date1, System.DateTime date2)
{
  System.DateTime EndDate;
  System.DateTime StartDate;

  if (date1 > date2)
  {
    StartDate = date2;
    EndDate = date1;
  }
  else
  {
    StartDate = date1;
    EndDate = date2;
  }

  while (StartDate.DayOfWeek != dayOfWeek)
    StartDate = StartDate.AddDays(1);

  return EndDate.Subtract(StartDate).Days / 7 + 1;
}
于 2008-10-29T21:57:14.517 に答える
0

4年後、私はテストを実行すると思いました:

[TestMethod]
public void ShouldFindFridaysInTimeSpan()
{
    //reference: http://stackoverflow.com/questions/248273/count-number-of-mondays-in-a-given-date-range

    var spanOfSixtyDays = new TimeSpan(60, 0, 0, 0);
    var setOfDates = new List<DateTime>(spanOfSixtyDays.Days);
    var now = DateTime.Now;

    for(int i = 0; i < spanOfSixtyDays.Days; i++)
    {
        setOfDates.Add(now.AddDays(i));
    }

    Assert.IsTrue(setOfDates.Count == 60,
        "The expected number of days is not here.");

    var fridays = setOfDates.Where(i => i.DayOfWeek == DayOfWeek.Friday);

    Assert.IsTrue(fridays.Count() > 0,
        "The expected Friday days are not here.");
    Assert.IsTrue(fridays.First() == setOfDates.First(i => i.DayOfWeek == DayOfWeek.Friday),
        "The expected first Friday day is not here.");
    Assert.IsTrue(fridays.Last() == setOfDates.Last(i => i.DayOfWeek == DayOfWeek.Friday),
        "The expected last Friday day is not here.");
}

私の使用は少しやり過ぎです---実際には、直接TimeSpanクエリを実行したかったのです。TimeSpan

于 2012-01-26T22:04:38.940 に答える
0

レポートについても同様の問題がありました。2 つの日付の間の稼働日数が必要でした。日付を循環させて数えることもできましたが、個別の数学のトレーニングではそれができませんでした。これは、2 つの日付間の稼働日数を取得するために VBA で記述した関数です。.net にも同様の WeekDay 機能があるはずです。

   1  
   2  ' WorkDays
   3  ' returns the number of working days between two dates
   4  Public Function WorkDays(ByVal dtBegin As Date, ByVal dtEnd As Date) As Long
   5  
   6     Dim dtFirstSunday As Date
   7     Dim dtLastSaturday As Date
   8     Dim lngWorkDays As Long
   9  
  10     ' get first sunday in range
  11     dtFirstSunday = dtBegin + ((8 - Weekday(dtBegin)) Mod 7)
  12  
  13     ' get last saturday in range
  14     dtLastSaturday = dtEnd - (Weekday(dtEnd) Mod 7)
  15  
  16     ' get work days between first sunday and last saturday
  17     lngWorkDays = (((dtLastSaturday - dtFirstSunday) + 1) / 7) * 5
  18  
  19     ' if first sunday is not begin date
  20     If dtFirstSunday <> dtBegin Then
  21  
  22        ' assume first sunday is after begin date
  23        ' add workdays from begin date to first sunday
  24        lngWorkDays = lngWorkDays + (7 - Weekday(dtBegin))
  25  
  26     End If
  27  
  28     ' if last saturday is not end date
  29     If dtLastSaturday <> dtEnd Then
  30  
  31        ' assume last saturday is before end date
  32        ' add workdays from last saturday to end date
  33        lngWorkDays = lngWorkDays + (Weekday(dtEnd) - 1)
  34  
  35     End If
  36  
  37     ' return working days
  38     WorkDays = lngWorkDays
  39  
  40  End Function
于 2008-10-29T20:52:36.083 に答える