18

这是我想做的事情:给定一个日期,一周中的一天和一个整数n,确定日期是否是n一个月的第几天。

例如:

  • 的输入1/1/2009,Monday,2 将是错误的,因为1/1/2009不是第二个星期一

  • input of 11/13/2008,Thursday,2 将返回 true,因为它是第二个星期四

我怎样才能改进这个实现?

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

8 回答 8

13

您可以更改一周的检查,以便函数显示为:

private bool NthDayOfMonth(DateTime date, DayOfWeek dow, int n){
  int d = date.Day;
  return date.DayOfWeek == dow && (d-1)/7 == (n-1);
}

除此之外,它看起来非常好且高效。

于 2008-11-13T22:12:03.723 回答
10

答案来自这个网站。复制/粘贴在这里,以防该网站丢失。

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;
}
于 2008-11-13T22:17:39.640 回答
1

是 MSDN 不得不说的。它的VB,但它很容易翻译。

于 2008-11-13T22:15:17.010 回答
1

看起来语言为给定日期提供日期/日期方法。如果有人感兴趣,您可以阅读Zeller 的一致性

我不认为这是他们想要你做的,但你可以从中找到一个月的第一天的星期几。现在我考虑了一下,您可以找到给定日期的星期几N并得到模 7。

哦等等,是一周中的第 N 天(如星期天)还是一个月中的第 N 个工作日!好的,我看到了例子。

如果您可以构造一个日期,例如一个月的 1 日,也许会有所不同。

鉴于这是一周中某一天的第 N 次出现,并且您不能摆弄任何日期时间数据类型,并且您可以访问获取星期几和获取月份日期功能。星期天会是零吗?

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。

认为上面的 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 *)

希望这个大声笑没有错误!
[编辑:星期六将是第 7 天,上限在上面(N-1)*7 + 7。]
您的解决方案看起来会匹配 2 个不同的星期?看起来周日它总是会返回零?应该在 C# 中完成伪代码.. 短路 && 就像我的 if.. 嘿不应该是周日开始的几个月内 N = 1 的第一场比赛?

 d/ 7 == n

那会导致(either 0 or 1)/7 == 1,那是不对的!你||(n-1)也有,罗伯特也有。跟着罗伯特瓦格纳的回答走!就2行,短就好!拥有(Day-1) mod 7
[edit: (Day-1) div 7] 消除了我不必要的变量和 2 行设置。

作为记录,这应该检查边界情况等等,例如如果 8 月 31 日是星期日或星期六。
[编辑:也应该检查周末案例。对不起!]

于 2008-11-14T23:44:53.550 回答
1

您可以找到一个函数,该函数返回任何一个月中特定工作日第 n 次出现的日期。

http://chiragrdarji.wordpress.com/2010/08/23/find-second-saturday-and-fourth-saturday-of-month/

于 2010-08-23T11:18:08.927 回答
0

这个答案中,需要翻转以下代码:

// 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”);
}
于 2009-02-06T15:33:20.223 回答
0

上面的大多数答案都是部分准确或不必要的复杂。您可以尝试这个更简单的函数,它还会检查给定日期是否是该月的最后一天,但也是第 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;
        }
于 2014-10-15T21:45:02.623 回答
0

如果您想要一个月的第 N 天的日期列表(不仅仅是一个),您可以使用这个:

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

...并这样称呼它:

// 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()));
}

你可以像这样得到每个月的第二个星期五:

List<DateTime> dates = GetDatesForNthDOWOfMonth(2, DayOfWeek.Friday, beg, end);

...ETC。

于 2016-02-23T17:33:27.813 回答