
Мой вариант1) функции, которая возвращает текущий день недели основываясь на дате. Использует модифицированный алгоритм Зеллера для программного обеспечения2).
Добавлена модифицированная функция, которая возвращает массив из дня недели и текущего часа.
Создаем глобальную функцию3) и получаем текущую дату.
:global dayOfWeek do={ :local date [ /system clock get date ];
Для тестирования и диагностики закомментировать предыдущее и раскомментировать это. Дату указывать, как в примере.
#:local date "mar/01/2009"; #:put $date;
Инициализируем необходимые переменные.
:local result; :local day; :local year;
Вводим массивы с данными. Обратите внимание в каком порядке следуют дни недели и какая нумерация у месяцев. Так должно быть согласно алгоритму.
:local days {"sat";"sun";"mon";"tue";"wed";"thu";"fri";}; :local months {mar="3";apr="4";may="5";jun="6";jul="7";aug="8";sep="9";oct="10";nov="11";dec="12";jan="13";feb="14";};
Отбираем месяц и «век».
:local month ( $months -> [ :pick $date 0 3 ] ); :local century [ :pick $date 7 9 ];
Проверяем день и год – если они начинаются с нуля, используем только вторую цифру.
:if ( [ :pick $date 4 5 ] = 0 ) do={ :set day [ :pick $date 5 6 ]; } else={ :set day [ :pick $date 4 6 ]; } :if ( [ :pick $date 9 10 ] = 0 ) do={ :set year [ :pick $date 10 11 ]; } else={ :set year [ :pick $date 9 11 ]; }
Корректируем номер года для Января и Февраля, т.к., согласно алгоритму, они имеют номера 13 и 14 соответственно.
:if ( $month = 13 || $month = 14 ) do={ :set year ( $year - 1 ); }
Сам модифицированный алгоритм Зеллера.
:set result ( $day + ( 13 * ( $month + 1 ) / 5 ) + ( $century / 4 ) + $year + ( $year / 4 ) + ( 5 * $century ) ); :set result ( $days -> ( $result % 7 ) );
Возвращаем результат.
:return $result; }
/system script add comment="\D4\F3\ED\EA\F6\E8\FF \E2\FB\F7\E8\F1\EB\E5\ED\E8\FF \E4\ED\FF \ \ED\E5\E4\E5\EB\E8" dont-require-permissions=no name=day-of-week owner=\ vasya policy=read,write,policy,test source="# Written by Nikolay Soloshin \ (nikolay@soloshin.su) for RouterOS v6.47.8 on hAP (mipsbe) @ 2020.12\r\ \n\r\ \n:global dayOfWeek do={\r\ \n :local date [ /system clock get date ];\r\ \n\r\ \n # For test\r\ \n #:local date \"mar/01/2009\";\r\ \n #:put \$date;\r\ \n\r\ \n :local result;\r\ \n :local day;\r\ \n :local year;\r\ \n\r\ \n :local days {\"sat\";\"sun\";\"mon\";\"tue\";\"wed\";\"thu\";\"fri\";}\ ;\r\ \n :local months {mar=\"3\";apr=\"4\";may=\"5\";jun=\"6\";jul=\"7\";aug=\ \"8\";sep=\"9\";oct=\"10\";nov=\"11\";dec=\"12\";jan=\"13\";feb=\"14\";};\ \r\ \n\r\ \n :local month ( \$months -> [ :pick \$date 0 3 ] );\r\ \n :local century [ :pick \$date 7 9 ];\r\ \n\r\ \n # If the first char is a 0 (zero) only read last char, else script fai\ ls\r\ \n :if ( [ :pick \$date 4 5 ] = 0 ) do={ :set day [ :pick \$date 5 6 ]; }\ \_else={ :set day [ :pick \$date 4 6 ]; }\r\ \n :if ( [ :pick \$date 9 10 ] = 0 ) do={ :set year [ :pick \$date 10 11 \ ]; } else={ :set year [ :pick \$date 9 11 ]; }\r\ \n \r\ \n # Adjusting the year value for January and February\r\ \n :if ( \$month = 13 || \$month = 14 ) do={ :set year ( \$year - 1 ); }\ \r\ \n\r\ \n # Modified Zeller's congruence for software\r\ \n :set result ( \$day + ( 13 * ( \$month + 1 ) / 5 ) + ( \$century / 4 )\ \_+ \$year + ( \$year / 4 ) + ( 5 * \$century ) );\r\ \n :set result ( \$days -> ( \$result % 7 ) );\r\ \n\r\ \n :return \$result;\r\ \n}\r\ \n\r\ \n# With love from Vladivostok."
Модифицированная функция, которая возвращает массив из цифры дня недели и цифры часа. Удобна для использования в составе других скриптов, т.к. манипулировать цифрами намного проще. Плюс, она универсальна. Пример вывода смотрите ниже.
НАПИСАТЬ, ГДЕ ВВОДИТСЯ И ГДЕ ИСПОЛЬЗУЕТСЯ,
Этот код содержит такие изменения:
Получение часа из текущего времени и преобразование строки в число.
:local time [ :tonum [ :pick [ /system clock get time ] 0 2 ] ];
Строка для тестирования.
#:local time [ :tonum 14 ];
Удаление нуля в первой позиции из времени.
:if ( [ :pick $time 0 1 ] = 0 ) do={ :set time [ :pick $time 0 1 ]; }
Сборка массива.
:set ( $result -> "day" ) $day; :set ( $result -> "time" ) $time;
Добавлено преобразование в массив.
:local result [ :toarray "" ];
Убрана трансформация в буквенный код дня недели.
:set day ( $day % 7 );
Этот массив больше не нужен, т.к. отдаем в виде цифры.
:local days {"sat";"sun";"mon";"tue";"wed";"thu";"fri";};
/system script add comment="\CC\EE\E4\E8\F4\E8\EA\E0\F6\E8\FF, \E2\EE\E7\E2\F0\E0\F9\E0\FE\F9\ \E0\FF \E4\E5\ED\FC \ED\E5\E4\E5\EB\E8 \E8 \E2\F0\E5\EC\FF" \ dont-require-permissions=no name=day-of-week-and-time owner=vasya policy=\ read,write,policy,test source="# Written by Nikolay Soloshin (nikolay@solo\ shin.su) for RouterOS v6.47.8 on hAP (mipsbe) @ 2020.12\r\ \n\r\ \n:global dayAndTime do={\r\ \n :local date [ /system clock get date ];\r\ \n :local time [ :tonum [ :pick [ /system clock get time ] 0 2 ] ];\r\ \n\r\ \n # For test\r\ \n #:local time [ :tonum 14 ];\r\ \n #:local date \"mar/01/2009\";\r\ \n\r\ \n :local day;\r\ \n :local year;\r\ \n :local result [ :toarray \"\" ];\r\ \n\r\ \n :local months {mar=\"3\";apr=\"4\";may=\"5\";jun=\"6\";jul=\"7\";aug=\ \"8\";sep=\"9\";oct=\"10\";nov=\"11\";dec=\"12\";jan=\"13\";feb=\"14\";};\ \r\ \n\r\ \n :local month ( \$months -> [ :pick \$date 0 3 ] );\r\ \n :local century [ :pick \$date 7 9 ];\r\ \n\r\ \n # If the first char is a 0 (zero) only read last char, else script fai\ ls\r\ \n :if ( [ :pick \$date 4 5 ] = 0 ) do={ :set day [ :pick \$date 5 6 ]; }\ \_else={ :set day [ :pick \$date 4 6 ]; }\r\ \n :if ( [ :pick \$date 9 10 ] = 0 ) do={ :set year [ :pick \$date 10 11 \ ]; } else={ :set year [ :pick \$date 9 11 ]; }\r\ \n :if ( [ :pick \$time 0 1 ] = 0 ) do={ :set time [ :pick \$time 0 1 ]; \ }\r\ \n \r\ \n # Adjusting the year value for January and February\r\ \n :if ( \$month = 13 || \$month = 14 ) do={ :set year ( \$year - 1 ); }\ \r\ \n\r\ \n # Modified Zeller's congruence for software\r\ \n :set day ( \$day + ( 13 * ( \$month + 1 ) / 5 ) + ( \$century / 4 ) + \ \$year + ( \$year / 4 ) + ( 5 * \$century ) );\r\ \n :set day ( \$day % 7 );\r\ \n\r\ \n :set ( \$result -> \"day\" ) \$day;\r\ \n :set ( \$result -> \"time\" ) \$time;\r\ \n\r\ \n :return \$result;\r\ \n}\r\ \n\r\ \n# With love from Vladivostok."
Т.к. функции глобальные, после запуска их можно вызывать из любого другого скрипта или из терминала.
Вывод оригинальной функции:
[vasya@Gateos] > :put [ $dayOfWeek ] dec/08/2020 tue
Вывод модифицированной функции:
[vasya@Gateos] > :put [ $dayAndTime ] dec/08/2020 18:29:37 day=3;time=18
Порядок следования дней недели смотрите выше.
Это минимально необходимый набор для работы функции.
:global
на :local
или вообще превратить в обычный фрагмент кода, убрав конструкцию :global dayOfWeek do={... :return $result; }
.
Обсуждение