Re[2]: Просидев на одном предприятии несколько лет...
От: mgu  
Дата: 10.08.21 02:03
Оценка: +1 -1 :)
Здравствуйте, B0FEE664, Вы писали:

vaa>>3. почему-то все крутые прогеры пока только накидывают критики, но никто не показал образцовое решение.

BFE>Какой самобытный код!
BFE>Я очарован этим кодом.
BFE>
  Опасно! Не для слабых умов. При чтении можно заработать вывих мозга:
BFE>
BFE>using System;

BFE>namespace TestApp
BFE>{
BFE>    /// <summary>
BFE>    /// Класс для задания и расчета времени по расписанию.
BFE>    /// </summary>
BFE>    public class Schedule
BFE>    {
BFE>        private const string _placeholder = "*"; // Звездочка означает любое возможное значение.
BFE>        private const string _defaultMilliseconds = "0"; // fff - миллисекунды (0-999). Если не указаны, то 0

BFE>        internal readonly byte[] _years =        new byte[101]; // год (2000-2100)
BFE>        internal readonly byte[] _months =       new byte[12]; // месяц (1-12)
BFE>        internal readonly byte[] _days =         new byte[32]; // число месяца (1-31 или 32)
BFE>        internal readonly byte[] _weekDays =     new byte[7]; // день недели (0-6)
BFE>        internal readonly byte[] _hours =        new byte[24]; // часы (0-23)
BFE>        internal readonly byte[] _minutes =      new byte[60]; // минуты (0-59)
BFE>        internal readonly byte[] _seconds =      new byte[60]; // секунды (0-59)
BFE>        internal readonly byte[] _milliseconds = new byte[1000]; // миллисекунды (0-999)

BFE>        /// <summary>
BFE>        /// Создает пустой экземпляр, который будет соответствовать
BFE>        /// расписанию типа "*.*.* * *:*:*.*" (раз в 1 мс).
BFE>        /// </summary>
BFE>        public Schedule ()
BFE>            : this ("*.*.* * *:*:*.*")
BFE>        {
BFE>        }

BFE>        /// <summary>
BFE>        /// Создает экземпляр из строки с представлением расписания.
BFE>        /// </summary>
BFE>        /// <param name="scheduleString">Строка расписания.
BFE>        /// Формат строки:
BFE>        ///     yyyy.MM.dd w HH:mm:ss.fff
BFE>        ///     yyyy.MM.dd HH:mm:ss.fff
BFE>        ///     HH:mm:ss.fff
BFE>        ///     yyyy.MM.dd w HH:mm:ss
BFE>        ///     yyyy.MM.dd HH:mm:ss
BFE>        ///     HH:mm:ss
BFE>        /// Где yyyy - год (2000-2100)
BFE>        ///     MM - месяц (1-12)
BFE>        ///     dd - число месяца (1-31 или 32). 32 означает последнее число месяца
BFE>        ///     w - день недели (0-6). 0 - воскресенье, 6 - суббота
BFE>        ///     HH - часы (0-23)
BFE>        ///     mm - минуты (0-59)
BFE>        ///     ss - секунды (0-59)
BFE>        ///     fff - миллисекунды (0-999). Если не указаны, то 0
BFE>        /// Каждую часть даты/времени можно задавать в виде списков и диапазонов.
BFE>        /// Например:
BFE>        ///     1,2,3-5,10-20/3
BFE>        ///     означает список 1,2,3,4,5,10,13,16,19
BFE>        /// Дробью задается шаг в списке.
BFE>        /// Звездочка означает любое возможное значение.
BFE>        /// Например (для часов):
BFE>        ///     */4
BFE>        ///     означает 0,4,8,12,16,20
BFE>        /// Вместо списка чисел месяца можно указать 32. Это означает последнее
BFE>        /// число любого месяца.
BFE>        /// Пример:
BFE>        ///     *.9.*/2 1-5 10:00:00.000
BFE>        ///     означает 10:00 во все дни с пн. по пт. по нечетным числам в сентябре
BFE>        ///     *:00:00
BFE>        ///     означает начало любого часа
BFE>        ///     *.*.01 01:30:00
BFE>        ///     означает 01:30 по первым числам каждого месяца
BFE>        /// </param>
BFE>        public Schedule (string scheduleString)
BFE>        {
BFE>            // конструктор большой по объёму исходника, но выполняет лишь простейшие действия и не выделяет память
BFE>            if (scheduleString == null)
BFE>            {
BFE>                throw new ArgumentNullException (nameof (scheduleString));
BFE>            }

BFE>            var dotPosition1 = scheduleString.IndexOf ('.');
BFE>            var dotPosition2 = (dotPosition1 < 0) ?
BFE>                -1 :
BFE>                scheduleString.IndexOf ('.', dotPosition1 + 1);
BFE>            var dotPosition3 = (dotPosition2 < 0) ?
BFE>                -1 :
BFE>                scheduleString.IndexOf ('.', dotPosition2 + 1);
BFE>            var colonPosition1 = scheduleString.IndexOf (':');
BFE>            var colonPosition2 = (colonPosition1 < 0) ?
BFE>                -1 :
BFE>                scheduleString.IndexOf (':', colonPosition1 + 1);
BFE>            if (colonPosition2 < 0)
BFE>            {
BFE>                // два двоеточия есть во всех форматах
BFE>                throw new FormatException ();
BFE>            }
BFE>            var spacePosition1 = scheduleString.IndexOf (' ');
BFE>            var spacePosition2 = (spacePosition1 < 0) ?
BFE>                -1 :
BFE>                scheduleString.IndexOf (' ', spacePosition1 + 1);

BFE>            ReadOnlySpan<char> yearPart;
BFE>            ReadOnlySpan<char> monthPart;
BFE>            ReadOnlySpan<char> dayPart;
BFE>            ReadOnlySpan<char> weekDayPart;
BFE>            ReadOnlySpan<char> hourPart;
BFE>            ReadOnlySpan<char> minutePart;
BFE>            ReadOnlySpan<char> secondPart;
BFE>            ReadOnlySpan<char> millisecondPart;
BFE>            if (
BFE>                (dotPosition1 >= 0) &&
BFE>                (dotPosition2 >= 0) &&
BFE>                (dotPosition3 >= 0) &&
BFE>                (colonPosition1 > dotPosition2) &&
BFE>                (dotPosition3 > colonPosition2))
BFE>            {
BFE>                // yyyy.MM.dd w HH:mm:ss.fff  или  yyyy.MM.dd HH:mm:ss.fff
BFE>                yearPart = scheduleString.AsSpan (0, dotPosition1);
BFE>                monthPart = scheduleString.AsSpan (dotPosition1 + 1, dotPosition2 - dotPosition1 - 1);
BFE>                dayPart = scheduleString.AsSpan (dotPosition2 + 1, spacePosition1 - dotPosition2 - 1);
BFE>                weekDayPart = (spacePosition2 < 0) ?
BFE>                    _placeholder :
BFE>                    scheduleString.AsSpan (spacePosition1 + 1, spacePosition2 - spacePosition1 - 1);
BFE>                hourPart = (spacePosition2 < 0) ?
BFE>                    scheduleString.AsSpan (spacePosition1 + 1, colonPosition1 - spacePosition1 - 1) :
BFE>                    scheduleString.AsSpan (spacePosition2 + 1, colonPosition1 - spacePosition2 - 1);
BFE>                minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>                secondPart = scheduleString.AsSpan (colonPosition2 + 1, dotPosition3 - colonPosition2 - 1);
BFE>                millisecondPart = scheduleString.AsSpan (dotPosition3 + 1);
BFE>            }
BFE>            else
BFE>            {
BFE>                if (
BFE>                    (dotPosition1 >= 0) &&
BFE>                    (dotPosition2 >= 0) &&
BFE>                    (dotPosition3 < 0) &&
BFE>                    (colonPosition1 > dotPosition2))
BFE>                {
BFE>                    // yyyy.MM.dd w HH:mm:ss  или  yyyy.MM.dd HH:mm:ss
BFE>                    yearPart = scheduleString.AsSpan (0, dotPosition1);
BFE>                    monthPart = scheduleString.AsSpan (dotPosition1 + 1, dotPosition2 - dotPosition1 - 1);
BFE>                    dayPart = scheduleString.AsSpan (dotPosition2 + 1, spacePosition1 - dotPosition2 - 1);
BFE>                    weekDayPart = (spacePosition2 < 0) ?
BFE>                        _placeholder :
BFE>                        scheduleString.AsSpan (spacePosition1 + 1, spacePosition2 - spacePosition1 - 1);
BFE>                    hourPart = (spacePosition2 < 0) ?
BFE>                        scheduleString.AsSpan (spacePosition1 + 1, colonPosition1 - spacePosition1 - 1) :
BFE>                        scheduleString.AsSpan (spacePosition2 + 1, colonPosition1 - spacePosition2 - 1);
BFE>                    minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>                    secondPart = scheduleString.AsSpan (colonPosition2 + 1);
BFE>                    millisecondPart = _defaultMilliseconds;
BFE>                }
BFE>                else
BFE>                {
BFE>                    if (
BFE>                        (dotPosition1 >= 0) &&
BFE>                        (dotPosition2 < 0) &&
BFE>                        (colonPosition2 < dotPosition1))
BFE>                    {
BFE>                        // HH:mm:ss.fff
BFE>                        yearPart = _placeholder;
BFE>                        monthPart = _placeholder;
BFE>                        dayPart = _placeholder;
BFE>                        weekDayPart = _placeholder;
BFE>                        hourPart = scheduleString.AsSpan (0, colonPosition1);
BFE>                        minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>                        secondPart = scheduleString.AsSpan (colonPosition2 + 1, dotPosition1 - colonPosition2 - 1);
BFE>                        millisecondPart = scheduleString.AsSpan (dotPosition1 + 1);
BFE>                    }
BFE>                    else
BFE>                    {
BFE>                        if (dotPosition1 < 0)
BFE>                        {
BFE>                            // HH:mm:ss
BFE>                            yearPart = _placeholder;
BFE>                            monthPart = _placeholder;
BFE>                            dayPart = _placeholder;
BFE>                            weekDayPart = _placeholder;
BFE>                            hourPart = scheduleString.AsSpan (0, colonPosition1);
BFE>                            minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>                            secondPart = scheduleString.AsSpan (colonPosition2 + 1);
BFE>                            millisecondPart = _defaultMilliseconds;
BFE>                        }
BFE>                        else
BFE>                        {
BFE>                            throw new FormatException ("Unrecognized schedule.");
BFE>                        }
BFE>                    }
BFE>                }
BFE>            }

BFE>            ParsePart (yearPart,        _years,        2000);
BFE>            ParsePart (monthPart,       _months,       1);
BFE>            ParsePart (dayPart,         _days,         1);
BFE>            ParsePart (weekDayPart,     _weekDays,     0);
BFE>            ParsePart (hourPart,        _hours,        0);
BFE>            ParsePart (minutePart,      _minutes,      0);
BFE>            ParsePart (secondPart,      _seconds,      0);
BFE>            ParsePart (millisecondPart, _milliseconds, 0);
BFE>        }

BFE>        /// <summary>
BFE>        /// Возвращает следующий ближайший к заданному времени момент в расписании или
BFE>        /// само заданное время, если оно есть в расписании.
BFE>        /// </summary>
BFE>        /// <param name="t1">Заданное время</param>
BFE>        /// <returns>Ближайший момент времени в расписании</returns>
BFE>        public DateTime NearestEvent(DateTime t1)
BFE>        {
BFE>            // цикл проверки каждый раз после корректировки времени, макс. кол-во итераций: 100 + 11 + 31 + 23 + 59 + 59 = 283
BFE>            while (true)
BFE>            {
BFE>                var yearOffset = t1.Year - 2000;
BFE>                if ((yearOffset < 0) || (yearOffset >= _years.Length))
BFE>                {
BFE>                    throw new InvalidOperationException ("Year out of range");
BFE>                }

BFE>                if (_years[yearOffset] > 0)
BFE>                {
BFE>                    if (_months[t1.Month - 1] > 0)
BFE>                    {
BFE>                        var isLastDayInMonth = t1.Day == DateTime.DaysInMonth (t1.Year, t1.Month);
BFE>                        // 32-й день означает последнее число месяца
BFE>                        if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
BFE>                        {
BFE>                            if (_hours[t1.Hour] > 0)
BFE>                            {
BFE>                                if (_minutes[t1.Minute] > 0)
BFE>                                {
BFE>                                    if (_seconds[t1.Second] > 0)
BFE>                                    {
BFE>                                        var millisecond = t1.Millisecond;
BFE>                                        do
BFE>                                        {
BFE>                                            if (_milliseconds[millisecond] > 0)
BFE>                                            {
BFE>                                                return new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second, millisecond);
BFE>                                            }

BFE>                                            millisecond++;
BFE>                                        } while (millisecond < _milliseconds.Length);
BFE>                                    }
BFE>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second).AddSeconds (1);
BFE>                                }
BFE>                                else
BFE>                                {
BFE>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, 0).AddMinutes (1);
BFE>                                }
BFE>                            }
BFE>                            else
BFE>                            {
BFE>                                t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, 0, 0).AddHours (1);
BFE>                            }
BFE>                        }
BFE>                        else
BFE>                        {
BFE>                            t1 = new DateTime (t1.Year, t1.Month, t1.Day).AddDays (1);
BFE>                        }
BFE>                    }
BFE>                    else
BFE>                    {
BFE>                        t1 = new DateTime (t1.Year, t1.Month, 1).AddMonths (1);
BFE>                    }
BFE>                }
BFE>                else
BFE>                {
BFE>                    t1 = new DateTime (t1.Year, 1, 1).AddYears (1);
BFE>                }
BFE>            }
BFE>        }

