public static Instant NextValid( this Instant instant, 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, [CanBeNull] CalendarSystem calendarSystem = null, [CanBeNull] DateTimeZone timeZone = null) { // 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 Instant.MaxValue; if (calendarSystem == null) calendarSystem = CalendarSystem.Iso; if (timeZone == null) timeZone = DateTimeZone.Utc; Debug.Assert(calendarSystem != null); Debug.Assert(timeZone != null); // Move to next second. instant = instant.CeilingSecond(); // 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 instant; // Get days and months. int[] days = Days(day).OrderBy(dy => dy).ToArray(); int[] months = month.Months().ToArray(); // 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 => calendarSystem.GetDaysInMonth(2000, mn) >= firstDay).ToArray(); if (months.Length < 1) return Instant.MaxValue; } // Get zoned date time. ZonedDateTime zdt = new ZonedDateTime(instant, timeZone, calendarSystem); int y = zdt.Year; int m = zdt.Month; int d = zdt.Day; int h = zdt.Hour; int n = zdt.Minute; int s = zdt.Second; int[] weeks = week.Weeks().ToArray(); IsoDayOfWeek[] weekDays = weekDay.WeekDays().ToArray(); int[] hours = hour.Hours().OrderBy(i => i).ToArray(); int[] minutes = minute.Minutes().OrderBy(i => i).ToArray(); int[] seconds = second.Seconds().ToArray(); 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 > calendarSystem.GetDaysInMonth(y, m)) break; // We have a potential day, check week and week day zdt = timeZone.AtLeniently(new LocalDateTime(y, m, d, h, n, s, calendarSystem)); if ((week != Week.Every) && (!weeks.Contains(zdt.WeekOfWeekYear))) continue; if ((weekDay != WeekDay.Every) && (!weekDays.Contains(zdt.IsoDayOfWeek))) 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 timeZone.AtLeniently( new LocalDateTime(y, m, d, h, n, currentSecond, calendarSystem)).ToInstant(); } n = s = 0; } h = n = s = 0; } d = 1; } d = 1; h = n = s = 0; } y++; // Don't bother checking max year. if (y >= calendarSystem.MaxYear) return Instant.MaxValue; // Start next year m = d = 1; h = n = s = 0; } while (true); }
/// <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); }
public static Instant NextValid( this Instant instant, 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, [CanBeNull] CalendarSystem calendarSystem = null, [CanBeNull] DateTimeZone timeZone = null) { // 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(Instant.MaxValue); } if (calendarSystem == null) { calendarSystem = CalendarSystem.Iso; } if (timeZone == null) { timeZone = DateTimeZone.Utc; } Debug.Assert(calendarSystem != null); Debug.Assert(timeZone != null); // Move to next second. instant = instant.CeilingSecond(); // 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(instant); } // Get days and months. int[] days = Days(day).OrderBy(dy => dy).ToArray(); int[] months = month.Months().ToArray(); // 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 => calendarSystem.GetDaysInMonth(2000, mn) >= firstDay).ToArray(); if (months.Length < 1) { return(Instant.MaxValue); } } // Get zoned date time. ZonedDateTime zdt = new ZonedDateTime(instant, timeZone, calendarSystem); int y = zdt.Year; int m = zdt.Month; int d = zdt.Day; int h = zdt.Hour; int n = zdt.Minute; int s = zdt.Second; int[] weeks = week.Weeks().ToArray(); IsoDayOfWeek[] weekDays = weekDay.WeekDays().ToArray(); int[] hours = hour.Hours().OrderBy(i => i).ToArray(); int[] minutes = minute.Minutes().OrderBy(i => i).ToArray(); int[] seconds = second.Seconds().ToArray(); 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 > calendarSystem.GetDaysInMonth(y, m)) { break; } // We have a potential day, check week and week day zdt = timeZone.AtLeniently(new LocalDateTime(y, m, d, h, n, s, calendarSystem)); if ((week != Week.Every) && (!weeks.Contains(zdt.WeekOfWeekYear))) { continue; } if ((weekDay != WeekDay.Every) && (!weekDays.Contains(zdt.IsoDayOfWeek))) { 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 (timeZone.AtLeniently( new LocalDateTime(y, m, d, h, n, currentSecond, calendarSystem)).ToInstant()); } n = s = 0; } h = n = s = 0; } d = 1; } d = 1; h = n = s = 0; } y++; // Don't bother checking max year. if (y >= calendarSystem.MaxYear) { return(Instant.MaxValue); } // Start next year m = d = 1; h = n = s = 0; } while (true); }
/// <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); }