سؤال

وبالنظر إلى نطاق التاريخ، ولست بحاجة لمعرفة كيفية العديد من الاثنين (أو الثلاثاء والأربعاء، الخ) في هذا النطاق.

وأنا أعمل حاليا في C #.

هل كانت مفيدة؟

المحلول

وجرب هذا:

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

نصائح أخرى

ومنذ كنت تستخدم C #، إذا كنت تستخدم C # 3.0، يمكنك استخدام LINQ.

وبفرض أن لديك صفيف / قائمة / 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());
}

وانها متعة للنظر في مختلف خوارزمية لحساب يوم من الأسبوع، وكان لافتاGabe Hollombe لWP حول موضوع فكرة عظيمة (وأتذكر تنفيذ <وأ href = "http://en.wikipedia.org/ ويكي / زيلر٪ 27s_congruence "يختلط =" noreferrer "> التطابق زيلر في في كوبول منذ حوالي عشرين عاما)، لكنه بدلا طول خط تسليم شخص مخططا من ساعة عند كل ما طلب وقت ما كان عليه.

في 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"، حتى إذا كان المطلوب هذا، وجعل لحلقة تقييم

dt < endDate.AddDays(1.0)

إليك بعض شبة الكود:

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

وأين DifferenceInDays عوائد End - Start في أيام، وDayOfWeek إرجاع يوم من أيام الأسبوع كعدد. فإنه لا يهم حقا ما رسم الخرائط يستخدم DayOfWeek، طالما أنه آخذ في الازدياد والمباريات مع DayImLookingFor.

لاحظ أن هذه الخوارزمية تفترض النطاق الزمني هو شامل. إذا End لا ينبغي أن تكون جزءا من مجموعة، سيكون لديك لضبط خوارزمية قليلا.

وترجمة إلى C # يترك باعتبارها ممارسة للقارئ.

وأي لغة معينة وبالتالي تنسيق التاريخ؟

إذا ممثلة التواريخ كما عد الأيام، ثم الفرق بين قيمتين الجمع (اليوم) واحد، والقسمة على 7، هو أكثر من إجابة. إذا كان كل من تواريخ انتهاء هي اليوم المذكور، إضافة واحد.

تعديل: تصحيح "مودولو 7 'إلى' القسمة على 7 '- شكرا. وهذا هو قسمة عدد صحيح.

وجئت عبر وسيلة أسهل قليلا إلى حل هذه المشكلة باستخدام LINQ.

public static int NumberOfFridays(DateTime start, DateTime end) 
{ 
    return start.GetDaysInBetween(end, inclusive: true).Count(d => d.DayOfWeek == DayOfWeek.Friday); 
} 

وعلى أمل أن يساعد.

وإضافة أصغر عدد ممكن لجعل اليوم الأول الاثنين. طرح أصغر عدد ممكن لجعل اليوم الأخير يوم الاثنين. حساب الفرق في أيام والقسمة على 7.

وتحويل التواريخ وجوليان عدد يوم، ثم القيام قليلا من الرياضيات. منذ الإثنين صفر زارة الدفاع 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

ولقد كان نفس الحاجة اليوم. لقد بدأت مع قانون القضاء العسكري وظيفة لأنني لا أفهم <م> JonB وظيفة ومنذ <م> Cyberherbalist وظيفة ليس خطيا.

وكان لديك لتصحيح

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 

ومع بين وظيفة أن العودة الحقيقية إذا، ابتداء من اليوم بداية، ونحن نجتمع لأول مرة dayImLookingFor قبل endDay.

ولقد فعلت بين وظيفة عن طريق حساب عدد اليوم من startDay ليومين الأخرى:

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;
    }
}
هل يمكن أن تحاول ذلك، إذا كنت ترغب في الحصول على أيام محددة في الأسبوع بين تاريخين
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;
}

وهذا سيعود مجموعة من الأعداد الصحيحة التي تبين عدد المرات التي يحدث كل يوم من أيام الأسبوع داخل نطاق تاريخ

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

وكان لي مشكلة مماثلة لتقرير. أنا في حاجة الى عدد أيام العمل بين تاريخين. أنا يمكن أن يكون من خلال تدوير مواعيد وعدها ولكن تدريبي الرياضيات المنفصلة لا يسمح لي. هنا هي وظيفة كتبت في VBA للحصول على عدد أيام العمل بين تاريخين. أنا متأكد من صافي لديه وظيفة أيام الأسبوع مماثلة.

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

وبعد أربع سنوات، ظننت أنني كنت تشغيل اختبار:

[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 مباشرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top