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

后端 未结 19 904
野的像风
野的像风 2020-11-27 06:07

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

相关标签:
19条回答
  • 2020-11-27 06:43

    I wrote extended version of @justcoding121's code that can get from the last day of the month. I don't know this algorithm is right, but it works so far.

    public static int? GetNthDayOfWeekInMonth(int year, int month, DayOfWeek dow, int weekNumOfMonth)
    {
        if (weekNumOfMonth < -5 || weekNumOfMonth == 0 || weekNumOfMonth > 5)
            throw new ArgumentOutOfRangeException("weekNumOfMonth", $"must be between 1~5 or -1~-5. ({weekNumOfMonth})");
    
        int daysOfMonth = DateTime.DaysInMonth(year, month);
    
        if (weekNumOfMonth > 0)
        {
            var firstDay = new DateTime(year, month, 1);
            var firstDayOfTargetDOW = (int)dow - (int)firstDay.DayOfWeek;
            if (firstDayOfTargetDOW < 0)
                firstDayOfTargetDOW += 7;
            var resultedDay = (firstDayOfTargetDOW + 1) + (7 * (weekNumOfMonth - 1));
    
            if (resultedDay > daysOfMonth)
                return null;
    
            return resultedDay;
        }
        else
        {
            var lastDay = new DateTime(year, month, daysOfMonth);
            var firstDayOfTargetDOW = (int)lastDay.DayOfWeek - (int)dow;
            if (firstDayOfTargetDOW < 0)
                firstDayOfTargetDOW += 7;
            var resultedDay = firstDayOfTargetDOW + (7 * (Math.Abs(weekNumOfMonth) - 1));
    
            if (resultedDay > daysOfMonth)
                return null;
    
            return (daysOfMonth - resultedDay);
        }
    }
    

    usage

    Assert.AreEqual(02, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, 1));
    Assert.AreEqual(30, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, -1));
    
    0 讨论(0)
  • 2020-11-27 06:45

    I haven't tested this, but since the third Friday can't possibly occur before the 15th of the month, create a new DateTime, then just increment until you get to a Friday.

    DateTime thirdFriday= new DateTime(yourDate.Year, yourDate.Month, 15);
    
    while (thirdFriday.DayOfWeek != DayOfWeek.Friday)
    {
       thirdFriday = thirdFriday.AddDays(1);
    }
    
    0 讨论(0)
  • 2020-11-27 06:45

    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];
      }
    
    0 讨论(0)
  • 2020-11-27 06:48

    Following works great, no validation for occurrence is provided. You can find any nth day for the given date month either from start or last. Provide minus occurrence value if you are looking for from the last.

     public static DateTime GetDayOfMonth(DateTime dateValue, DayOfWeek dayOfWeek, int occurance)
        {
            List<DateTime> dayOfWeekRanges = new List<DateTime>();
    
            //move to the first of th month
            DateTime startOfMonth = new DateTime(dateValue.Year, dateValue.Month, 1);
    
            //move startOfMonth to the dayOfWeek requested
            while (startOfMonth.DayOfWeek != dayOfWeek)
                startOfMonth = startOfMonth.AddDays(1);
    
            do
            {
                dayOfWeekRanges.Add(startOfMonth);
                startOfMonth = startOfMonth.AddDays(7);
            } while (startOfMonth.Month == dateValue.Month);
    
            bool fromLast = occurance < 0;
            if (fromLast)
                occurance = occurance * -1;
    
            if (fromLast)
                return dayOfWeekRanges[dayOfWeekRanges.Count - occurance];
            else
                return dayOfWeekRanges[occurance - 1];
        }
    
    0 讨论(0)
  • 2020-11-27 06:50
        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;
        }
    
    0 讨论(0)
  • 2020-11-27 06:51

    I followed User:Mark Ransom's algorithm and wrote a generalized day finder. For example to get the 3rd friday of december 2013,

    int thirdFriday = DayFinder.FindDay(2013, 12, DayOfWeek.Friday, 3);
    

    And here is the function definition. It doesn't have any iterative loops, so its efficient.

      public class DayFinder
      {
    
        //For example to find the day for 2nd Friday, February, 2016
        //=>call FindDay(2016, 2, DayOfWeek.Friday, 2)
        public static int FindDay(int year, int month, DayOfWeek Day, int occurance)
        {
    
            if (occurance <= 0 || occurance > 5)
                throw new Exception("Occurance is invalid");
    
            DateTime firstDayOfMonth = new DateTime(year, month, 1);
            //Substract first day of the month with the required day of the week 
            var daysneeded = (int)Day - (int)firstDayOfMonth.DayOfWeek;
            //if it is less than zero we need to get the next week day (add 7 days)
            if (daysneeded < 0) daysneeded = daysneeded + 7;
            //DayOfWeek is zero index based; multiply by the Occurance to get the day
            var resultedDay = (daysneeded + 1) + (7 * (occurance - 1));
    
            if (resultedDay > (firstDayOfMonth.AddMonths(1) - firstDayOfMonth).Days)
                throw new Exception(String.Format("No {0} occurance(s) of {1} in the required month", occurance, Day.ToString()));
    
            return resultedDay;
        }
    }
    
    0 讨论(0)
提交回复
热议问题