2008-10-29 120 views

回答

32

试试这个:

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

任何特定的语言,因此日期格式?

如果日期表示为天数,那么两个值之差加上一天(天)并除以7就是答案的大部分。如果两个结束日期都是有问题的那一天,请添加一个。

编辑:纠正'模7'到'除以7' - 谢谢。那是整数除法。

+0

他的标签包含C# – mmcdole 2008-10-29 20:31:00

+0

除非我误解您提出的算法,否则任何日期范围的最大结果将为6,因为这是任何数字的模7的最大结果。我错过了什么? – EBGreen 2008-10-29 20:33:29

+0

是的,它应该除以7,而不是mod 7 – Moe 2008-10-29 20:34:20

1

添加尽可能小的数字,以使第一天成为星期一。减去最小可能的数字,使最后一天成为星期一。计算天数的差值除以7.

20

由于您使用的是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()); 
} 
4

下面是一些伪代码:

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#仅供读者参考。

13

看看不同的算法来计算每周的星期几很有意思,并且@Gabe Hollombe指出WP在这个主题上是一个好主意(我记得大约二十年前在COBOL中实现Zeller's Congruence),但它是相当的当他们问他们什么时候是什么时候,向他们传递一个时钟蓝图的路线。

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

转换的日期朱利安日数,然后做一点数学。由于周一是零国防部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 
0

我有一个报告了类似的问题。我需要两个日期之间的工作日数。 我本来可以通过日期和计数,但离散的数学训练不会让我。这是我在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 
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; 
} 
1

我今天有同样的需求。我开始使用函数,因为我不了解函数,因为函数不是线性函数。

我必须要纠正

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。

我已经通过计算当日从朝九特派到其他二级天数完成的功能之间:

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; 
    } 
} 
1
你可以试试这个,如果你想获得两个日期之间的特定工作日
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; 
} 
0

四年后,我想我会运行一个测试:

[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."); 
} 

中号y使用TimeSpan有点过分---实际上我想直接查询TimeSpan

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

我遇到了一个稍微简单的方法来解决这个问题,使用LINQ。

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

希望有所帮助。

相关问题