BFE>        /// <summary>
BFE>        /// Возвращает предыдущий ближайший к заданному времени момент в расписании или
BFE>        /// само заданное время, если оно есть в расписании.
BFE>        /// </summary>
BFE>        /// <param name="t1">Заданное время</param>
BFE>        /// <returns>Ближайший момент времени в расписании</returns>
BFE>        public DateTime NearestPrevEvent(DateTime t1)
BFE>        {
BFE>            // цикл проверки каждый раз после корректировки времени, макс. кол-во итераций: 100 + 11 + 31 + 23 + 59 + 59 = 283
BFE>            while (true)
BFE>            {
BFE>                var yearOffset = t1.Year - 2000;
BFE>                if ((yearOffset < 0) || (yearOffset >= _years.Length))
BFE>                {
BFE>                    throw new InvalidOperationException ("Year out of range");
BFE>                }

BFE>                if (_years[yearOffset] > 0)
BFE>                {
BFE>                    if (_months[t1.Month - 1] > 0)
BFE>                    {
BFE>                        var isLastDayInMonth = t1.Day == DateTime.DaysInMonth (t1.Year, t1.Month);
BFE>                        // 32-й день означает последнее число месяца
BFE>                        if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
BFE>                        {
BFE>                            if (_hours[t1.Hour] > 0)
BFE>                            {
BFE>                                if (_minutes[t1.Minute] > 0)
BFE>                                {
BFE>                                    if (_seconds[t1.Second] > 0)
BFE>                                    {
BFE>                                        var millisecond = t1.Millisecond;
BFE>                                        do
BFE>                                        {
BFE>                                            if (_milliseconds[millisecond] > 0)
BFE>                                            {
BFE>                                                return new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second, millisecond);
BFE>                                            }

BFE>                                            millisecond--;
BFE>                                        } while (millisecond >= 0);
BFE>                                    }
BFE>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second).AddMilliseconds (-1);
BFE>                                }
BFE>                                else
BFE>                                {
BFE>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, 0).AddMilliseconds (-1);
BFE>                                }
BFE>                            }
BFE>                            else
BFE>                            {
BFE>                                t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, 0, 0).AddMilliseconds (-1);
BFE>                            }
BFE>                        }
BFE>                        else
BFE>                        {
BFE>                            t1 = new DateTime (t1.Year, t1.Month, t1.Day).AddMilliseconds (-1);
BFE>                        }
BFE>                    }
BFE>                    else
BFE>                    {
BFE>                        t1 = new DateTime (t1.Year, t1.Month, 1).AddMilliseconds (-1);
BFE>                    }
BFE>                }
BFE>                else
BFE>                {
BFE>                    t1 = new DateTime (t1.Year, 1, 1).AddMilliseconds (-1);
BFE>                }
BFE>            }
BFE>        }

