Инструменты пользователя

Инструменты сайта


mikrotik:rb3011uias:routeros:system:scripts:functions:day_of_the_week

Функция вычисления дня недели по дате для MikroTik

Мой вариант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;
}

Код для импорта

day-of-week.rsc
/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";};

Код для импорта

day-of-week-and-time.rsc
/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

Порядок следования дней недели смотрите выше.

Политики запуска

Это минимально необходимый набор для работы функции.

  • read,
  • write,
  • policy,
  • test.

Дисклеймер

  • Использование материалов данной базы знаний разрешено на условиях лицензии, указанной внизу каждой страницы! При использовании материалов активная гиперссылка на соответствующую страницу данной базы знаний обязательна!
  • Автор не несет и не может нести какую либо ответственность за последствия использования материалов, размещенных в данной базе знаний. Все материалы предоставляются по принципу «как есть». Используйте их исключительно на свой страх и риск.
  • Все высказывания, мысли или идеи автора, размещенные в материалах данной базе знаний, являются исключительно его личным субъективным мнением и могут не совпадать с мнением читателей!
  • При размещении ссылок в данной базе знаний на интернет-страницы третьих лиц автор не несет ответственности за их техническую функциональность (особенно отсутствие вирусов) и содержание! При обнаружении таких ссылок, можно и желательно сообщить о них в комментариях к соответствующей статье.
1)
В Интернете есть несколько других кейсов, но все они показались мне несколько громоздкими и, по разным сообщениям, не всегда корректно работающим. Вот ссылки на них – раз, два и три. Поэтому я разобрался в работе алгоритма – Excel с примером – и собрал свой велосипед. LOL
2)
Подробнее смотрите по ссылке.
3)
При необходимости можно сделать функцию локальной, заменив :global на :local или вообще превратить в обычный фрагмент кода, убрав конструкцию :global dayOfWeek do={... :return $result; }.

Обсуждение

Ваш комментарий:
S​ M᠎ N C D R M O S U J F᠎ O Y L A
 
Последнее изменение: 2022/02/12 11:40 (внешнее изменение)