Дайджесты новостей
Двусторонний алгоритмический транслятор естественно-языковых расписаний и классических выражений cron с проверкой обратимости.

cronsense: двусторонний транслятор человеческих расписаний в cron

Настройка периодических задач в приложениях — вечный конфликт между удобством человека и жестким формализмом планировщиков. Обычный пользователь формулирует задачу естественно: «по будням в 9:30» или «каждые 15 минут с 10 до 18». Планировщик unix-систем требует холодную строку вида 30 9 * * 1-5. Попытки закрыть эту пропасть с помощью генеративных нейросетей часто оборачиваются скрытыми авариями: модели склонны галлюцинировать, незаметно путая дни недели или сдвигая интервалы запуска.

Открытая библиотека cronsense от разработчика MrProLopstar (опубликованная в реестре JSR) решает проблему с математической точностью, реализуя полностью детерминированный двусторонний транслятор расписаний для TypeScript и JavaScript.

Лексер, грамматический парсер и ловушки синтаксиса

В основе библиотеки лежит не вероятностное угадывание, а строгий парсер рекурсивного спуска. Лексер разбивает входную строку на лексемы (числа, временные маркеры, интервалы) с сохранением точных координат символов. Специальный словарь основ слов покрывает грамматические падежи русского и английского языков, исключая необходимость тащить тяжелые словари морфологии.

Архитектура корректно разрешает неочевидные ловушки синтаксиса cron:

  1. Конфликт дня недели и дня месяца. По стандарту POSIX поля дня месяца и дня недели объединяются логическим оператором «ИЛИ». Выражение 0 0 1 * 1 сработает и каждый понедельник, и каждое первое число. Библиотека выявляет неоднозначные фразы вроде «по понедельникам 1 числа» и отклоняет их с понятной ошибкой CONFLICT, а не плодит ошибочные интервалы.
  2. Границы интервалов. Фраза «каждые 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, позволяющим подключать эти алгоритмы к ИИ-ассистентам в качестве надежного инструмента планирования без галлюцинаций.