BFE>        /// <summary>
BFE>        /// Возвращает следующий момент времени в расписании.
BFE>        /// </summary>
BFE>        /// <param name="t1">Время, от которого нужно отступить</param>
BFE>        /// <returns>Следующий момент времени в расписании</returns>
BFE>        public DateTime NextEvent(DateTime t1)
BFE>        {
BFE>            return NearestEvent (t1.AddMilliseconds (1));
BFE>        }

BFE>        /// <summary>
BFE>        /// Возвращает предыдущий момент времени в расписании.
BFE>        /// </summary>
BFE>        /// <param name="t1">Время, от которого нужно отступить</param>
BFE>        /// <returns>Предыдущий момент времени в расписании</returns>
BFE>        public DateTime PrevEvent(DateTime t1)
BFE>        {
BFE>            return NearestPrevEvent (t1.AddMilliseconds (-1));
BFE>        }

BFE>        /// <summary>
BFE>        /// Заполняет указанный массив ненулевыми значениями для тех индексов, которые указаны в partStr.
BFE>        /// </summary>
BFE>        /// <param name="partStr">Текстовый список диапазонов.</param>
BFE>        /// <param name="allowedValues">Массив, в котором будут отмечены ненулевым значением указанные в partStr числа.</param>
BFE>        /// <param name="offset">Смещение, которое будет вычитаться для всех чисел, указанных в partStr.</param>
BFE>        private static void ParsePart (ReadOnlySpan<char> partStr, byte[] allowedValues, int offset)
BFE>        {
BFE>            // Каждую часть даты/времени можно задавать в виде списков и диапазонов.
BFE>            // Например:
BFE>            //     1,2,3-5,10-20/3
BFE>            //     означает список 1,2,3,4,5,10,13,16,19
BFE>            // Дробью задается шаг в списке.
BFE>            // Звездочка означает любое возможное значение.

BFE>            if (partStr.Length < 1)
BFE>            {
BFE>                throw new FormatException ("Invalid part");
BFE>            }

BFE>            var idx = 0;
BFE>            while (idx < partStr.Length)
BFE>            {
BFE>                int number1;
BFE>                int number2;
BFE>                if (partStr[idx] == '*')
BFE>                {
BFE>                    idx++;
BFE>                    number1 = 0;
BFE>                    number2 = allowedValues.Length - 1;
BFE>                }
BFE>                else
BFE>                {
BFE>                    number1 = ParseNumber (partStr, ref idx) - offset;
BFE>                    if ((number1 < 0) || (number1 >= allowedValues.Length))
BFE>                    {
BFE>                        throw new FormatException ("Number out of range.");
BFE>                    }

BFE>                    number2 = number1;
BFE>                    if ((idx < partStr.Length) && (partStr[idx] == '-'))
BFE>                    {
BFE>                        idx++;
BFE>                        number2 = ParseNumber (partStr, ref idx) - offset;
BFE>                        if ((number2 < 0) || (number2 >= allowedValues.Length))
BFE>                        {
BFE>                            throw new FormatException ("Number out of range.");
BFE>                        }
BFE>                    }
BFE>                }

BFE>                var period = 1;
BFE>                if (idx < partStr.Length)
BFE>                {
BFE>                    switch (partStr[idx])
BFE>                    {
BFE>                        case '/':
BFE>                            idx++;
BFE>                            period = ParseNumber (partStr, ref idx);
BFE>                            break;
BFE>                        case ',':
BFE>                            idx++;
BFE>                            break;
BFE>                        default:
BFE>                            throw new FormatException ("Invalid character.");
BFE>                    }
BFE>                }

BFE>                for (var i = number1; i <= number2; i += period)
BFE>                {
BFE>                    allowedValues[i] = 1;
BFE>                }
BFE>            }
BFE>        }

BFE>        // возвращает число, полученное из текстового представленая в partStr начиная с индекса в idx
BFE>        private static int ParseNumber (ReadOnlySpan<char> partStr, ref int idx)
BFE>        {
BFE>            var number = 0;
BFE>            while ((idx < partStr.Length) && (partStr[idx] >= '0') && (partStr[idx] <= '9'))
BFE>            {
BFE>                number = 10 * number + partStr[idx] - '0';
BFE>                idx++;
BFE>            }

BFE>            return number;
BFE>        }
BFE>    }
BFE>}
BFE>



