<commit_before>#region License and Terms
//
// NCrontab - Crontab for .NET
// Copyright (c) 2008 <NAME>. All rights reserved.
// Portions Copyright (c) 2001 The OpenSymphony Group. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion

namespace NCrontab
{
    #region Imports

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using Debug = System.Diagnostics.Debug;

    #endregion

    /// <summary>
    /// Represents a schedule initialized from the crontab expression.
    /// </summary>

    // ReSharper disable once PartialTypeWithSinglePart

    public sealed partial class CrontabSchedule
    {
        readonly CrontabField _seconds;
        readonly CrontabField _minutes;
        readonly CrontabField _hours;
        readonly CrontabField _days;
        readonly CrontabField _months;
        readonly CrontabField _daysOfWeek;

        static readonly CrontabField SecondZero = CrontabField.Seconds("0");

        // ReSharper disable once PartialTypeWithSinglePart

        public sealed partial class ParseOptions
        {
            public bool IncludingSeconds { get; set; }
        }

        //
        // Crontab expression format:
        //
        // * * * * *
        // - - - - -
        // | | | | |
        // | | | | +----- day of week (0 - 6) (Sunday=0)
        // | | | +------- month (1 - 12)
        // | | +--------- day of month (1 - 31)
        // | +----------- hour (0 - 23)
        // +------------- min (0 - 59)
        //
        // Star (*) in the value field above means all legal values as in
        // braces for that column. The value column can have a * or a list
        // of elements separated by commas. An element is either a number in
        // the ranges shown above or two numbers in the range separated by a
        // hyphen (meaning an inclusive range).
        //
        // Source: http://www.adminschoice.com/docs/crontab.htm
        //

        // Six-part expression format:
        //
        // * * * * * *
        // - - - - - -
        // | | | | | |
        // | | | | | +--- day of week (0 - 6) (Sunday=0)
        // | | | | +----- month (1 - 12)
        // | | | +------- day of month (1 - 31)
        // | | +--------- hour (0 - 23)
        // | +----------- min (0 - 59)
        // +------------- sec (0 - 59)
        //
        // The six-part expression behaves similarly to the traditional
        // crontab format except that it can denotate more precise schedules
        // that use a seconds component.
        //

        public static CrontabSchedule Parse(string expression) => Parse(expression, null);

        public static CrontabSchedule Parse(string expression, ParseOptions? options) =>
            TryParse(expression, options, v => v, e => throw e());

        public static CrontabSchedule? TryParse(string expression) => TryParse(expression, null);

        public static CrontabSchedule? TryParse(string expression, ParseOptions? options) =>
            TryParse(expression ?? string.Empty, options, v => v, _ => (CrontabSchedule?)null);

        public static T TryParse<T>(string expression,
                                    Func<CrontabSchedule, T> valueSelector,
                                    Func<ExceptionProvider, T> errorSelector) =>
            TryParse(expression ?? string.Empty, null, valueSelector, errorSelector);

        public static T TryParse<T>(string expression, ParseOptions? options, Func<CrontabSchedule, T> valueSelector, Func<ExceptionProvider, T> errorSelector)
        {
            if (expression == null) throw new ArgumentNullException(nameof(expression));

            var tokens = expression.Split(StringSeparatorStock.Space, StringSplitOptions.RemoveEmptyEntries);

            var includingSeconds = options != null && options.IncludingSeconds;
            var expectedTokenCount = includingSeconds ? 6 : 5;
            if (tokens.Length < expectedTokenCount || tokens.Length > expectedTokenCount)
            {
                return errorSelector(() =>
                {
                    var components =
                        includingSeconds
                        ? "6 components of a schedule in the sequence of seconds, minutes, hours, days, months, and days of week"
                        : "5 components of a schedule in the sequence of minutes, hours, days, months, and days of week";
                    return new CrontabException($"'{expression}' is an invalid crontab expression. It must contain {components}.");
                });
            }

            var fields = new CrontabField[6];

            var offset = includingSeconds ? 0 : 1;
            for (var i = 0; i < tokens.Length; i++)
            {
                var kind = (CrontabFieldKind)i + offset;
                var field = CrontabField.TryParse(kind, tokens[i], v => new { ErrorProvider = (ExceptionProvider?)null, Value = (CrontabField?)v    },
                                                                   e => new { ErrorProvider = (ExceptionProvider?)e   , Value = (CrontabField?)null }) ;

                if (field.ErrorProvider != null)
                    return errorSelector(field.ErrorProvider);
                fields[i + offset] = field.Value!; // non-null by mutual exclusivity!
            }

            return valueSelector(new CrontabSchedule(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5]));
        }

        CrontabSchedule(
            CrontabField seconds,
            CrontabField minutes, CrontabField hours,
            CrontabField days, CrontabField months,
            CrontabField daysOfWeek)
        {
            _seconds = seconds;
            _minutes = minutes;
            _hours = hours;
            _days = days;
            _months = months;
            _daysOfWeek = daysOfWeek;
        }

        /// <summary>
        /// Enumerates all the occurrences of this schedule starting with a
        /// base time and up to an end time limit. This method uses deferred
        /// execution such that the occurrences are only calculated as they
        /// are enumerated.<commit_msg>Fix nullability of second field of schedule<commit_after>#region License and Terms
//
// NCrontab - Crontab for .NET
// Copyright (c) 2008 <NAME>. All rights reserved.
// Portions Copyright (c) 2001 The OpenSymphony Group. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#endregion

namespace NCrontab
{
    #region Imports

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using Debug = System.Diagnostics.Debug;

