/// <summary> /// Get's the next valid second after the current . /// </summary> /// <param name="dateTime">The date time (fractions of a second are removed).</param> /// <param name="month">The month.</param> /// <param name="week">The week.</param> /// <param name="day">The day.</param> /// <param name="weekDay">The week day.</param> /// <param name="hour">The hour.</param> /// <param name="minute">The minute.</param> /// <param name="second">The second.</param> /// <param name="calendar">The calendar.</param> /// <param name="calendarWeekRule">The calendar week rule.</param> /// <param name="firstDayOfWeek">The first day of week.</param> /// <param name="inclusive">if set to <c>true</c> can return the time specified, otherwise, starts at the next second..</param> /// <returns> /// The next valid date (or <see cref="DateTime.MaxValue"/> if none). /// </returns> public static DateTime NextValid( this DateTime dateTime, Month month = Month.Every, Week week = Week.Every, Day day = Day.Every, WeekDay weekDay = WeekDay.Every, Hour hour = Hour.Zeroth, Minute minute = Minute.Zeroth, Second second = Second.Zeroth, Calendar calendar = null, CalendarWeekRule calendarWeekRule = CalendarWeekRule.FirstFourDayWeek, DayOfWeek firstDayOfWeek = DayOfWeek.Sunday, bool inclusive = false) { // Never case, if any are set to never, we'll never get a valid date. if ((month == Month.Never) || (week == Week.Never) || (day == Day.Never) || (weekDay == WeekDay.Never) || (hour == Hour.Never) || (minute == Minute.Never) || (second == Second.Never)) return DateTime.MaxValue; if (calendar == null) calendar = CultureInfo.CurrentCulture.Calendar; // Set the time to this second (or the next one if not inclusive), remove fractions of a second. dateTime = new DateTime( dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second); if (!inclusive) dateTime = calendar.AddSeconds(dateTime, 1); // Every second case. if ((month == Month.Every) && (day == Day.Every) && (weekDay == WeekDay.Every) && (hour == Hour.Every) && (minute == Minute.Every) && (second == Second.Every) && (week == Week.Every)) return calendar.AddSeconds(dateTime, 1); // Get days and months. IEnumerable<int> days = day.Days().OrderBy(dy => dy); IEnumerable<int> months = month.Months(); // Remove months where the first day isn't in the month. int firstDay = days.First(); if (firstDay > 28) { // 2000 is a leap year, so February has 29 days. months = months.Where(mn => calendar.GetDaysInMonth(2000, mn) >= firstDay); if (months.Count() < 1) return DateTime.MaxValue; } // Get remaining date components. int y = calendar.GetYear(dateTime); int m = calendar.GetMonth(dateTime); int d = calendar.GetDayOfMonth(dateTime); int h = calendar.GetHour(dateTime); int n = calendar.GetMinute(dateTime); int s = calendar.GetSecond(dateTime); IEnumerable<int> weeks = week.Weeks(); IEnumerable<DayOfWeek> weekDays = weekDay.WeekDays(); IEnumerable<int> hours = hour.Hours().OrderBy(i => i); IEnumerable<int> minutes = minute.Minutes().OrderBy(i => i); IEnumerable<int> seconds = second.Seconds(); do { foreach (int currentMonth in months) { if (currentMonth < m) continue; if (currentMonth > m) { d = 1; h = n = s = 0; } m = currentMonth; foreach (int currentDay in days) { if (currentDay < d) continue; if (currentDay > d) h = n = s = 0; d = currentDay; // Check day is valid for this month. if ((d > 28) && (d > calendar.GetDaysInMonth(y, m))) break; // We have a potential day, check week and week day dateTime = new DateTime(y, m, d, h, n, s); if ((week != Week.Every) && (!weeks.Contains(dateTime.WeekNumber(calendar, calendarWeekRule, firstDayOfWeek)))) continue; if ((weekDay != WeekDay.Every) && (!weekDays.Contains(calendar.GetDayOfWeek(dateTime)))) continue; // We have a date match, check time. foreach (int currentHour in hours) { if (currentHour < h) continue; if (currentHour > h) n = s = 0; h = currentHour; foreach (int currentMinute in minutes) { if (currentMinute < n) continue; if (currentMinute > n) s = 0; n = currentMinute; foreach (int currentSecond in seconds) { if (currentSecond < s) continue; return new DateTime(y, m, d, h, n, currentSecond, calendar); } n = s = 0; } h = n = s = 0; } d = 1; } d = 1; h = n = s = 0; } y++; // Don't bother checking max year. if (y > 9998) return DateTime.MaxValue; // Start next year m = d = 1; h = n = s = 0; } while (true); }