Какой вывих мозга? Всё же совершенно очевидно:
     // 32-й день означает последнее число месяца


Все возмущаются вложенностью условий... Да этот господин и одно-то условие не может написать толком:

    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))


Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.
Re[3]: Просидев на одном предприятии несколько лет...
От: Doom100500 Израиль  
Дата: 10.08.21 05:15
Оценка: +4
Здравствуйте, mgu, Вы писали:

mgu>
mgu>    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
mgu>


mgu>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.


Это не математические, а логические оперзции. В школе их не изучают (по крайней мере не во втором классе).
А ставить скобки для удобочтаемости — это нормально.
Спасибо за внимание
Re[3]: Просидев на одном предприятии несколько лет...
От: AlexMld Россия  
Дата: 10.08.21 07:34
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>А что не так, ты бы по-другому сделал? Вроде бы все верно, или нет?

bnk>Альтернатива — задавать интервалами, но это неэффективно.

Я, видимо, не внимательно условия задачи прочитал. В принципе, да, можно так.
Re[3]: Просидев на одном предприятии несколько лет...
От: B0FEE664  
Дата: 10.08.21 11:34
Оценка:
Здравствуйте, mgu, Вы писали:

mgu>Здравствуйте, B0FEE664, Вы писали:


vaa>>>3. почему-то все крутые прогеры пока только накидывают критики, но никто не показал образцовое решение.

BFE>>Какой самобытный код!
BFE>>Я очарован этим кодом.
BFE>>
  Опасно! Не для слабых умов. При чтении можно заработать вывих мозга:
BFE>>
BFE>>using System;

