C# 计算给定日期范围内的星期一数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/248273/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Count number of Mondays in a given date range
提问by ThePeeje
Given a date range, I need to know how many Mondays (or Tuesdays, Wednesdays, etc) are in that range.
给定一个日期范围,我需要知道该范围内有多少个星期一(或星期二、星期三等)。
I am currently working in C#.
我目前在 C# 中工作。
采纳答案by Jon B
Try this:
尝试这个:
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;
}
回答by Jonathan Leffler
Any particular language and therefore date format?
任何特定的语言和日期格式?
If dates are represented as a count of days, then the difference between two values plus one (day), and divide by 7, is most of the answer. If both end dates are the day in question, add one.
如果日期表示为天数,则两个值之差加 1(天)再除以 7 就是大部分答案。如果两个结束日期都是相关日期,请添加一个。
Edited:corrected 'modulo 7' to 'divide by 7' - thanks. And that is integer division.
编辑:将“模 7”更正为“除以 7” - 谢谢。这就是整数除法。
回答by Mark Ransom
Add the smallest possible number to make the first day a Monday. Subtract the smallest possible number to make the last day a Monday. Calculate the difference in days and divide by 7.
添加尽可能小的数字,使第一天成为星期一。减去尽可能小的数字,使最后一天成为星期一。计算天数之差并除以 7。
回答by Codewerks
Since you're using C#, if you're using C#3.0, you can use LINQ.
由于您使用的是 C#,如果您使用的是 C#3.0,则可以使用 LINQ。
Assuming you have an Array/List/IQueryable etc that contains your dates as DateTime types:
假设您有一个 Array/List/IQueryable 等,其中包含您的日期作为 DateTime 类型:
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}
Added:
添加:
Not sure if you meant grouping them and counting them, but here's how to do that in LINQ as well:
不确定您是否要对它们进行分组和计数,但在 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());
}
回答by cjm
Here's some pseudocode:
这是一些伪代码:
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
Where DifferenceInDays
returns End - Start
in days, and DayOfWeek
returns the day of the week as an integer. It doesn't really matter what mapping DayOfWeek
uses, as long as it is increasing and matches up with DayImLookingFor
.
其中以天为单位DifferenceInDays
返回End - Start
,并DayOfWeek
以整数形式返回星期几。映射DayOfWeek
使用什么并不重要,只要它增加并与DayImLookingFor
.
Note that this algorithm assumes the date range is inclusive. If End
should not be part of the range, you'll have to adjust the algorithm slightly.
请注意,此算法假定日期范围包括在内。如果End
不应该是范围的一部分,则必须稍微调整算法。
Translating to C# is left as an exercise for the reader.
翻译为 C# 留给读者作为练习。
回答by Cyberherbalist
It's fun to look at different algorithm's for calculating day of week, and @Gabe Hollombe's pointing to WP on the subject was a great idea (and I remember implementing Zeller's Congruencein COBOL about twenty years ago), but it was rather along the line of handing someone a blueprint of a clock when all they asked what time it was.
查看用于计算星期几的不同算法很有趣,@Gabe Holllombe 在这个主题上指向 WP 是一个好主意(我记得大约二十年前在 COBOL 中实现Zeller 的同余),但它更接近于当他们问现在几点时,他们会递给某人一张时钟的蓝图。
In C#:
在 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;
}
This of course does not evaluate the end date for "Mondayness", so if this was desired, make the for loop evaluate
这当然不会评估“星期一”的结束日期,所以如果需要的话,让 for 循环评估
dt < endDate.AddDays(1.0)
回答by DarenW
Convert the dates to Julian Day Number, then do a little bit of math. Since Mondays are zero mod 7, you could do the calculation like this:
将日期转换为儒略日数,然后进行一些数学运算。由于星期一是零模 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
回答by Will Rickards
I had a similar problem for a report. I needed the number of workdays between two dates. I could have cycled through the dates and counted but my discrete math training wouldn't let me. Here is a function I wrote in VBA to get the number of workdays between two dates. I'm sure .net has a similar WeekDay function.
我在报告中遇到了类似的问题。我需要两个日期之间的工作日数。我本可以循环查看日期并进行计数,但我的离散数学训练不允许我这样做。这是我在 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
回答by Paul Osterhout
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;
}
回答by Olivier de Rivoyre
I have had the same need today. I started with the cjmfunction since I don't understand the JonBfunction and since the Cyberherbalistfunction is not linear.
我今天也有同样的需求。我从cjm函数开始,因为我不理解JonB函数并且因为Cyberherbalist函数不是线性的。
I had have to correct
我不得不纠正
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayOfWeek(Start) <= DayImLookingFor
+ 1 if DayOfWeek(End) >= DayImLookingFor
- 1
to
到
DifferenceInDays(Start, End) / 7 // Integer division discarding remainder
+ 1 if DayImLookingFor is between Start.Day and End.Day
With the between function that return true if, starting from the start day, we meet first the dayImLookingFor before the endDay.
使用返回 true 的 between 函数,如果从开始日开始,我们在 endDay 之前首先遇到 dayImLookingFor。
I have done the between function by computing the number of day from startDay to the other two days:
我通过计算从 startDay 到其他两天的天数来完成 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;
}
}