How to find the 3rd Friday in a month with C#?

2020-01-25 01:15发布

Given a date (of type DateTime), how do I find the 3rd Friday in the month of that date?

标签: c# .net datetime
17条回答
Evening l夕情丶
2楼-- · 2020-01-25 01:46

My reasoning goes like this

  • the 15th is the first possible "third Friday" (1,8,15)
  • therefore we're looking for the first Friday on or after the 15th
  • DayOfWeek is an enumeration starting with 0 for Sunday
  • Therefore you have to add an offet of 5-(int)baseDay.DayOfWeek to the 15th
  • Except that the above offset can be negative, which we fix by adding 7, then doing modulo 7.

In code:

public static DateTime GetThirdFriday(int year, int month)
{
   DateTime baseDay = new DateTime(year, month, 15);
   int thirdfriday = 15 + ((12 - (int)baseDay.DayOfWeek) % 7);
   return new DateTime(year, month, thirdfriday);
}

Since there are only 7 possible results, you could also do this:

  private readonly static int[] thirdfridays =
      new int[] { 20, 19, 18, 17, 16, 15, 21 };

  public static int GetThirdFriday(int year, int month)
  {
     DateTime baseDay = new DateTime(year, month, 15);
     return thirdfridays[(int)baseDay.DayOfWeek];
  }
查看更多
Juvenile、少年°
3楼-- · 2020-01-25 01:46
    int numday = 0;
    int dayofweek = 5; //friday
    DateTime thirdfriday;
    for (int i = 0; i < (date.AddMonths(1) - date).Days && numday <3; i++)
    {
        if ((int)date.AddDays(i).DayOfWeek == dayofweek)
        {
            numday++;
        }
        if (numday == 3)
        {
            thirdfriday = date.AddDays(i);
        }

    }
查看更多
可以哭但决不认输i
4楼-- · 2020-01-25 01:48
    public DateTime GetThirdThursday(DateTime now)
    {
        DateTime ThirdThursday;
        now = DateTime.Now;
        string wkday;
        DateTime firstday = new DateTime(now.Year, now.Month, 1);
        ThirdThursday = firstday.AddDays(15);

        // ThirdThursday = now.AddDays((now.Day - 1) * -1).AddDays(14);
        wkday = ThirdThursday.DayOfWeek.ToString();

        while (wkday.CompareTo("Thursday") < 0)

        {
            ThirdThursday.AddDays(1);
        }
        return ThirdThursday;
    }
查看更多
smile是对你的礼貌
5楼-- · 2020-01-25 01:49

Sorry to jump in late on this... Might help someone else tho.

Begin rant: Loops, yuck. Too much code, yuck. Not Generic Enough, yuck.

Here's a simple function with a free overload.

public DateTime DateOfWeekOfMonth(int year, int month, DayOfWeek dayOfWeek, byte weekNumber)
{
    DateTime tempDate = new DateTime(year, month, 1);
    tempDate = tempDate.AddDays(-(tempDate.DayOfWeek - dayOfWeek));

    return
        tempDate.Day > (byte)DayOfWeek.Saturday
            ? tempDate.AddDays(7 * weekNumber)
            : tempDate.AddDays(7 * (weekNumber - 1));
}

public DateTime DateOfWeekOfMonth(DateTime sender, DayOfWeek dayOfWeek, byte weekNumber)
{
    return DateOfWeekOfMonth(sender.Year, sender.Month, dayOfWeek, weekNumber);
}

Your usage:

DateTime thirdFridayOfMonth = DateOfWeekOfMonth(DateTime.Now, DayOfWeek.Friday, 3);
查看更多
霸刀☆藐视天下
6楼-- · 2020-01-25 01:54

Probably best to abstract this to a method to do any date/day combination:

(Extension Method)