BFE>>namespace TestApp
BFE>>{
BFE>>    /// <summary>
BFE>>    /// Класс для задания и расчета времени по расписанию.
BFE>>    /// </summary>
BFE>>    public class Schedule
BFE>>    {
BFE>>        private const string _placeholder = "*"; // Звездочка означает любое возможное значение.
BFE>>        private const string _defaultMilliseconds = "0"; // fff - миллисекунды (0-999). Если не указаны, то 0

BFE>>        internal readonly byte[] _years =        new byte[101]; // год (2000-2100)
BFE>>        internal readonly byte[] _months =       new byte[12]; // месяц (1-12)
BFE>>        internal readonly byte[] _days =         new byte[32]; // число месяца (1-31 или 32)
BFE>>        internal readonly byte[] _weekDays =     new byte[7]; // день недели (0-6)
BFE>>        internal readonly byte[] _hours =        new byte[24]; // часы (0-23)
BFE>>        internal readonly byte[] _minutes =      new byte[60]; // минуты (0-59)
BFE>>        internal readonly byte[] _seconds =      new byte[60]; // секунды (0-59)
BFE>>        internal readonly byte[] _milliseconds = new byte[1000]; // миллисекунды (0-999)

BFE>>        /// <summary>
BFE>>        /// Создает пустой экземпляр, который будет соответствовать
BFE>>        /// расписанию типа "*.*.* * *:*:*.*" (раз в 1 мс).
BFE>>        /// </summary>
BFE>>        public Schedule ()
BFE>>            : this ("*.*.* * *:*:*.*")
BFE>>        {
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Создает экземпляр из строки с представлением расписания.
BFE>>        /// </summary>
BFE>>        /// <param name="scheduleString">Строка расписания.
BFE>>        /// Формат строки:
BFE>>        ///     yyyy.MM.dd w HH:mm:ss.fff
BFE>>        ///     yyyy.MM.dd HH:mm:ss.fff
BFE>>        ///     HH:mm:ss.fff
BFE>>        ///     yyyy.MM.dd w HH:mm:ss
BFE>>        ///     yyyy.MM.dd HH:mm:ss
BFE>>        ///     HH:mm:ss
BFE>>        /// Где yyyy - год (2000-2100)
BFE>>        ///     MM - месяц (1-12)
BFE>>        ///     dd - число месяца (1-31 или 32). 32 означает последнее число месяца
BFE>>        ///     w - день недели (0-6). 0 - воскресенье, 6 - суббота
BFE>>        ///     HH - часы (0-23)
BFE>>        ///     mm - минуты (0-59)
BFE>>        ///     ss - секунды (0-59)
BFE>>        ///     fff - миллисекунды (0-999). Если не указаны, то 0
BFE>>        /// Каждую часть даты/времени можно задавать в виде списков и диапазонов.
BFE>>        /// Например:
BFE>>        ///     1,2,3-5,10-20/3
BFE>>        ///     означает список 1,2,3,4,5,10,13,16,19
BFE>>        /// Дробью задается шаг в списке.
BFE>>        /// Звездочка означает любое возможное значение.
BFE>>        /// Например (для часов):
BFE>>        ///     */4
BFE>>        ///     означает 0,4,8,12,16,20
BFE>>        /// Вместо списка чисел месяца можно указать 32. Это означает последнее
BFE>>        /// число любого месяца.
BFE>>        /// Пример:
BFE>>        ///     *.9.*/2 1-5 10:00:00.000
BFE>>        ///     означает 10:00 во все дни с пн. по пт. по нечетным числам в сентябре
BFE>>        ///     *:00:00
BFE>>        ///     означает начало любого часа
BFE>>        ///     *.*.01 01:30:00
BFE>>        ///     означает 01:30 по первым числам каждого месяца
BFE>>        /// </param>
BFE>>        public Schedule (string scheduleString)
BFE>>        {
BFE>>            // конструктор большой по объёму исходника, но выполняет лишь простейшие действия и не выделяет память
BFE>>            if (scheduleString == null)
BFE>>            {
BFE>>                throw new ArgumentNullException (nameof (scheduleString));
BFE>>            }

BFE>>            var dotPosition1 = scheduleString.IndexOf ('.');
BFE>>            var dotPosition2 = (dotPosition1 < 0) ?
BFE>>                -1 :
BFE>>                scheduleString.IndexOf ('.', dotPosition1 + 1);
BFE>>            var dotPosition3 = (dotPosition2 < 0) ?
BFE>>                -1 :
BFE>>                scheduleString.IndexOf ('.', dotPosition2 + 1);
BFE>>            var colonPosition1 = scheduleString.IndexOf (':');
BFE>>            var colonPosition2 = (colonPosition1 < 0) ?
BFE>>                -1 :
BFE>>                scheduleString.IndexOf (':', colonPosition1 + 1);
BFE>>            if (colonPosition2 < 0)
BFE>>            {
BFE>>                // два двоеточия есть во всех форматах
BFE>>                throw new FormatException ();
BFE>>            }
BFE>>            var spacePosition1 = scheduleString.IndexOf (' ');
BFE>>            var spacePosition2 = (spacePosition1 < 0) ?
BFE>>                -1 :
BFE>>                scheduleString.IndexOf (' ', spacePosition1 + 1);

BFE>>            ReadOnlySpan<char> yearPart;
BFE>>            ReadOnlySpan<char> monthPart;
BFE>>            ReadOnlySpan<char> dayPart;
BFE>>            ReadOnlySpan<char> weekDayPart;
BFE>>            ReadOnlySpan<char> hourPart;
BFE>>            ReadOnlySpan<char> minutePart;
BFE>>            ReadOnlySpan<char> secondPart;
BFE>>            ReadOnlySpan<char> millisecondPart;
BFE>>            if (
BFE>>                (dotPosition1 >= 0) &&
BFE>>                (dotPosition2 >= 0) &&
BFE>>                (dotPosition3 >= 0) &&
BFE>>                (colonPosition1 > dotPosition2) &&
BFE>>                (dotPosition3 > colonPosition2))
BFE>>            {
BFE>>                // yyyy.MM.dd w HH:mm:ss.fff  или  yyyy.MM.dd HH:mm:ss.fff
BFE>>                yearPart = scheduleString.AsSpan (0, dotPosition1);
BFE>>                monthPart = scheduleString.AsSpan (dotPosition1 + 1, dotPosition2 - dotPosition1 - 1);
BFE>>                dayPart = scheduleString.AsSpan (dotPosition2 + 1, spacePosition1 - dotPosition2 - 1);
BFE>>                weekDayPart = (spacePosition2 < 0) ?
BFE>>                    _placeholder :
BFE>>                    scheduleString.AsSpan (spacePosition1 + 1, spacePosition2 - spacePosition1 - 1);
BFE>>                hourPart = (spacePosition2 < 0) ?
BFE>>                    scheduleString.AsSpan (spacePosition1 + 1, colonPosition1 - spacePosition1 - 1) :
BFE>>                    scheduleString.AsSpan (spacePosition2 + 1, colonPosition1 - spacePosition2 - 1);
BFE>>                minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>>                secondPart = scheduleString.AsSpan (colonPosition2 + 1, dotPosition3 - colonPosition2 - 1);
BFE>>                millisecondPart = scheduleString.AsSpan (dotPosition3 + 1);
BFE>>            }
BFE>>            else
BFE>>            {
BFE>>                if (
BFE>>                    (dotPosition1 >= 0) &&
BFE>>                    (dotPosition2 >= 0) &&
BFE>>                    (dotPosition3 < 0) &&
BFE>>                    (colonPosition1 > dotPosition2))
BFE>>                {
BFE>>                    // yyyy.MM.dd w HH:mm:ss  или  yyyy.MM.dd HH:mm:ss
BFE>>                    yearPart = scheduleString.AsSpan (0, dotPosition1);
BFE>>                    monthPart = scheduleString.AsSpan (dotPosition1 + 1, dotPosition2 - dotPosition1 - 1);
BFE>>                    dayPart = scheduleString.AsSpan (dotPosition2 + 1, spacePosition1 - dotPosition2 - 1);
BFE>>                    weekDayPart = (spacePosition2 < 0) ?
BFE>>                        _placeholder :
BFE>>                        scheduleString.AsSpan (spacePosition1 + 1, spacePosition2 - spacePosition1 - 1);
BFE>>                    hourPart = (spacePosition2 < 0) ?
BFE>>                        scheduleString.AsSpan (spacePosition1 + 1, colonPosition1 - spacePosition1 - 1) :
BFE>>                        scheduleString.AsSpan (spacePosition2 + 1, colonPosition1 - spacePosition2 - 1);
BFE>>                    minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>>                    secondPart = scheduleString.AsSpan (colonPosition2 + 1);
BFE>>                    millisecondPart = _defaultMilliseconds;
BFE>>                }
BFE>>                else
BFE>>                {
BFE>>                    if (
BFE>>                        (dotPosition1 >= 0) &&
BFE>>                        (dotPosition2 < 0) &&
BFE>>                        (colonPosition2 < dotPosition1))
BFE>>                    {
BFE>>                        // HH:mm:ss.fff
BFE>>                        yearPart = _placeholder;
BFE>>                        monthPart = _placeholder;
BFE>>                        dayPart = _placeholder;
BFE>>                        weekDayPart = _placeholder;
BFE>>                        hourPart = scheduleString.AsSpan (0, colonPosition1);
BFE>>                        minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>>                        secondPart = scheduleString.AsSpan (colonPosition2 + 1, dotPosition1 - colonPosition2 - 1);
BFE>>                        millisecondPart = scheduleString.AsSpan (dotPosition1 + 1);
BFE>>                    }
BFE>>                    else
BFE>>                    {
BFE>>                        if (dotPosition1 < 0)
BFE>>                        {
BFE>>                            // HH:mm:ss
BFE>>                            yearPart = _placeholder;
BFE>>                            monthPart = _placeholder;
BFE>>                            dayPart = _placeholder;
BFE>>                            weekDayPart = _placeholder;
BFE>>                            hourPart = scheduleString.AsSpan (0, colonPosition1);
BFE>>                            minutePart = scheduleString.AsSpan (colonPosition1 + 1, colonPosition2 - colonPosition1 - 1);
BFE>>                            secondPart = scheduleString.AsSpan (colonPosition2 + 1);
BFE>>                            millisecondPart = _defaultMilliseconds;
BFE>>                        }
BFE>>                        else
BFE>>                        {
BFE>>                            throw new FormatException ("Unrecognized schedule.");
BFE>>                        }
BFE>>                    }
BFE>>                }
BFE>>            }

BFE>>            ParsePart (yearPart,        _years,        2000);
BFE>>            ParsePart (monthPart,       _months,       1);
BFE>>            ParsePart (dayPart,         _days,         1);
BFE>>            ParsePart (weekDayPart,     _weekDays,     0);
BFE>>            ParsePart (hourPart,        _hours,        0);
BFE>>            ParsePart (minutePart,      _minutes,      0);
BFE>>            ParsePart (secondPart,      _seconds,      0);
BFE>>            ParsePart (millisecondPart, _milliseconds, 0);
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Возвращает следующий ближайший к заданному времени момент в расписании или
BFE>>        /// само заданное время, если оно есть в расписании.
BFE>>        /// </summary>
BFE>>        /// <param name="t1">Заданное время</param>
BFE>>        /// <returns>Ближайший момент времени в расписании</returns>
BFE>>        public DateTime NearestEvent(DateTime t1)
BFE>>        {
BFE>>            // цикл проверки каждый раз после корректировки времени, макс. кол-во итераций: 100 + 11 + 31 + 23 + 59 + 59 = 283
BFE>>            while (true)
BFE>>            {
BFE>>                var yearOffset = t1.Year - 2000;
BFE>>                if ((yearOffset < 0) || (yearOffset >= _years.Length))
BFE>>                {
BFE>>                    throw new InvalidOperationException ("Year out of range");
BFE>>                }

BFE>>                if (_years[yearOffset] > 0)
BFE>>                {
BFE>>                    if (_months[t1.Month - 1] > 0)
BFE>>                    {
BFE>>                        var isLastDayInMonth = t1.Day == DateTime.DaysInMonth (t1.Year, t1.Month);
BFE>>                        // 32-й день означает последнее число месяца
BFE>>                        if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
BFE>>                        {
BFE>>                            if (_hours[t1.Hour] > 0)
BFE>>                            {
BFE>>                                if (_minutes[t1.Minute] > 0)
BFE>>                                {
BFE>>                                    if (_seconds[t1.Second] > 0)
BFE>>                                    {
BFE>>                                        var millisecond = t1.Millisecond;
BFE>>                                        do
BFE>>                                        {
BFE>>                                            if (_milliseconds[millisecond] > 0)
BFE>>                                            {
BFE>>                                                return new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second, millisecond);
BFE>>                                            }

BFE>>                                            millisecond++;
BFE>>                                        } while (millisecond < _milliseconds.Length);
BFE>>                                    }
BFE>>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second).AddSeconds (1);
BFE>>                                }
BFE>>                                else
BFE>>                                {
BFE>>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, 0).AddMinutes (1);
BFE>>                                }
BFE>>                            }
BFE>>                            else
BFE>>                            {
BFE>>                                t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, 0, 0).AddHours (1);
BFE>>                            }
BFE>>                        }
BFE>>                        else
BFE>>                        {
BFE>>                            t1 = new DateTime (t1.Year, t1.Month, t1.Day).AddDays (1);
BFE>>                        }
BFE>>                    }
BFE>>                    else
BFE>>                    {
BFE>>                        t1 = new DateTime (t1.Year, t1.Month, 1).AddMonths (1);
BFE>>                    }
BFE>>                }
BFE>>                else
BFE>>                {
BFE>>                    t1 = new DateTime (t1.Year, 1, 1).AddYears (1);
BFE>>                }
BFE>>            }
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Возвращает предыдущий ближайший к заданному времени момент в расписании или
BFE>>        /// само заданное время, если оно есть в расписании.
BFE>>        /// </summary>
BFE>>        /// <param name="t1">Заданное время</param>
BFE>>        /// <returns>Ближайший момент времени в расписании</returns>
BFE>>        public DateTime NearestPrevEvent(DateTime t1)
BFE>>        {
BFE>>            // цикл проверки каждый раз после корректировки времени, макс. кол-во итераций: 100 + 11 + 31 + 23 + 59 + 59 = 283
BFE>>            while (true)
BFE>>            {
BFE>>                var yearOffset = t1.Year - 2000;
BFE>>                if ((yearOffset < 0) || (yearOffset >= _years.Length))
BFE>>                {
BFE>>                    throw new InvalidOperationException ("Year out of range");
BFE>>                }

BFE>>                if (_years[yearOffset] > 0)
BFE>>                {
BFE>>                    if (_months[t1.Month - 1] > 0)
BFE>>                    {
BFE>>                        var isLastDayInMonth = t1.Day == DateTime.DaysInMonth (t1.Year, t1.Month);
BFE>>                        // 32-й день означает последнее число месяца
BFE>>                        if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
BFE>>                        {
BFE>>                            if (_hours[t1.Hour] > 0)
BFE>>                            {
BFE>>                                if (_minutes[t1.Minute] > 0)
BFE>>                                {
BFE>>                                    if (_seconds[t1.Second] > 0)
BFE>>                                    {
BFE>>                                        var millisecond = t1.Millisecond;
BFE>>                                        do
BFE>>                                        {
BFE>>                                            if (_milliseconds[millisecond] > 0)
BFE>>                                            {
BFE>>                                                return new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second, millisecond);
BFE>>                                            }

BFE>>                                            millisecond--;
BFE>>                                        } while (millisecond >= 0);
BFE>>                                    }
BFE>>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, t1.Second).AddMilliseconds (-1);
BFE>>                                }
BFE>>                                else
BFE>>                                {
BFE>>                                    t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, t1.Minute, 0).AddMilliseconds (-1);
BFE>>                                }
BFE>>                            }
BFE>>                            else
BFE>>                            {
BFE>>                                t1 = new DateTime (t1.Year, t1.Month, t1.Day, t1.Hour, 0, 0).AddMilliseconds (-1);
BFE>>                            }
BFE>>                        }
BFE>>                        else
BFE>>                        {
BFE>>                            t1 = new DateTime (t1.Year, t1.Month, t1.Day).AddMilliseconds (-1);
BFE>>                        }
BFE>>                    }
BFE>>                    else
BFE>>                    {
BFE>>                        t1 = new DateTime (t1.Year, t1.Month, 1).AddMilliseconds (-1);
BFE>>                    }
BFE>>                }
BFE>>                else
BFE>>                {
BFE>>                    t1 = new DateTime (t1.Year, 1, 1).AddMilliseconds (-1);
BFE>>                }
BFE>>            }
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Возвращает следующий момент времени в расписании.
BFE>>        /// </summary>
BFE>>        /// <param name="t1">Время, от которого нужно отступить</param>
BFE>>        /// <returns>Следующий момент времени в расписании</returns>
BFE>>        public DateTime NextEvent(DateTime t1)
BFE>>        {
BFE>>            return NearestEvent (t1.AddMilliseconds (1));
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Возвращает предыдущий момент времени в расписании.
BFE>>        /// </summary>
BFE>>        /// <param name="t1">Время, от которого нужно отступить</param>
BFE>>        /// <returns>Предыдущий момент времени в расписании</returns>
BFE>>        public DateTime PrevEvent(DateTime t1)
BFE>>        {
BFE>>            return NearestPrevEvent (t1.AddMilliseconds (-1));
BFE>>        }

BFE>>        /// <summary>
BFE>>        /// Заполняет указанный массив ненулевыми значениями для тех индексов, которые указаны в partStr.
BFE>>        /// </summary>
BFE>>        /// <param name="partStr">Текстовый список диапазонов.</param>
BFE>>        /// <param name="allowedValues">Массив, в котором будут отмечены ненулевым значением указанные в partStr числа.</param>
BFE>>        /// <param name="offset">Смещение, которое будет вычитаться для всех чисел, указанных в partStr.</param>
BFE>>        private static void ParsePart (ReadOnlySpan<char> partStr, byte[] allowedValues, int offset)
BFE>>        {
BFE>>            // Каждую часть даты/времени можно задавать в виде списков и диапазонов.
BFE>>            // Например:
BFE>>            //     1,2,3-5,10-20/3
BFE>>            //     означает список 1,2,3,4,5,10,13,16,19
BFE>>            // Дробью задается шаг в списке.
BFE>>            // Звездочка означает любое возможное значение.

BFE>>            if (partStr.Length < 1)
BFE>>            {
BFE>>                throw new FormatException ("Invalid part");
BFE>>            }

BFE>>            var idx = 0;
BFE>>            while (idx < partStr.Length)
BFE>>            {
BFE>>                int number1;
BFE>>                int number2;
BFE>>                if (partStr[idx] == '*')
BFE>>                {
BFE>>                    idx++;
BFE>>                    number1 = 0;
BFE>>                    number2 = allowedValues.Length - 1;
BFE>>                }
BFE>>                else
BFE>>                {
BFE>>                    number1 = ParseNumber (partStr, ref idx) - offset;
BFE>>                    if ((number1 < 0) || (number1 >= allowedValues.Length))
BFE>>                    {
BFE>>                        throw new FormatException ("Number out of range.");
BFE>>                    }

BFE>>                    number2 = number1;
BFE>>                    if ((idx < partStr.Length) && (partStr[idx] == '-'))
BFE>>                    {
BFE>>                        idx++;
BFE>>                        number2 = ParseNumber (partStr, ref idx) - offset;
BFE>>                        if ((number2 < 0) || (number2 >= allowedValues.Length))
BFE>>                        {
BFE>>                            throw new FormatException ("Number out of range.");
BFE>>                        }
BFE>>                    }
BFE>>                }

BFE>>                var period = 1;
BFE>>                if (idx < partStr.Length)
BFE>>                {
BFE>>                    switch (partStr[idx])
BFE>>                    {
BFE>>                        case '/':
BFE>>                            idx++;
BFE>>                            period = ParseNumber (partStr, ref idx);
BFE>>                            break;
BFE>>                        case ',':
BFE>>                            idx++;
BFE>>                            break;
BFE>>                        default:
BFE>>                            throw new FormatException ("Invalid character.");
BFE>>                    }
BFE>>                }

BFE>>                for (var i = number1; i <= number2; i += period)
BFE>>                {
BFE>>                    allowedValues[i] = 1;
BFE>>                }
BFE>>            }
BFE>>        }

BFE>>        // возвращает число, полученное из текстового представленая в partStr начиная с индекса в idx
BFE>>        private static int ParseNumber (ReadOnlySpan<char> partStr, ref int idx)
BFE>>        {
BFE>>            var number = 0;
BFE>>            while ((idx < partStr.Length) && (partStr[idx] >= '0') && (partStr[idx] <= '9'))
BFE>>            {
BFE>>                number = 10 * number + partStr[idx] - '0';
BFE>>                idx++;
BFE>>            }

BFE>>            return number;
BFE>>        }
BFE>>    }
BFE>>}
BFE>>



