Справочник · формат данных

Синтаксис и форматы

Что принимает поле выражения, какие ошибки оно показывает, как устроены файлы JSON и .ics и как проверить отпечаток. Сетевого API нет: всё, что описано ниже, происходит в вашем браузере.

Принимаемый синтаксис

Принимаемые элементы выражения
элементпримерзначение
Поля30 2 * * *минута 0–59, час 0–23, день месяца 1–31, месяц 1–12, день недели 0–7
Звёздочка*все значения поля; поле со звёздочкой в начале считается неограниченным
Число15одно значение
Диапазон1-5включительно, начало не больше конца
Список0,15,30значения через запятую; элементом может быть диапазон или шаг
Шаг*/15, 10-50/20от начала диапазона: 0, 15, 30, 45 и 10, 30, 50
Именаjan-mar, mon,wed,frijan–dec и sun–sat в любом регистре, в том числе в диапазонах и списках
Воскресенье0, 7оба значения — воскресенье
Макросы@daily@yearly и @annually = 0 0 1 1 *, @monthly = 0 0 1 * *, @weekly = 0 0 * * 0, @daily и @midnight = 0 0 * * *, @hourly = 0 * * * *

Отклоняемый синтаксис

Ошибка в поле показывается на его картуше: картуш краснеет, а под лентой появляется текст с названием поля. Ниже — точные тексты.

Отклоняемые выражения и тексты ошибок
вводтекст ошибки
@reboot@reboot привязан к старту системы, а не ко времени — в ведомость не попадает.
0 0 * * * *Полей 6 — похоже на формат с секундами или годом; здесь пятипольный cron.
0 0 L * *день месяца: «L» — это расширение других планировщиков; CronLens проверяет классический пятипольный cron
0 0 * * 5#3день недели: «5#3» — это расширение других планировщиков; CronLens проверяет классический пятипольный cron
5/10 * * * *минута: шаг пишется после * или диапазона: */10 или 5-59/10
0 24 * * *час: час 24 вне 0–23
*/0 * * * *минута: шаг 0 — шаг должен быть не меньше 1
0 5-2 * * *час: диапазон 5-2 обратный: начало больше конца
0 1,,2 * * *час: пустой элемент списка — лишняя запятая
0 0 * foo *месяц: «foo» — такого имени нет: месяцы пишутся jan–dec
0 0 1Полей 3, а нужно пять: минута, час, день месяца, месяц, день недели.
пустое полеВведите выражение: пять полей через пробел или макрос вроде @daily.
больше 120 символовВыражение длиннее 120 символов.
пояс Europe/MoskvaПояс «Europe/Moskva» не найден в базе браузера. Похожие: Europe/Moscow, … (до трёх подсказок)

Прочие проверки: имя задания — от 1 до 40 символов, без управляющих символов и без повторов; длительность — целое число от 1 до 1440; дата начала окна обязательна. Для имён вроде Etc/GMT-3 рядом с полем появляется напоминание, что знак в них обратный.

Три правила на примере Берлина

Задание 30 2 * * * в поясе Europe/Berlin. 25.10.2026 в 03:00 часы переводят на 02:00 (+02:00 → +01:00), 28.03.2027 в 02:00 — на 03:00 (+01:00 → +02:00).

Результат трёх правил для Берлина
правило25.10.2026, повтор28.03.2027, разрыв
С догономодин раз: 02:30 +02:00 = 00:30Z↷ 03:00 +02:00 = 01:00Z
Пропуск и один разодин раз: 02:30 +02:00 = 00:30Z⊘ потерян
Буквальнодважды: 00:30Z (↺¹) и 01:30Z (↺²)⊘ потерян

Для задания по маске, например */15 2 * * *, «С догоном» ведёт себя иначе: весной четыре запуска 02:00–02:45 потеряны, осенью они выполняются дважды — задание идёт по новым часам.

Файл JSON

Имя файла: cronlens-<образец или check>-<первые 8 hex отпечатка>.json, тип application/json, отступ два пробела. Все числа — целые.

Поля файла JSON
полечто содержит
format, tool"cronlens.vedomost/1", "CronLens"
generated_locallyвсегда true: файл собран в браузере
exported_atмомент скачивания в UTC; в отпечаток не входит
sampleслаг образца или null для своего расчёта
rulecatchup, skip-once или literal
tzdb"Intl браузера" — откуда правила поясов
windowstart_local, zone, start_utc, end_utc, span_days
dial_zone, extra_zonesпояс циферблата и до двух дополнительных поясов
jobs[]id (А–Г), name, expression, class (fixed-time или mask), zone, duration_min, normalized, runs, runs_total, truncated, lost, next_after_window
normalizedсписки minute, hour, dom, month, dow и флаги dom_restricted, dow_restricted
runs[]n, utc, local, offset_min, extra[] (zone, local, offset_min), marks[]
marks[]catchup, repeat-first, repeat-second, repeat-second-skipped, overlap, longer-than-interval
lost[]local и reason: gap или gap-large-shift; такие совпадения не нумеруются и не попадают в .ics
days[]date, zone, length_min — длина суток пояса циферблата
transitions[]zone, utc, from_offset_min, to_offset_min, kind (gap или repeat), local_from, local_to
overlaps[]a, b, start_utc, end_utc, minutes
self_overlaps[]job, count, first_utc
warnings[]kind, job, text — те же замечания, что на странице
fingerprintSHA-256, 64 hex