public static bool TryGetDayOfMonth(this DateTime instance, 
                                 DayOfWeek dayOfWeek, 
                                 int occurance, 
                                 out DateTime dateOfMonth)
{
    if (instance == null)
    {
        throw new ArgumentNullException("instance");
    }

    if (occurance <= 0 || occurance > 5)
    {
        throw new ArgumentOutOfRangeException("occurance", "Occurance must be greater than zero and less than 6.");
    }

    bool result;
    dateOfMonth = new DateTime();

    // Change to first day of the month
    DateTime dayOfMonth = instance.AddDays(1 - instance.Day);

    // Find first dayOfWeek of this month;
    if (dayOfMonth.DayOfWeek > dayOfWeek)
    {
        dayOfMonth = dayOfMonth.AddDays(7 - (int)dayOfMonth.DayOfWeek + (int)dayOfWeek);
    }
    else
    {
        dayOfMonth = dayOfMonth.AddDays((int)dayOfWeek - (int)dayOfMonth.DayOfWeek);
    }

    // add 7 days per occurance
    dayOfMonth = dayOfMonth.AddDays(7 * (occurance - 1));

    // make sure this occurance is within the original month
    result = dayOfMonth.Month == instance.Month;


    if (result)
    {
        dateOfMonth = dayOfMonth;
    }

    return result;
}

Results:

DateTime myDate = new DateTime(2013, 1, 1)
DateTime dateOfMonth;

myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 1, out dateOfMonth) 
// returns: true; dateOfMonth = Sunday, 1/6/2013

myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 4, out dateOfMonth) 
// returns: true; dateOfMonth = Sunday, 1/27/2013

myDate.TryGetDayOfMonth(DayOfWeek.Sunday, 5, out dateOfMonth) 
// returns: false; 

myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 1, out dateOfMonth) 
// returns: true; dateOfMonth = Wednesday, 1/2/2013

myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 4, out dateOfMonth) 
// returns: true; dateOfMonth = Wednesday, 1/23/2013

myDate.TryGetDayOfMonth(DayOfWeek.Wednesday, 5, out dateOfMonth) 
// returns: true; dateOfMonth = Wednesday, 1/30/2013 

// etc
查看更多
萌系小妹纸
7楼-- · 2020-01-25 01:55

Old post, but I found remarkably few decent answers online for this surely quite common problem! Mark Ransom's answer should be the last word on this algorithm-wise, but here is a C# helper class (in this case I think clearer than extensions) for anyone who wants a quick answer to the common problems of "first day of week in month", "xth day of week in month" and "last day of week in month".

I modified it to return DateTime.MinValue if the Xth day of the week falls outside the provided month rather than wrapping to the next month, because that to me seems more useful.

I've thrown in a LINQPad-runnable example program too.

void Main()
{
    DayOfWeek dow = DayOfWeek.Friday;
    int y = 2014;
    int m = 2;

    String.Format("First {0}: {1}", new object[] { dow, DateHelper.FirstDayOfWeekInMonth(y, m, dow) }).Dump();

    "".Dump();

    String.Format("Last {0}: {1}", new object[] { dow, DateHelper.LastDayOfWeekInMonth(y, m, dow) }).Dump();

    "".Dump();

    for(int i = 1; i <= 6; i++)
        String.Format("{0} #{1}: {2}", new object[] { dow, i, DateHelper.XthDayOfWeekInMonth(y, m, dow, i) }).Dump();
}


public class DateHelper
{
    public static DateTime FirstDayOfWeekInMonth(int year, int month, DayOfWeek day)
    {
        DateTime res = new DateTime(year, month, 1);
        int offset = -(res.DayOfWeek - day);

        if (offset < 0)
            offset += 7;

        res = res.AddDays(offset);

        return res;
    }

    public static DateTime LastDayOfWeekInMonth(int year, int month, DayOfWeek day)
    {
        DateTime dt = new DateTime(year, month, 1).AddMonths(1);        
        DateTime res = FirstDayOfWeekInMonth(dt.Year, dt.Month, day);

        res = res.AddDays(-7);

        return res;
    }


    public static DateTime XthDayOfWeekInMonth(int year, int month, DayOfWeek day, int x)
    {
        DateTime res = DateTime.MinValue;

        if (x > 0)
        {
            res = FirstDayOfWeekInMonth(year, month, day);

            if (x > 1)
                res = res.AddDays((x - 1) * 7);

            res = res.Year == year && res.Month == month ? res : DateTime.MinValue;
        }

        return res;
    }
}

Prints:

First Friday: 07/02/2014 00:00:00

Last Friday: 28/02/2014 00:00:00

Friday #1: 07/02/2014 00:00:00
Friday #2: 14/02/2014 00:00:00
Friday #3: 21/02/2014 00:00:00
Friday #4: 28/02/2014 00:00:00
Friday #5: 01/01/0001 00:00:00
Friday #6: 01/01/0001 00:00:00
查看更多
登录 后发表回答