mgu>Какой вывих мозга?

А вы смогли сходу (за одно прочтение) понять, что и зачем делает автор?

mgu> Всё же совершенно очевидно:

mgu>
mgu>     // 32-й день означает последнее число месяца
mgu>

Это как раз да — это взято из условий.

mgu>Все возмущаются вложенностью условий... Да этот господин и одно-то условие не может написать толком:

А что не так?

mgu>
mgu>    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
mgu>

mgu>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.
Я не знаю, как там оно в C#, поэтому мне со скобками проще читать. А как надо?
И каждый день — без права на ошибку...
Re[4]: Просидев на одном предприятии несколько лет...
От: B0FEE664  
Дата: 10.08.21 11:40
Оценка:
Здравствуйте, Sharov, Вы писали:

S>переложить большую часть проблем с учетом всяческих високосных годов на DataTime.

А разве это не так?
И каждый день — без права на ошибку...
Re[2]: Просидев на одном предприятии несколько лет...
От: B0FEE664  
Дата: 10.08.21 11:43
Оценка:
Здравствуйте, rosencrantz, Вы писали:

R>Здравствуйте, vaa, Вы писали:


vaa>>https://habr.com/ru/post/571342/

vaa>>Читаю комменты второй день и . Парадоксально на мой взгляд, но никто до сих пор(региться не охота)
vaa>>не отметил:
vaa>>1. быть может отказали почуяв крутого кулцхакера(конкурента).
vaa>>слышал в крупных компаниях есть такое ограничение — слишком умных не брать, чтобы не взломали систему.
vaa>>2. "Просидев на одном предприятии несколько лет...", таки зачем срываться? похоже на минутную слабость.
vaa>>3. почему-то все крутые прогеры пока только накидывают критики, но никто не показал образцовое решение.

