Beispiel #1
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        /// <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);
        }