C# 平到下个月,因为这对我来说似乎更有用

C# 平到下个月,因为这对我来说似乎更有用,c#,.net,datetime,C#,.net,Datetime,我还加入了一个LINQPad可运行的示例程序 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.Fo

我还加入了一个LINQPad可运行的示例程序

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;
    }
}
这是我的算法:

  • 查找距即将到来的星期五的天数
  • 初始化计数器并将其设置为1。从[1]返回的日期减去七天,然后将从返回日期算起的月份与从(1)返回的日期进行比较。
  • 如果月份不相等,请从[2]返回计数器
  • 如果月份相等,则递归到[2],并将1添加到[2]中创建的计数器

  • 柜台将为您提供该日期当月的第n个星期五(或即将到来的星期五)。

    我将此日期时间传递给您,作为我所查看的月初的日期时间

        private DateTime thirdSunday(DateTime timeFrom)
        {
            List<DateTime> days = new List<DateTime>();
            DateTime testDate = timeFrom;
    
            while (testDate < timeFrom.AddMonths(1))
            {
                if (testDate.DayOfWeek == DayOfWeek.Friday)
                {
                    days.Add(testDate);
                }
                testDate = testDate.AddDays(1);
            }
    
            return days[2];
        }
    
    private DateTime thirdSunday(DateTime timeFrom)
    {
    列表天数=新列表();
    DateTime testDate=timeFrom;
    而(测试日期
    以下方法效果很好,未提供事件验证。您可以找到给定日期月份的任何第n天,从开始或最后。如果要查找上一个事件,请提供负发生值

     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];
        }
    
    public static DateTime GetDayOfMonth(DateTime dateValue、DayOfWeek-DayOfWeek、int-occurrence)
    {
    List dayOfWeekRanges=新列表();
    //移到第个月的第一天
    DateTime startOfMonth=新的日期时间(dateValue.Year,dateValue.Month,1);
    //将startOfMonth移动到请求的星期几
    while(startOfMonth.DayOfWeek!=DayOfWeek)
    startOfMonth=startOfMonth.AddDays(1);
    做
    {
    dayOfWeekRanges.Add(startOfMonth);
    startOfMonth=startOfMonth.AddDays(7);
    }while(startOfMonth.Month==dateValue.Month);
    bool fromLast=发生率<0;
    if(fromLast)
    发生率=发生率*-1;
    if(fromLast)
    返回Weekranges日[dayOfWeekRanges.Count-发生];
    其他的
    周末回归日[发生-1];
    }
    
    这是我的两分钱。。。 没有不必要的循环或测试的优化解决方案:

    public static DateTime ThirdFridayOfMonth(DateTime dateTime)
    {
        int day = dateTime.Day;
        return dateTime.AddDays(21 - day - ((int)dateTime.DayOfWeek + 37 - day) % 7);
    }
    

    我编写了@justcoding121代码的扩展版本,可以从每月的最后一天获得。我不知道这个算法是对的,但到目前为止它仍然有效

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

    我知道这个帖子很旧。我有这个解决方案,试图找到一个更干净的代码#伯伯叔叔

    publicstaticboolshirdwednesday(DateTime-inputDate)
    {
    DateTime firstDayOfMonth=新的日期时间(inputDate.Year,inputDate.Month,1);
    DateTime firstDayOfNextMonth=firstDayOfMonth.AddMonths(1);
    int周三计数=0;
    while(每月第一天<下个月第一天)
    {
    如果(每月的第一天。星期三的第二天==星期三的第二天)
    星期三计数++;
    如果(星期三计数=3)
    {
    如果(inputDate==每月的第一天)
    返回true;
    其他的
    返回false;
    }
    firstDayOfMonth=每月第一天添加天数(1);
    }
    返回false;
    }
    
    +1解释而不是给出代码,因为这是一个算法问题,而不是技术问题。这应该是答案,因为它很清楚,普遍适用,并且实际有效。我已经在它的基础上创建了一个C#类,并添加了它作为任何想要快速解决问题的人的答案。你有一个bug。它应该如下所示。否则我认为这是最干净的解决方案更改为每月第一天DateTime dayOfMonth=instance.AddDays(1-instance.day);此测试:if(occurrence<0 | | occurrence>5)将允许出现值为#0,我认为这是一个错误。这是可行的,但TryGet方法是否应该引发异常?我认为您是根据Int32.TryParseMost等方法建模的,如果不是所有以Try开头的Microsoft.Net framework方法都不会对正常错误引发异常。相反,如果尝试以布尔值形式成功,它们将返回,并在out参数中返回有效结果(如不抛出异常)。现在考虑到我添加了额外的参数,验证参数并在这些参数无效时抛出异常仍然是最佳做法(我可能不应该检查实例,因为DateTime不能为null)。例如,可以在反射时同时抛出
    ArgumentException
    NotSupportedException
    ,将XthDayOfWeekInMonth更改为接受负数“x”表示“最后一个”、“倒数第二个”等是非常好的。但是我没有个人的使用案例,所以我没有这样做:o)LastDayOfWeekInMonth在12月失败,因为DateTime不能用第13个月来计算出您需要下一年的1月。该死的,我怎么从来没有注意到这一点?我会编辑一个补丁谢谢你的功能!效果很好,补充了马克的答案。谢谢。。。这真的很有帮助。:)欢迎来到SO。回答这个问题可能有助于解释您演示的代码背后的逻辑/基本原理。
    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);
    }
    
      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];
      }
    
        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;
        }
    
    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;
    }
    
    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
    
    int thirdFriday = DayFinder.FindDay(2013, 12, DayOfWeek.Friday, 3);
    
      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;
        }
    }
    
    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);
    }
    
    DateTime thirdFridayOfMonth = DateOfWeekOfMonth(DateTime.Now, DayOfWeek.Friday, 3);
    
    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;
        }
    }
    
    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
    
        private DateTime thirdSunday(DateTime timeFrom)
        {
            List<DateTime> days = new List<DateTime>();
            DateTime testDate = timeFrom;
    
            while (testDate < timeFrom.AddMonths(1))
            {
                if (testDate.DayOfWeek == DayOfWeek.Friday)
                {
                    days.Add(testDate);
                }
                testDate = testDate.AddDays(1);
            }
    
            return days[2];
        }
    
     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];
        }
    
    public static DateTime ThirdFridayOfMonth(DateTime dateTime)
    {
        int day = dateTime.Day;
        return dateTime.AddDays(21 - day - ((int)dateTime.DayOfWeek + 37 - day) % 7);
    }
    
    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);
        }
    }
    
    Assert.AreEqual(02, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, 1));
    Assert.AreEqual(30, DateTimeHelper.GetNthDayOfWeekInMonth(2019, 11, DayOfWeek.Saturday, -1));
    
        public static DateTime FindTheNthDay(
            int year, int month, DayOfWeek day, int occurrence)
        {
            var startDate = new DateTime(year, month, 1);
    
            while(startDate.DayOfWeek != day)
            {
                startDate = startDate.AddDays(1);
            }
    
            var nDays = 7 * (occurrence - 1);
            var result = startDate.AddDays(nDays);
    
            return result;
        }
    
    > FindTheNthDay(2006, 11, DayOfWeek.Friday, 4)
    [11/24/2006 12:00:00 AM]
    > FindTheNthDay(2005, 11, DayOfWeek.Friday, 4)
    [11/25/2005 12:00:00 AM]
    > FindTheNthDay(2004, 11, DayOfWeek.Friday, 4)
    [11/26/2004 12:00:00 AM]
    > FindTheNthDay(2003, 11, DayOfWeek.Friday, 4)
    [11/28/2003 12:00:00 AM]
    > FindTheNthDay(1983, 11, DayOfWeek.Friday, 4)
    [11/25/1983 12:00:00 AM]
    > FindTheNthDay(1978, 11, DayOfWeek.Friday, 4)
    [11/24/1978 12:00:00 AM]
    > FindTheNthDay(1972, 11, DayOfWeek.Friday, 4)
    [11/24/1972 12:00:00 AM]
    
        public static bool IsThirdWednesday(DateTime inputDate)
        {
            DateTime firstDayOfMonth = new DateTime(inputDate.Year, inputDate.Month, 1);
            DateTime firstDayOfNextMonth = firstDayOfMonth.AddMonths(1);
    
            int wednesdayCount = 0;
            while(firstDayOfMonth < firstDayOfNextMonth)
            {
                if (firstDayOfMonth.DayOfWeek == DayOfWeek.Wednesday)
                    wednesdayCount++;
    
                if (wednesdayCount == 3)
                {
                    if (inputDate == firstDayOfMonth)
                        return true;
                    else
                        return false;
                  
                }
    
                firstDayOfMonth = firstDayOfMonth.AddDays(1);
            }
    
            return false;
        }