    #endregion

    /// <summary>
    /// Represents a schedule initialized from the crontab expression.
    /// </summary>

    // ReSharper disable once PartialTypeWithSinglePart

    public sealed partial class CrontabSchedule
    {
        readonly CrontabField? _seconds;
        readonly CrontabField _minutes;
        readonly CrontabField _hours;
        readonly CrontabField _days;
        readonly CrontabField _months;
        readonly CrontabField _daysOfWeek;

        static readonly CrontabField SecondZero = CrontabField.Seconds("0");

        // ReSharper disable once PartialTypeWithSinglePart

        public sealed partial class ParseOptions
        {
            public bool IncludingSeconds { get; set; }
        }

        //
        // Crontab expression format:
        //
        // * * * * *
        // - - - - -
        // | | | | |
        // | | | | +----- day of week (0 - 6) (Sunday=0)
        // | | | +------- month (1 - 12)
        // | | +--------- day of month (1 - 31)
        // | +----------- hour (0 - 23)
        // +------------- min (0 - 59)
        //
        // Star (*) in the value field above means all legal values as in
        // braces for that column. The value column can have a * or a list
        // of elements separated by commas. An element is either a number in
        // the ranges shown above or two numbers in the range separated by a
        // hyphen (meaning an inclusive range).
        //
        // Source: http://www.adminschoice.com/docs/crontab.htm
        //

        // Six-part expression format:
        //
        // * * * * * *
        // - - - - - -
        // | | | | | |
        // | | | | | +--- day of week (0 - 6) (Sunday=0)
        // | | | | +----- month (1 - 12)
        // | | | +------- day of month (1 - 31)
        // | | +--------- hour (0 - 23)
        // | +----------- min (0 - 59)
        // +------------- sec (0 - 59)
        //
        // The six-part expression behaves similarly to the traditional
        // crontab format except that it can denotate more precise schedules
        // that use a seconds component.
        //

        public static CrontabSchedule Parse(string expression) => Parse(expression, null);

        public static CrontabSchedule Parse(string expression, ParseOptions? options) =>
            TryParse(expression, options, v => v, e => throw e());

        public static CrontabSchedule? TryParse(string expression) => TryParse(expression, null);

        public static CrontabSchedule? TryParse(string expression, ParseOptions? options) =>
            TryParse(expression ?? string.Empty, options, v => v, _ => (CrontabSchedule?)null);

        public static T TryParse<T>(string expression,
                                    Func<CrontabSchedule, T> valueSelector,
                                    Func<ExceptionProvider, T> errorSelector) =>
            TryParse(expression ?? string.Empty, null, valueSelector, errorSelector);

        public static T TryParse<T>(string expression, ParseOptions? options, Func<CrontabSchedule, T> valueSelector, Func<ExceptionProvider, T> errorSelector)
        {
            if (expression == null) throw new ArgumentNullException(nameof(expression));

            var tokens = expression.Split(StringSeparatorStock.Space, StringSplitOptions.RemoveEmptyEntries);

            var includingSeconds = options != null && options.IncludingSeconds;
            var expectedTokenCount = includingSeconds ? 6 : 5;
            if (tokens.Length < expectedTokenCount || tokens.Length > expectedTokenCount)
            {
                return errorSelector(() =>
                {
                    var components =
                        includingSeconds
                        ? "6 components of a schedule in the sequence of seconds, minutes, hours, days, months, and days of week"
                        : "5 components of a schedule in the sequence of minutes, hours, days, months, and days of week";
                    return new CrontabException($"'{expression}' is an invalid crontab expression. It must contain {components}.");
                });
            }

            var fields = new CrontabField[6];

            var offset = includingSeconds ? 0 : 1;
            for (var i = 0; i < tokens.Length; i++)
            {
                var kind = (CrontabFieldKind)i + offset;
                var field = CrontabField.TryParse(kind, tokens[i], v => new { ErrorProvider = (ExceptionProvider?)null, Value = (CrontabField?)v    },
                                                                   e => new { ErrorProvider = (ExceptionProvider?)e   , Value = (CrontabField?)null }) ;

                if (field.ErrorProvider != null)
                    return errorSelector(field.ErrorProvider);
                fields[i + offset] = field.Value!; // non-null by mutual exclusivity!
            }

            return valueSelector(new CrontabSchedule(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5]));
        }

        CrontabSchedule(
            CrontabField? seconds,
            CrontabField minutes, CrontabField hours,
            CrontabField days, CrontabField months,
            CrontabField daysOfWeek)
        {
            _seconds = seconds;
            _minutes = minutes;
            _hours = hours;
            _days = days;
            _months = months;
            _daysOfWeek = daysOfWeek;
        }

        /// <summary>
        /// Enumerates all the occurrences of this schedule starting with a
        /// base time and up to an end time limit. This method uses deferred
        /// execution such that the occurrences are only calculated as they
        /// are enumerated.
{'fraction_non_alphanumeric': 0.11087897328756902, 'fraction_numerical': 0.008953887479480675, 'mean_word_length': 1.7928735153156907, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2854895', 'n_tokens_mistral': 3499, 'n_tokens_neox': 3304, 'n_words': 1143}