R>Мне код не нравится — выглядит как "авторский".

Код реально авторский — не промышленный.

R>1. Для чтения выражений нужно какой-то внятный парсер с внятной грамматикой, или хотя бы регулярные выражения. Чтобы грамматика была не в комментах, а в чём-то более-менее компьютерном.

Это чтобы было сложнее тестировать или чтобы медленнее работал код?

R>Чтобы можно было красиво ругаться "что qwerty не выглядит как число от 1 до 12".

И что с этим потом делать?

R>2. Решение никак не порезано на отдельные логические куски — программу невозможно читать по частям, только как монолит. Я бы попытался дизайнить в сторону "композиции триггеров". Парсим -> дерево разбора -> составной триггер.

В один день уложитесь?
И каждый день — без права на ошибку...
Re[5]: Просидев на одном предприятии несколько лет...
От: Sharov Россия  
Дата: 10.08.21 11:50
Оценка:
Здравствуйте, B0FEE664, Вы писали:


S>>переложить большую часть проблем с учетом всяческих високосных годов на DataTime.

BFE>А разве это не так?

Я поверхностно пробежал, офигел от процедурного стиля и уровня вложений if, соотв. показалось, что он все делает руками. Т.е сам вычисляет условия високостного года и т.д. Могу и ошибаться.
Кодом людям нужно помогать!
Re[3]: Просидев на одном предприятии несколько лет...
От: rosencrantz США  
Дата: 10.08.21 17:08
Оценка:
Здравствуйте, B0FEE664, Вы писали:

R>>1. Для чтения выражений нужно какой-то внятный парсер с внятной грамматикой, или хотя бы регулярные выражения. Чтобы грамматика была не в комментах, а в чём-то более-менее компьютерном.

BFE>Это чтобы было сложнее тестировать или чтобы медленнее работал код?

На сложность тестирования это никак не влияет: тесты как были вход->выход, так и остаются. Про тормоза не стоит так вопрос ставить. Тормозит не код, тормозит система в конкретном ворклоаде. Использовать инструменты более высокого уровня (парсер против indexOf) стоит ради читаемости. Короткую регулярку (или десяток регулярок — по одной на каждый случай грамматики) прочитать и понять легче, чем эту лапшу из ифов и волшебных чисел.

Цитата из оригинальной статьи:

Добиваться каких то экстремальных показателей в плане оптимизации нет смысла, потому что это приведёт к снижению такого важного показателя как поддерживаемость кода, а будет ли от этого польза — непонятно, поскольку неизвестны условия эксплуатации.


R>>Чтобы можно было красиво ругаться "что qwerty не выглядит как число от 1 до 12".

BFE>И что с этим потом делать?

Падать с эксшепшном "плохое выражение: qwerty не выглядит как число от 1 до 12" вместо "плохое выражение".

R>>2. Решение никак не порезано на отдельные логические куски — программу невозможно читать по частям, только как монолит. Я бы попытался дизайнить в сторону "композиции триггеров". Парсим -> дерево разбора -> составной триггер.

BFE>В один день уложитесь?