Фрагмент файла для образца «Ночной архив · осень», правило «С догоном» (многоточием сокращены длинные списки):

{
  "format": "cronlens.vedomost/1",
  "tool": "CronLens",
  "generated_locally": true,
  "sample": "archive-autumn",
  "rule": "catchup",
  "tzdb": "Intl браузера",
  "window": { "start_local": "2026-10-20T00:00", "zone": "Europe/Berlin",
              "start_utc": "2026-10-19T22:00:00Z", "end_utc": "2026-10-26T23:00:00Z", "span_days": 7 },
  "dial_zone": "Europe/Berlin", "extra_zones": [],
  "jobs": [ { "id": "А", "name": "Ночной архив", "expression": "30 2 * * *",
              "class": "fixed-time", "zone": "Europe/Berlin", "duration_min": 45,
              "normalized": { "minute": [30], "hour": [2], "dom": [1, 2, …, 31],
                              "month": [1, 2, …, 12], "dow": [0, 1, …, 6],
                              "dom_restricted": false, "dow_restricted": false },
              "runs": [ …,
                { "n": 6, "utc": "2026-10-25T00:30:00Z", "local": "2026-10-25T02:30",
                  "offset_min": 120, "extra": [],
                  "marks": ["repeat-first", "repeat-second-skipped"] }, … ],
              "runs_total": 7, "truncated": false, "lost": [],
              "next_after_window": "2026-10-27T01:30:00Z" } ],
  "days": [ …, { "date": "2026-10-25", "zone": "Europe/Berlin", "length_min": 1500 }, … ],
  "transitions": [ { "zone": "Europe/Berlin", "utc": "2026-10-25T01:00:00Z",
                     "from_offset_min": 120, "to_offset_min": 60, "kind": "repeat",
                     "local_from": "2026-10-25T03:00", "local_to": "2026-10-25T02:00" } ],
  "overlaps": [], "self_overlaps": [],
  "warnings": [ { "kind": "repeat", "job": "А", "text": "А · Ночной архив: 25.10.2026 в Берлине час 02:00–02:59 проходит дважды …" } ],
  "exported_at": "…",
  "fingerprint": "…"
}

Отпечаток ведомости

Отпечаток — SHA-256 канонической строки: объект JSON без полей fingerprint и exported_at, ключи рекурсивно отсортированы, JSON без пробелов, кодировка UTF-8. Одинаковые входные данные дают одинаковый отпечаток; смена правила, пояса или окна — другой. Момент скачивания и DTSTAMP в .ics в отпечаток не входят.

Проверка скачанного файла на Python (стандартная библиотека; p — путь к файлу):

import json, hashlib
d = json.load(open(p, encoding='utf-8'))
fp = d.pop('fingerprint')
d.pop('exported_at')
s = json.dumps(d, ensure_ascii=False, sort_keys=True, separators=(',', ':'))
print(hashlib.sha256(s.encode()).hexdigest() == fp)

Файл .ics

Имя файла: cronlens-<образец или check>-<ГГГГММДД начала окна>-<N>d.ics, тип text/calendar; charset=utf-8. Строки разделены CRLF и свёрнуты по 75 октетов UTF-8 (продолжение начинается с пробела, кириллица не разрывается). В TEXT экранируются \\, \;, \, и перевод строки \n.

Календарь: VERSION:2.0, PRODID:-//CronLens//Vedomost 1//RU, CALSCALE:GREGORIAN, X-WR-CALNAME:CronLens — <образец или «свой расчёт»>. Одно событие на каждый выполненный запуск, до 1000 событий. Напоминаний (VALARM) нет.

BEGIN:VEVENT
UID:<первые 16 hex отпечатка>-A-6@cronlens.onehots-api.com
DTSTAMP:20260911T120000Z          ← момент экспорта, в отпечаток не входит
DTSTART:20261025T003000Z          ← начало в UTC
DTEND:20261025T011500Z            ← начало + длительность, не меньше 1 мин
SUMMARY:Ночной архив · CronLens
DESCRIPTION:Выражение: 30 2 * * *\nПояс: Europe/Berlin\nМестное время: 2026-10-25 02:30 +02:00\nПравило перевода часов: С догоном\nОтметки: ↺¹ первое прохождение повтора; второе прохождение не выполняется\nОбразец\nРассчитано в браузере
TRANSP:TRANSPARENT                ← событие не занимает время в календаре
END:VEVENT

Буква задания в UID записана латиницей: А → A, Б → B, В → V, Г → G. Номер — порядковый номер запуска задания в окне. В самом файле длинная строка DESCRIPTION свёрнута.

Почему не RRULE и TZID

По RFC 5545 (раздел 3.3.5) время с TZID, попавшее в разрыв, календарь сам сдвигает по смещению до перевода, а в повторе берёт первое прохождение. Правило повтора RRULE разворачивалось бы по этим правилам календаря, а не по правилу вашего планировщика. Поэтому каждый запуск — отдельное событие с точным моментом в UTC, как в ведомости.