Настройка периодических задач в приложениях — вечный конфликт между удобством человека и жестким формализмом планировщиков. Обычный пользователь формулирует задачу естественно: «по будням в 9:30» или «каждые 15 минут с 10 до 18». Планировщик unix-систем требует холодную строку вида 30 9 * * 1-5. Попытки закрыть эту пропасть с помощью генеративных нейросетей часто оборачиваются скрытыми авариями: модели склонны галлюцинировать, незаметно путая дни недели или сдвигая интервалы запуска.
Открытая библиотека cronsense от разработчика MrProLopstar (опубликованная в реестре JSR) решает проблему с математической точностью, реализуя полностью детерминированный двусторонний транслятор расписаний для TypeScript и JavaScript.
Лексер, грамматический парсер и ловушки синтаксиса
В основе библиотеки лежит не вероятностное угадывание, а строгий парсер рекурсивного спуска. Лексер разбивает входную строку на лексемы (числа, временные маркеры, интервалы) с сохранением точных координат символов. Специальный словарь основ слов покрывает грамматические падежи русского и английского языков, исключая необходимость тащить тяжелые словари морфологии.
Архитектура корректно разрешает неочевидные ловушки синтаксиса cron:
- Конфликт дня недели и дня месяца. По стандарту POSIX поля дня месяца и дня недели объединяются логическим оператором «ИЛИ». Выражение
0 0 1 * 1сработает и каждый понедельник, и каждое первое число. Библиотека выявляет неоднозначные фразы вроде «по понедельникам 1 числа» и отклоняет их с понятной ошибкойCONFLICT, а не плодит ошибочные интервалы. - Границы интервалов. Фраза «каждые 15 минут с 9 до 18» логически означает, что последний запуск в рамках часа произойдет в 17:45. Библиотека транслирует это в часы
9-17, предотвращая лишний запуск ровно в 18:00.
Продемонстрируем прямое преобразование естественного текста в cron-строку:
import { toCron } from '@mrprolopstar/cronsense';
// Трансляция сложного человеческого расписания в стандартную строку
const result = toCron('по будням каждые 2 часа с 9 до 18', { locale: 'ru' });
if (result.ok) {
console.log('Сгенерированный cron:', result.cron);
// Вывод: "0 9-17/2 * * 1-5"
} else {
console.error('Ошибка разбора:', result.error.code, result.error.message);
}
Обратная генерация и тестирование обратимости
Второе направление работы библиотеки — генерация понятного текстового описания из сырой строки cron с расчетом ближайших запусков:
import { describeCron, getNextRuns } from '@mrprolopstar/cronsense';
const cronExpr = '30 9 * * 1-5';
// Обратный перевод выражения в текст для интерфейса пользователя
const humanDescription = describeCron(cronExpr, { locale: 'ru' });
console.log(humanDescription); // "В 09:30 по будням"
// Вычисление меток времени следующих трех выполнений задачи
const nextExecutions = getNextRuns(cronExpr, { count: 3 });
console.log('Следующие запуски:', nextExecutions.map(d => d.toISOString()));
Надежность алгоритмов подтверждается property-тестированием на выборке из 3000 случайно сгенерированных выражений: библиотека гарантирует строгую обратимость (round-trip), когда текстовое описание восстанавливает исходную cron-строку без искажения множеств минут и часов.
Библиотека также поставляется со встроенным сервером cronsense-mcp, позволяющим подключать эти алгоритмы к ИИ-ассистентам в качестве надежного инструмента планирования без галлюцинаций.