Нет, дня 3. А что?
Re[3]: Просидев на одном предприятии несколько лет...
От: vfedosov  
Дата: 10.08.21 18:25
Оценка: +1
mgu>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.

Некоторые конторы заставляют ставить скобки вообще везде, где есть 2 операции и насрать им на приоритет. В Германии, к примеру, в атомобильной промышленности это просто индустриальный стандарт . Конечно, нечитабельно, но выхода нет — пишешь такое гавно.
Отредактировано 10.08.2021 18:26 vfedosov . Предыдущая версия .
Re[2]: Просидев на одном предприятии несколько лет...
От: ononim  
Дата: 10.08.21 19:59
Оценка:
AM>Зачем, например, под миллисекунды 1000 байт? По байту на каждое возможное значение? 60 байт на секунды, 60 на минуты и т.п. Зачем? Странный какой-то код у него.
Да ваще, экономист блин нашелся. BitArray-ем надо было.
Как много веселых ребят, и все делают велосипед...
Re: Просидев на одном предприятии несколько лет...
От: scf  
Дата: 10.08.21 19:59
Оценка: 3 (1)
Здравствуйте, vaa, Вы писали:

vaa>3. почему-то все крутые прогеры пока только накидывают критики, но никто не показал образцовое решение.


На хабре выложили интересный разбор решения и предложили "как надо" https://habr.com/ru/post/572052/
Re[4]: Просидев на одном предприятии несколько лет...
От: mgu  
Дата: 10.08.21 22:05
Оценка:
Здравствуйте, Doom100500, Вы писали:

D>Здравствуйте, mgu, Вы писали:


mgu>>
mgu>>    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
mgu>>


mgu>>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.


D>Это не математические, а логические оперзции. В школе их не изучают (по крайней мере не во втором классе).

D>А ставить скобки для удобочтаемости — это нормально.

А скобки и есть математические операции. От лишних скобок читаемость как раз страдает. Лучше бы в тексте про запятые не забывали.
Re[4]: Просидев на одном предприятии несколько лет...
От: mgu  
Дата: 10.08.21 22:24
Оценка:
Здравствуйте, B0FEE664, Вы писали:

mgu>>Какой вывих мозга?

BFE>А вы смогли сходу (за одно прочтение) понять, что и зачем делает автор?

Нет. А надо сходу?

mgu>> Всё же совершенно очевидно:

mgu>>
mgu>>     // 32-й день означает последнее число месяца
mgu>>

BFE>Это как раз да — это взято из условий.

Феерично! Тогда первый день месяца -- -1?

mgu>>Все возмущаются вложенностью условий... Да этот господин и одно-то условие не может написать толком:

BFE>А что не так?

mgu>>
mgu>>    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
mgu>>

mgu>>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.
BFE>Я не знаю, как там оно в C#, поэтому мне со скобками проще читать.

А при чём здесь C#? Приоритет операций одинаков в большинстве ЯП.

BFE>А как надо?


Без бессмысленных скобок хотя бы так:
if ((_days[t1.Day - 1] > 0 || isLastDayInMonth && _days[31] > 0) && _weekDays[(int)t1.DayOfWeek] > 0)


А можно и так:
if (_days[isLastDayInMonth ? 31 : t1.Day - 1] > 0 && _weekDays[(int)t1.DayOfWeek] > 0)


А лучше вообще соорудить метод t1.isEmpty().
Re[4]: Просидев на одном предприятии несколько лет...
От: mgu  
Дата: 10.08.21 22:38
Оценка:
Здравствуйте, vfedosov, Вы писали:

mgu>>Приоритет математических операций изучают во втором классе школы. Судя по правописанию, автор закончил только первый.


V>Некоторые конторы заставляют ставить скобки вообще везде, где есть 2 операции и насрать им на приоритет. В Германии, к примеру, в атомобильной промышленности это просто индустриальный стандарт . Конечно, нечитабельно, но выхода нет — пишешь такое гавно.


Так дойдёт до:

a + (b * c)


Заметил, что кадровые говнокодеры, обычно пишушие в таком стиле:

a= 1;
b =2;
c = 3;


...за однострочный блок без фигурных скобок горло перегрызут.
Re[2]: Просидев на одном предприятии несколько лет...
От: vaa  
Дата: 11.08.21 01:45
Оценка:
Здравствуйте, scf, Вы писали:


scf>На хабре выложили интересный разбор решения и предложили "как надо" https://habr.com/ru/post/572052/


Т.е. даже прошаренному спецу понадобилось чуть больше недели чтобы заимплиментить задачу. да уж.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: Просидев на одном предприятии несколько лет...
От: Тёмчик Австралия жж
Дата: 11.08.21 02:19
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

scf>>P.S. И, конечно, сначала посмотрел бы, как умные люди это уже реализовали


БП>Не-не-не, не нужно смотреть. Там точно такая же простыня, но с регулярками.


Код на лиспе. Функции достаточно короткие. Сравни это с кодом автора, где 1 метод- гигантская простыня с кучей вложенных if-ов — else-ов.
Re[4]: Просидев на одном предприятии несколько лет...
От: Тёмчик Австралия жж
Дата: 11.08.21 02:23
Оценка: -1
Здравствуйте, Doom100500, Вы писали:

D>А ставить скобки для удобочтаемости — это нормально.


Я заметил корелляцию кстати (из жизненных наблюдений за коллегами), способности программиста знать приоритет операций, и адекватностью его дизайнов (наркоманы все как один хотят скобки для удобочитаемости).
Re[5]: Просидев на одном предприятии несколько лет...
От: Doom100500 Израиль  
Дата: 11.08.21 04:57
Оценка:
Здравствуйте, mgu, Вы писали:


mgu>Лучше бы в тексте про запятые не забывали.


Слив засчитан
Спасибо за внимание
Re[5]: Просидев на одном предприятии несколько лет...
От: Doom100500 Израиль  
Дата: 11.08.21 05:00
Оценка:
Здравствуйте, Тёмчик, Вы писали:

Тё>(наркоманы все как один хотят скобки для удобочитаемости).


К сожаению аргументов у меня нет, поэтому сразу перехожу на личности.
Спасибо за внимание
Re[5]: Просидев на одном предприятии несколько лет...
От: Doom100500 Израиль  
Дата: 11.08.21 05:05
Оценка:
Здравствуйте, mgu, Вы писали:

mgu>А можно и так:

mgu>
mgu>if (_days[isLastDayInMonth ? 31 : t1.Day - 1] > 0 && _weekDays[(int)t1.DayOfWeek] > 0)
mgu>


Вот это вообще зашквар

mgu>>>
mgu>>>    if (((_days[t1.Day - 1] > 0) || (isLastDayInMonth && (_days[31] > 0))) && (_weekDays[(int)t1.DayOfWeek] > 0))
mgu>>>


Как, в принципе и в оригинале. (Извините погoрячился)
Спасибо за внимание
Отредактировано 11.08.2021 5:33 Doom100500 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.