C# 如何确定给定日期是否是该月的第 N 个工作日?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/288513/
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
How do I determine if a given date is the Nth weekday of the month?
提问by Kevin
Here is what I am trying to do:
Given a date, a day of the week, and an integer n
, determine whether the date is the n
th day of the month.
这是我想要做的:给定一个日期、一周中的某一天和一个整数n
,确定该日期是否是n
该月的第 th 天。
For example:
例如:
input of
1/1/2009,Monday,2
would be false because1/1/2009
is not the second Mondayinput of
11/13/2008,Thursday,2
would return true because it is the second Thursday
输入
1/1/2009,Monday,2
将是假的,因为1/1/2009
不是第二个星期一输入
11/13/2008,Thursday,2
将返回 true 因为它是第二个星期四
How can I improve this implementation?
我怎样才能改进这个实现?
private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n)
{
int d = date.Day;
return date.DayOfWeek == dow && (d/ 7 == n || (d/ 7 == (n - 1) && d % 7 > 0));
}
采纳答案by Robert Wagner
You could change the check of the week so the function would read:
您可以更改本周的支票,以便该函数显示为:
private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){
int d = date.Day;
return date.DayOfWeek == dow && (d-1)/7 == (n-1);
}
Other than that, it looks pretty good and efficient.
除此之外,它看起来非常好且高效。
回答by Andrew Bullock
回答by George Stocker
The answer is from this website. Copy/pasted here in case that site is ever lost.
答案来自这个网站。复制/粘贴到此处以防该站点丢失。
public static DateTime FindTheNthSpecificWeekday(int year, int month,int nth, System.DayOfWeek day_of_the_week)
{
// validate month value
if(month < 1 || month > 12)
{
throw new ArgumentOutOfRangeException("Invalid month value.");
}
// validate the nth value
if(nth < 0 || nth > 5)
{
throw new ArgumentOutOfRangeException("Invalid nth value.");
}
// start from the first day of the month
DateTime dt = new DateTime(year, month, 1);
// loop until we find our first match day of the week
while(dt.DayOfWeek != day_of_the_week)
{
dt = dt.AddDays(1);
}
if(dt.Month != month)
{
// we skip to the next month, we throw an exception
throw new ArgumentOutOfRangeException(string.Format("The given month has less than {0} {1}s", nth, day_of_the_week));
}
// Complete the gap to the nth week
dt = dt.AddDays((nth - 1) * 7);
return dt;
}
回答by waynecolvin
It looks like the language supplies date/day methods for a given date. If anybody was interested you can read about Zeller's congruence.
看起来该语言为给定日期提供日期/日期方法。如果有人感兴趣,您可以阅读有关Zeller's congruence 的文章。
I don't think that's what they wanted you to do but you could find the day of week of the first day of a month from that. Now that I thought about it you could find the day of week for the given day as N
and get that modulo 7.
我认为这不是他们想要你做的,但你可以从中找到一个月第一天的星期几。现在我想到了它,你可以找到给定日期的星期几,N
并得到那个模 7。
Oh wait, is that the Nth occurance of a day of the week (like Sunday) or like the Nth weekdayof the month! Okay I see the examples.
哦等等,是一周中的第 N 个出现(如星期日)还是一个月的第 N 个工作日!好的,我看到了例子。
Maybe it would make a difference if you could construct a date such as the 1st of a month..
如果您可以构建一个日期,例如一个月的 1 号,也许会有所作为。
Given that it is Nth occurance of a day of the week, and that you can't fiddle with whatever datetime datatype, and that you have access to both a get day of week and get day of month functions. Would Sunday be a zero?
鉴于它是a day of a week 的第 N 次出现,并且您不能摆弄任何 datetime 数据类型,并且您可以访问 get day of week 和 get day of month 函数。星期天会是零吗?
1) First, the day of the week would have to match the day of the week given.
2) N would have to be at least 1 and at most 4.
3) The day of the month would range between n*7*dayOfWeek + 1 and n*7*dayOfWeek + 6 for the same n.
- Let me think about that. If Sunday was the first.. 0*7*0+1 = 1 and Saturday the 6th would be 0*7*0+6.
1) 首先,星期几必须与给定的星期几相匹配。
2) N 必须至少为 1 且至多为 4。
3) 对于相同的 n,一个月中的第几天将介于 n*7*dayOfWeek + 1 和 n*7*dayOfWeek + 6 之间。
- 让我想想。如果星期日是第一个.. 0*7*0+1 = 1 并且星期六第 6 个将是 0*7*0+6。
Think 1 and 3 above are sufficient since a get day of month function shouldn't violate 2.
认为上面的 1 和 3 就足够了,因为 get day of month 函数不应该违反 2。
(* first try, this code sucks *)
function isNthGivenDayInMonth(date : dateTime;
dow : dayOfWeek;
N : integer) : boolean;
var B, A : integer (* on or before and after day of month *)
var Day : integer (* day of month *)
begin
B := (N-1)*7 + 1; A := (N-1)*7 + 6;
D := getDayOfMonth(date);
if (dow <> getDayOfWeek(date)
then return(false)
else return( (B <= Day) and (A >= Day) );
end; (* function *)
Hope there isn't a bug in that lol!
[edit: Saturday would have been the 7th, and the upper bound above (N-1)*7 + 7
.]
Your solution looks like it would match 2 different weeks? Looks like it would always return zero for Sundays? Should have done pseudocode in C#.. short circuit && is like my if..
hey shouldn't Sunday the first match for N = 1 in months that start on Sunday?
希望lol没有bug!
[编辑:星期六应该是第 7 天,并且是上面的上限(N-1)*7 + 7
。]
您的解决方案看起来会匹配 2 个不同的星期?看起来周日总是返回零?应该在 C# 中完成伪代码 .. 短路 && 就像我的 if.. 嘿,在周日开始的几个月里,周日不应该是 N = 1 的第一场比赛吗?
d/ 7 == n
That would result in (either 0 or 1)/7 == 1
, that can't be right! Your ||
catches the (n-1)
also, Robert has that. Go with Robert Wagner's answer! It's only 2 lines, short is good! Having (Day-1) mod 7
[edit: (Day-1) div 7
]eliminates my unnecessary variables and 2 lines of setup.
那会导致(either 0 or 1)/7 == 1
,那不可能!你也||
抓住了(n-1)
,罗伯特有那个。与罗伯特瓦格纳的答案一起去!只有2行,短就是好的!使用(Day-1) mod 7
[edit: (Day-1) div 7
]消除了我不必要的变量和 2 行设置。
For the record this should be checked for boundary cases and so forth like what if August 31st was a Sunday or Saturday.
[edit: Should have checked the end of week case too. Sorry!]
作为记录,这应该检查边界情况等等,就像 8 月 31 日是星期日或星期六一样。
[编辑:也应该检查周末案例。对不起!]
回答by waynecolvin
In this answer, the following code needs to be flipped:
在这个答案中,需要翻转以下代码:
// Complete the gap to the nth week
dt = dt.AddDays((nth - 1) * 7);
if(dt.Month != month)
{
// we skip to the next month, we throw an exception
throw new ArgumentOutOfRangeException(”The given month has less than ” nth.ToString() ” ”
day_of_the_week.ToString() “s”);
}
回答by Chirag Darji
You can find a function which returns a date for the nth occurrence of particular week day in any month.
您可以找到一个函数,该函数返回任何月份中特定工作日第 n 次出现的日期。
See http://chiragrdarji.wordpress.com/2010/08/23/find-second-saturday-and-fourth-saturday-of-month/
见http://chiragrdarji.wordpress.com/2010/08/23/find-second-saturday-and-fourth-saturday-of-month/
回答by reexmonkey
Most of the answers above are partially accurate or unnecessarily complex. You could try this simpler function, which also checks if the given date is the last but Nth day of the month.
上面的大多数答案部分准确或不必要地复杂。你可以试试这个更简单的函数,它还会检查给定的日期是否是当月的最后一天但第 N 天。
public static bool IsNthDayofMonth(this DateTime date, DayOfWeek weekday, int N)
{
if (N > 0)
{
var first = new DateTime(date.Year, date.Month, 1);
return (date.Day - first.Day)/ 7 == N - 1 && date.DayOfWeek == weekday;
}
else
{
var last = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
return (last.Day - date.Day) / 7 == (Math.Abs(N) - 1) && date.DayOfWeek == weekday;
}
回答by B. Clay Shannon
In case you want a list of dates for a span of time (not just one) for the Nth DayOfWeek of a Month, you can use this:
如果您想要一个月的第 N 个 DayOfWeek 的某个时间跨度(不仅仅是一个)的日期列表,您可以使用这个:
internal static List<DateTime> GetDatesForNthDOWOfMonth(int weekNum, DayOfWeek DOW, DateTime beginDate, DateTime endDate)
{
List<DateTime> datesForNthDOWOfMonth = new List<DateTime>();
int earliestDayOfMonth = 1;
int latestDayOfMonth = 7;
DateTime currentDate = beginDate;
switch (weekNum)
{
case 1:
earliestDayOfMonth = 1;
latestDayOfMonth = 7;
break;
case 2:
earliestDayOfMonth = 8;
latestDayOfMonth = 14;
break;
case 3:
earliestDayOfMonth = 15;
latestDayOfMonth = 21;
break;
case 4:
earliestDayOfMonth = 22;
latestDayOfMonth = 28;
break;
}
while (currentDate < endDate)
{
DateTime dateToInc = currentDate;
DateTime endOfMonth = new DateTime(dateToInc.Year, dateToInc.Month, DateTime.DaysInMonth(dateToInc.Year, dateToInc.Month));
bool dateFound = false;
while (!dateFound)
{
dateFound = dateToInc.DayOfWeek.Equals(DOW);
if (dateFound)
{
if ((dateToInc.Day >= earliestDayOfMonth) &&
(dateToInc.Day <= latestDayOfMonth))
{
datesForNthDOWOfMonth.Add(dateToInc);
}
}
if (dateToInc.Date.Equals(endOfMonth.Date)) continue;
dateToInc = dateToInc.AddDays(1);
}
currentDate = new DateTime(currentDate.Year, currentDate.Month, 1);
currentDate = currentDate.AddMonths(1);
}
return datesForNthDOWOfMonth;
}
...and call it this way:
...并这样称呼它:
// This is to get the 1st Monday in each month from today through one year from today
DateTime beg = DateTime.Now;
DateTime end = DateTime.Now.AddYears(1);
List<DateTime> dates = GetDatesForNthDOWOfMonth(1, DayOfWeek.Monday, beg, end);
// To see the list of dateTimes, for verification
foreach (DateTime d in dates)
{
MessageBox.Show(string.Format("Found {0}", d.ToString()));
}
You could get the 2nd Friday of each month like so:
您可以像这样获得每个月的第二个星期五:
List<DateTime> dates = GetDatesForNthDOWOfMonth(2, DayOfWeek.Friday, beg, end);
...etc.
...等等。