计算给定日期范围内的星期一数

鉴于日期范围,我需要知道在该范围内有多少星期一(或星期二,星期三等)。

我目前在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。

假设您有一个包含日期为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()); } 

看看计算星期几的不同算法是很有趣的,而且@Gabe Hollombe在这个主题上指向WP是一个好主意(我记得大约二十年前在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; } 

这当然不会评估“星期一”的结束日期,因此如果需要,请进行for循环评估

 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以天为单位End - StartDayOfWeek以整数forms返回星期几。 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。

将日期转换为朱利安日数,然后做一些数学运算。 由于星期一是零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 

我今天也有同样的需要。 我开始使用cjm函数,因为我不理解JonB函数,因为Cyber​​herbalist函数不是线性的。

我必须纠正

 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之间的函数。

我通过计算从startDay到其他两天的天数来完成介于两者之间的function:

 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 GetSelectedDaysInPeriod(DateTime startDate, DateTime endDate, List daysToCheck) { var selectedDates = new List(); 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(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 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(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(); for (int dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++) result[(DayOfWeek)dayOfWeek] = resultArray[dayOfWeek]; return result; } 

我的报告也有类似的问题。 我需要两个日期之间的工作日数。 我可以在日期中循环并计算,但我的离散数学训练不会让我。 这是我在VBA中编写的函数,用于获取两个日期之间的工作日数。 我确定.net有类似的WeekDayfunction。

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