cron-explain-ja
Version:
cron式と日本語を相互変換するライブラリ / CLI
1 lines • 161 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","names":["collect"],"sources":["../src/cron/fields.ts","../src/errors.ts","../src/cron/parser.ts","../src/cron/values.ts","../src/cron/next.ts","../src/cron/zone.ts","../src/cron/shift.ts","../src/cron/validate.ts","../src/explain/time.ts","../src/explain/field.ts","../src/explain/compose.ts","../src/explain/index.ts","../src/parse/dictionary.ts","../src/parse/fill.ts","../src/parse/normalize.ts","../src/parse/tokenize.ts","../src/parse/index.ts"],"sourcesContent":["import type { CronField } from \"../types\";\n\nexport interface FieldSpec {\n field: CronField;\n /** エラーメッセージ用の日本語名 */\n label: string;\n /** 展開後の下限 */\n min: number;\n /** 展開後の上限 */\n max: number;\n /** 入力として許容する上限(曜日のみ 7) */\n inputMax: number;\n /** 名前による指定(JAN, MON など) */\n names?: Record<string, number>;\n}\n\nexport const MONTH_NAMES: Record<string, number> = {\n JAN: 1,\n FEB: 2,\n MAR: 3,\n APR: 4,\n MAY: 5,\n JUN: 6,\n JUL: 7,\n AUG: 8,\n SEP: 9,\n OCT: 10,\n NOV: 11,\n DEC: 12,\n};\n\nexport const DOW_NAMES: Record<string, number> = {\n SUN: 0,\n MON: 1,\n TUE: 2,\n WED: 3,\n THU: 4,\n FRI: 5,\n SAT: 6,\n};\n\nexport const SECOND_SPEC: FieldSpec = {\n field: \"second\",\n label: \"秒\",\n min: 0,\n max: 59,\n inputMax: 59,\n};\nexport const MINUTE_SPEC: FieldSpec = {\n field: \"minute\",\n label: \"分\",\n min: 0,\n max: 59,\n inputMax: 59,\n};\nexport const HOUR_SPEC: FieldSpec = { field: \"hour\", label: \"時\", min: 0, max: 23, inputMax: 23 };\nexport const DOM_SPEC: FieldSpec = {\n field: \"dayOfMonth\",\n label: \"日\",\n min: 1,\n max: 31,\n inputMax: 31,\n};\nexport const MONTH_SPEC: FieldSpec = {\n field: \"month\",\n label: \"月\",\n min: 1,\n max: 12,\n inputMax: 12,\n names: MONTH_NAMES,\n};\nexport const DOW_SPEC: FieldSpec = {\n field: \"dayOfWeek\",\n label: \"曜日\",\n min: 0,\n max: 6,\n inputMax: 7,\n names: DOW_NAMES,\n};\n\n/** 5 フィールド式の並び */\nexport const FIELD_SPECS: FieldSpec[] = [MINUTE_SPEC, HOUR_SPEC, DOM_SPEC, MONTH_SPEC, DOW_SPEC];\n\n/** 6 フィールド(秒付き)式の並び */\nexport const FIELD_SPECS_WITH_SECONDS: FieldSpec[] = [SECOND_SPEC, ...FIELD_SPECS];\n\nexport const MACROS: Record<string, string> = {\n \"@yearly\": \"0 0 1 1 *\",\n \"@annually\": \"0 0 1 1 *\",\n \"@monthly\": \"0 0 1 * *\",\n \"@weekly\": \"0 0 * * 0\",\n \"@daily\": \"0 0 * * *\",\n \"@midnight\": \"0 0 * * *\",\n \"@hourly\": \"0 * * * *\",\n};\n\n/**\n * crontab では有効だが、実行タイミングが日時で決まらないため説明できない指定。\n * 値はエラーメッセージに使う理由。\n */\nexport const UNSCHEDULABLE_MACROS: Record<string, string> = {\n \"@reboot\": \"起動時に一度だけ実行される指定で、日時を持たないため説明できません\",\n};\n\nexport const DOW_LABELS = [\"日曜日\", \"月曜日\", \"火曜日\", \"水曜日\", \"木曜日\", \"金曜日\", \"土曜日\"];\n","import type { CronField, ParseResult } from \"./types\";\n\n/**\n * cron 式の構文エラー。\n */\nexport class CronSyntaxError extends Error {\n readonly field?: CronField;\n readonly position?: number;\n\n constructor(message: string, options: { field?: CronField; position?: number } = {}) {\n super(message);\n this.name = \"CronSyntaxError\";\n if (options.field !== undefined) this.field = options.field;\n if (options.position !== undefined) this.position = options.position;\n }\n}\n\n/**\n * `parse({ strict: true })` で解釈が曖昧だったときに投げられる。\n */\nexport class ParseAmbiguityError extends Error {\n readonly result: ParseResult;\n\n constructor(message: string, result: ParseResult) {\n super(message);\n this.name = \"ParseAmbiguityError\";\n this.result = result;\n }\n}\n\n/**\n * タイムゾーン名を解釈できなかったときに投げられる。\n */\nexport class CronTimeZoneError extends Error {\n /** 与えられたゾーン名 */\n readonly timeZone: string;\n\n constructor(message: string, timeZone: string) {\n super(message);\n this.name = \"CronTimeZoneError\";\n this.timeZone = timeZone;\n }\n}\n","import { CronSyntaxError } from \"../errors\";\nimport type { CronAST, CronExtension, CronField, FieldAST, ParserOptions } from \"../types\";\nimport {\n FIELD_SPECS,\n FIELD_SPECS_WITH_SECONDS,\n type FieldSpec,\n MACROS,\n UNSCHEDULABLE_MACROS,\n} from \"./fields\";\n\nexport interface ParsedExpression {\n ast: CronAST;\n /** フィールドごとの入力文字列(正規化前) */\n raw: {\n seconds?: string;\n minute: string;\n hour: string;\n dayOfMonth: string;\n month: string;\n dayOfWeek: string;\n };\n /** 使用されている拡張構文 */\n extensions: CronExtension[];\n /** マクロが展開された場合、その元の表記 */\n macro?: string;\n}\n\ninterface Part {\n text: string;\n offset: number;\n}\n\n/** カンマ区切りで位置情報を保ったまま分割する */\nfunction splitParts(text: string, offset: number, separator: string): Part[] {\n const parts: Part[] = [];\n let start = 0;\n for (let i = 0; i <= text.length; i++) {\n if (i === text.length || text[i] === separator) {\n parts.push({ text: text.slice(start, i), offset: offset + start });\n start = i + 1;\n }\n }\n return parts;\n}\n\n/** 曜日の 7 は日曜(0)と同じ値を指す */\nfunction normalizeWeekday(value: number, spec: FieldSpec): number {\n return spec.field === \"dayOfWeek\" && value === 7 ? 0 : value;\n}\n\n/** 書かれたままの値を読む。曜日の 7 は 0 に畳まない */\nfunction parseNumber(text: string, spec: FieldSpec, position: number): number {\n const upper = text.toUpperCase();\n const named = spec.names?.[upper];\n if (named !== undefined) return named;\n\n if (!/^\\d{1,2}$/.test(text)) {\n throw new CronSyntaxError(`${spec.label} フィールドの値 '${text}' を解釈できません`, {\n field: spec.field,\n position,\n });\n }\n const value = Number(text);\n if (value < spec.min || value > spec.inputMax) {\n throw new CronSyntaxError(\n `${spec.label} フィールドの値 ${value} は範囲外です (${spec.min}-${spec.inputMax})`,\n { field: spec.field, position },\n );\n }\n return value;\n}\n\n/** 値を読んで、曜日の 7 を 0 に正規化する */\nfunction parseValue(text: string, spec: FieldSpec, position: number): number {\n return normalizeWeekday(parseNumber(text, spec, position), spec);\n}\n\nfunction parseAtom(text: string, spec: FieldSpec, position: number): FieldAST {\n if (text === \"\") {\n throw new CronSyntaxError(`${spec.label} フィールドが空です`, {\n field: spec.field,\n position,\n });\n }\n if (text === \"*\") return { kind: \"any\" };\n\n if (text === \"?\") {\n if (spec.field !== \"dayOfMonth\" && spec.field !== \"dayOfWeek\") {\n throw new CronSyntaxError(`'?' は日・曜日フィールドでのみ使用できます`, {\n field: spec.field,\n position,\n });\n }\n return { kind: \"noSpecific\" };\n }\n\n if (spec.field === \"dayOfMonth\") {\n if (text === \"L\") return { kind: \"last\" };\n const lastOffset = /^L-(\\d{1,2})$/.exec(text);\n if (lastOffset?.[1] !== undefined) {\n const offset = Number(lastOffset[1]);\n if (offset > 30) {\n throw new CronSyntaxError(`'L-${offset}' のオフセットは 0-30 の範囲で指定してください`, {\n field: spec.field,\n position,\n });\n }\n return { kind: \"last\", offset };\n }\n const nearest = /^(\\d{1,2})W$/i.exec(text);\n if (nearest?.[1] !== undefined) {\n return { kind: \"nearestWeekday\", day: parseValue(nearest[1], spec, position) };\n }\n }\n\n if (spec.field === \"dayOfWeek\") {\n const hash = text.indexOf(\"#\");\n if (hash >= 0) {\n const weekday = parseValue(text.slice(0, hash), spec, position);\n const nthText = text.slice(hash + 1);\n if (!/^[1-5]$/.test(nthText)) {\n throw new CronSyntaxError(`'#' の後は 1-5 で指定してください`, {\n field: spec.field,\n position: position + hash + 1,\n });\n }\n return { kind: \"nth\", weekday, nth: Number(nthText) };\n }\n if (/^.+L$/i.test(text)) {\n const weekday = parseValue(text.slice(0, -1), spec, position);\n return { kind: \"nth\", weekday, nth: -1 };\n }\n if (text.toUpperCase() === \"L\") {\n throw new CronSyntaxError(`曜日フィールドの 'L' は '5L' のように曜日と組み合わせてください`, {\n field: spec.field,\n position,\n });\n }\n }\n\n const dash = text.indexOf(\"-\");\n if (dash > 0) {\n const from = parseNumber(text.slice(0, dash), spec, position);\n const to = parseNumber(text.slice(dash + 1), spec, position + dash + 1);\n // `0-7` は「日曜から日曜まで」ではなく全曜日。7 を先に 0 へ畳むと幅が消えてしまうので、\n // ここだけは正規化前の 7 を見て全域の範囲に読み替える。\n // `1-7` のように始まりが 0 でない場合は、`1-0` の循環範囲が同じ集合を指すので畳んでよい\n if (spec.field === \"dayOfWeek\" && from === spec.min && to === spec.inputMax) {\n return { kind: \"range\", from: spec.min, to: spec.max };\n }\n return {\n kind: \"range\",\n from: normalizeWeekday(from, spec),\n to: normalizeWeekday(to, spec),\n };\n }\n\n return { kind: \"value\", value: parseValue(text, spec, position) };\n}\n\nfunction parseItem(text: string, spec: FieldSpec, position: number): FieldAST {\n const slash = text.indexOf(\"/\");\n if (slash < 0) return parseAtom(text, spec, position);\n\n const stepText = text.slice(slash + 1);\n if (!/^\\d{1,2}$/.test(stepText)) {\n throw new CronSyntaxError(`${spec.label} フィールドの刻み幅 '${stepText}' を解釈できません`, {\n field: spec.field,\n position: position + slash + 1,\n });\n }\n const step = Number(stepText);\n if (step < 1) {\n throw new CronSyntaxError(`${spec.label} フィールドの刻み幅は 1 以上で指定してください`, {\n field: spec.field,\n position: position + slash + 1,\n });\n }\n\n const baseText = text.slice(0, slash);\n const base = parseAtom(baseText === \"\" ? \"*\" : baseText, spec, position);\n if (base.kind === \"value\") {\n // `5/15` は「5 から上限まで 15 刻み」の意味。`5-<上限>` と書いたのと同じなので、\n // 範囲として読み直す。こうすると曜日の `7`(日曜)や `0-7`(全曜日)の扱いが\n // `a-b` と揃う。`base.value` は正規化済みなのでそのままでは 7 が 0 に潰れてしまう\n return { kind: \"step\", base: parseAtom(`${baseText}-${spec.inputMax}`, spec, position), step };\n }\n if (base.kind !== \"any\" && base.kind !== \"range\") {\n throw new CronSyntaxError(`${spec.label} フィールドの刻みは '*' か範囲にのみ指定できます`, {\n field: spec.field,\n position,\n });\n }\n return { kind: \"step\", base, step };\n}\n\nfunction parseField(text: string, spec: FieldSpec, offset: number): FieldAST {\n const parts = splitParts(text, offset, \",\");\n const items = parts.map((part) => parseItem(part.text, spec, part.offset));\n const first = items[0];\n if (first === undefined) {\n throw new CronSyntaxError(`${spec.label} フィールドが空です`, {\n field: spec.field,\n position: offset,\n });\n }\n if (items.length === 1) return first;\n return { kind: \"list\", items };\n}\n\nfunction collectExtensions(ast: FieldAST, into: Set<CronExtension>): void {\n switch (ast.kind) {\n case \"last\":\n into.add(\"L\");\n break;\n case \"nth\":\n into.add(ast.nth === -1 ? \"L\" : \"#\");\n break;\n case \"nearestWeekday\":\n into.add(\"W\");\n break;\n case \"noSpecific\":\n into.add(\"?\");\n break;\n case \"list\":\n for (const item of ast.items) collectExtensions(item, into);\n break;\n case \"step\":\n collectExtensions(ast.base, into);\n break;\n default:\n break;\n }\n}\n\n/**\n * cron 式を構文解析する。不正な式は {@link CronSyntaxError} を投げる。\n */\nexport function parseExpression(expression: string, options: ParserOptions = {}): ParsedExpression {\n if (typeof expression !== \"string\") {\n throw new CronSyntaxError(\"cron 式は文字列で指定してください\");\n }\n const trimmed = expression.trim();\n if (trimmed === \"\") {\n throw new CronSyntaxError(\"cron 式が空です\");\n }\n\n let source = trimmed;\n let macro: string | undefined;\n if (source.startsWith(\"@\")) {\n // crontab の行は「@daily <コマンド>」の形を取り、マクロは常に先頭の 1 トークン。\n // 数値のフィールドと違って区切りが曖昧にならないので、残りはコマンドとして捨てる\n const token = /^\\S+/.exec(source)?.[0] ?? source;\n const lower = token.toLowerCase();\n const expanded = MACROS[lower];\n if (expanded === undefined) {\n const reason = UNSCHEDULABLE_MACROS[lower];\n if (reason !== undefined) {\n throw new CronSyntaxError(`'${token}' は${reason}`, { position: 0 });\n }\n throw new CronSyntaxError(`マクロ '${token}' には対応していません`, { position: 0 });\n }\n macro = token;\n source = expanded;\n }\n\n const specs = options.seconds === true ? FIELD_SPECS_WITH_SECONDS : FIELD_SPECS;\n const fields: Part[] = [];\n const re = /\\S+/g;\n let match = re.exec(source);\n while (match !== null) {\n fields.push({ text: match[0], offset: match.index });\n match = re.exec(source);\n }\n\n if (fields.length !== specs.length) {\n const hint =\n fields.length === 6 && options.seconds !== true\n ? \"。秒付きの式は seconds オプションを有効にしてください\"\n : \"\";\n throw new CronSyntaxError(\n `フィールド数が不正です(${specs.length} 個必要ですが ${fields.length} 個でした)${hint}`,\n { position: 0 },\n );\n }\n\n interface Entry {\n spec: FieldSpec;\n part: Part;\n ast: FieldAST;\n }\n const parsed: Entry[] = specs.map((spec, index) => {\n const part = fields[index];\n /* c8 ignore next -- fields.length === specs.length を確認済み */\n if (part === undefined) throw new CronSyntaxError(\"フィールド数が不正です\");\n return { spec, part, ast: parseField(part.text, spec, part.offset) };\n });\n\n const byField = new Map<CronField, Entry>(parsed.map((entry) => [entry.spec.field, entry]));\n const get = (field: CronField): Entry => {\n const entry = byField.get(field);\n /* c8 ignore next -- specs は必ず全フィールドを含む */\n if (entry === undefined) throw new CronSyntaxError(\"フィールドが不足しています\");\n return entry;\n };\n\n const minute = get(\"minute\");\n const hour = get(\"hour\");\n const dayOfMonth = get(\"dayOfMonth\");\n const month = get(\"month\");\n const dayOfWeek = get(\"dayOfWeek\");\n const seconds = options.seconds === true ? get(\"second\") : undefined;\n\n const ast: CronAST = {\n minute: minute.ast,\n hour: hour.ast,\n dayOfMonth: dayOfMonth.ast,\n month: month.ast,\n dayOfWeek: dayOfWeek.ast,\n };\n if (seconds !== undefined) ast.seconds = seconds.ast;\n\n const extensions = new Set<CronExtension>();\n for (const entry of parsed) collectExtensions(entry.ast, extensions);\n\n const result: ParsedExpression = {\n ast,\n raw: {\n minute: minute.part.text,\n hour: hour.part.text,\n dayOfMonth: dayOfMonth.part.text,\n month: month.part.text,\n dayOfWeek: dayOfWeek.part.text,\n },\n extensions: [...extensions],\n };\n if (seconds !== undefined) result.raw.seconds = seconds.part.text;\n if (macro !== undefined) result.macro = macro;\n return result;\n}\n","import type { CronAST, FieldAST } from \"../types\";\nimport type { FieldSpec } from \"./fields\";\n\n/** 値に展開できない拡張構文(L / # / W)を含むか。`?` は制約なしなので含めない */\nexport function hasExtension(ast: FieldAST): boolean {\n switch (ast.kind) {\n case \"last\":\n case \"nth\":\n case \"nearestWeekday\":\n return true;\n case \"list\":\n return ast.items.some(hasExtension);\n case \"step\":\n return hasExtension(ast.base);\n default:\n return false;\n }\n}\n\n/** `*` あるいは `?`(=制約なし)か */\nexport function isAny(ast: FieldAST): boolean {\n if (ast.kind === \"any\" || ast.kind === \"noSpecific\") return true;\n if (ast.kind === \"step\") return ast.step === 1 && isAny(ast.base);\n return false;\n}\n\n/** 表記は違っても、そのフィールドの全値を含むか(`0-6` など) */\nexport function coversAll(ast: FieldAST, spec: FieldSpec): boolean {\n if (isAny(ast)) return true;\n if (hasExtension(ast)) return false;\n return expandField(ast, spec).length === spec.max - spec.min + 1;\n}\n\n/**\n * フィールドの全域に対する刻みなら、その刻み幅を返す。\n * `0-59/5` のように範囲が全域を覆う場合を含み、`*` を base にしたものと同じ意味になる。\n */\nexport function fullRangeStep(ast: FieldAST, spec: FieldSpec): number | undefined {\n if (ast.kind !== \"step\") return undefined;\n const base = ast.base;\n // 刻みは base の下限を起点に数えるため、全値を含んでいても起点が min でなければ\n // `*` とは値が違う。`1-0/2` は循環して全値を含むが 1,3,5… であり `*/2` ではない\n const fromMin =\n isAny(base) || (base.kind === \"range\" && base.from === spec.min && base.to === spec.max);\n if (!fromMin) return undefined;\n // 幅を超える刻みは実際には起点で 1 回動くだけなので、「Nごと」とは説明しない\n if (ast.step > spec.max - spec.min) return undefined;\n return ast.step;\n}\n\n/**\n * 「AからBまでNごと」と説明できる刻みなら、その範囲と刻み幅を返す。\n * 幅を超える刻みは起点で 1 回動くだけなので、範囲としては説明しない。\n */\nexport function rangeStep(\n ast: FieldAST,\n spec: FieldSpec,\n): { from: number; to: number; step: number } | undefined {\n if (ast.kind !== \"step\" || ast.base.kind !== \"range\") return undefined;\n const { from, to } = ast.base;\n const span = spec.max - spec.min + 1;\n const width = from <= to ? to - from : span - from + to;\n if (ast.step > width) return undefined;\n return { from, to, step: ast.step };\n}\n\nfunction rangeValues(from: number, to: number, spec: FieldSpec, step: number): number[] {\n const values: number[] = [];\n const span = spec.max - spec.min + 1;\n // from > to は循環範囲(例: 金-月 = 5-1)として扱う\n const length = from <= to ? to - from + 1 : span - from + to + 1;\n for (let i = 0; i < length; i += step) {\n values.push(spec.min + ((from - spec.min + i) % span));\n }\n return values;\n}\n\n/**\n * フィールドの構文木を実際の値へ展開する。\n * 拡張構文(L / # / W)は静的に展開できないため空配列を返す。\n */\nexport function expandField(ast: FieldAST, spec: FieldSpec): number[] {\n const values = collect(ast, spec);\n return [...new Set(values)].sort((a, b) => a - b);\n}\n\nfunction collect(ast: FieldAST, spec: FieldSpec): number[] {\n switch (ast.kind) {\n case \"any\":\n case \"noSpecific\":\n return rangeValues(spec.min, spec.max, spec, 1);\n case \"value\":\n return [ast.value];\n case \"range\":\n return rangeValues(ast.from, ast.to, spec, 1);\n case \"step\": {\n const base = ast.base;\n if (base.kind === \"range\") return rangeValues(base.from, base.to, spec, ast.step);\n return rangeValues(spec.min, spec.max, spec, ast.step);\n }\n case \"list\":\n return ast.items.flatMap((item) => collect(item, spec));\n default:\n return [];\n }\n}\n\n/** 構文木を正規化された cron 表記へ戻す */\nexport function formatField(ast: FieldAST): string {\n switch (ast.kind) {\n case \"any\":\n return \"*\";\n case \"noSpecific\":\n return \"?\";\n case \"value\":\n return String(ast.value);\n case \"range\":\n return `${ast.from}-${ast.to}`;\n case \"step\":\n return `${formatField(ast.base)}/${ast.step}`;\n case \"list\":\n return ast.items.map(formatField).join(\",\");\n case \"last\":\n return ast.offset === undefined ? \"L\" : `L-${ast.offset}`;\n case \"nth\":\n return ast.nth === -1 ? `${ast.weekday}L` : `${ast.weekday}#${ast.nth}`;\n case \"nearestWeekday\":\n return `${ast.day}W`;\n }\n}\n\n/** 連続した値の並びを範囲に畳む([1,2,3,5] → [[1,3],[5,5]]) */\nexport function toRanges(values: number[]): Array<[number, number]> {\n const ranges: Array<[number, number]> = [];\n for (const value of values) {\n const last = ranges[ranges.length - 1];\n if (last !== undefined && value === last[1] + 1) {\n last[1] = value;\n } else {\n ranges.push([value, value]);\n }\n }\n return ranges;\n}\n\n/** 構文木を正規化された cron 式へ戻す */\nexport function formatExpression(ast: CronAST): string {\n const fields = [ast.minute, ast.hour, ast.dayOfMonth, ast.month, ast.dayOfWeek].map(formatField);\n if (ast.seconds !== undefined) fields.unshift(formatField(ast.seconds));\n return fields.join(\" \");\n}\n","import type { NextOptions } from \"../types\";\nimport { DOM_SPEC, DOW_SPEC, HOUR_SPEC, MINUTE_SPEC, MONTH_SPEC, SECOND_SPEC } from \"./fields\";\nimport { parseExpression } from \"./parser\";\nimport { expandField, isAny } from \"./values\";\n\ninterface Parts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n dayOfWeek: number;\n}\n\n/** 瞬間 → UTC の壁時計 */\nfunction partsOf(date: Date): Parts {\n return {\n year: date.getUTCFullYear(),\n month: date.getUTCMonth() + 1,\n day: date.getUTCDate(),\n hour: date.getUTCHours(),\n minute: date.getUTCMinutes(),\n second: date.getUTCSeconds(),\n dayOfWeek: date.getUTCDay(),\n };\n}\n\n/** UTC の壁時計 → 瞬間。範囲外の値(13 月・32 日・24 時など)は繰り上がる */\nfunction dateOf(\n year: number,\n month: number,\n day: number,\n hour: number,\n minute: number,\n second: number,\n): Date {\n return new Date(Date.UTC(year, month - 1, day, hour, minute, second, 0));\n}\n\n/** sorted の中で value 以上の最小値。無ければ null */\nfunction atLeast(sorted: number[], value: number): number | null {\n for (const candidate of sorted) {\n if (candidate >= value) return candidate;\n }\n return null;\n}\n\n/** 5 年先まで探索する */\nconst SEARCH_YEARS = 5;\n\n/** 無限ループを避けるための保険 */\nconst MAX_ITERATIONS = 2_000_000;\n\n/**\n * cron 式の次回実行日時を求める。\n *\n * cron 式は UTC のサーバーで動くものとして解釈する。返るのは絶対時刻なので、\n * どのタイムゾーンで表示するかは呼び出し側の裁量。\n *\n * `L` / `#` / `W` を含む式は v1 では計算対象外で、空配列を返す。\n */\nexport function next(expression: string, options: NextOptions = {}): Date[] {\n const parserOptions = options.seconds === true ? { seconds: true } : {};\n const parsed = parseExpression(expression, parserOptions);\n if (parsed.extensions.some((extension) => extension !== \"?\")) return [];\n\n const count = options.count ?? 3;\n if (count <= 0) return [];\n\n const from = options.from ?? new Date();\n if (Number.isNaN(from.getTime())) return [];\n\n const ast = parsed.ast;\n const seconds = ast.seconds === undefined ? [0] : expandField(ast.seconds, SECOND_SPEC);\n const minutes = expandField(ast.minute, MINUTE_SPEC);\n const hours = expandField(ast.hour, HOUR_SPEC);\n const months = expandField(ast.month, MONTH_SPEC);\n const days = expandField(ast.dayOfMonth, DOM_SPEC);\n const weekdays = expandField(ast.dayOfWeek, DOW_SPEC);\n if ([seconds, minutes, hours, months].some((values) => values.length === 0)) return [];\n\n const domRestricted = !isAny(ast.dayOfMonth);\n const dowRestricted = !isAny(ast.dayOfWeek);\n const daySet = new Set(days);\n const weekdaySet = new Set(weekdays);\n const monthSet = new Set(months);\n\n const dayMatches = (parts: Parts): boolean => {\n if (domRestricted && dowRestricted) {\n return daySet.has(parts.day) || weekdaySet.has(parts.dayOfWeek);\n }\n if (domRestricted) return daySet.has(parts.day);\n if (dowRestricted) return weekdaySet.has(parts.dayOfWeek);\n return true;\n };\n\n const startParts = partsOf(from);\n const limitYear = startParts.year + SEARCH_YEARS;\n\n // 起点そのものは含めないので 1 秒進めてから秒に丸める\n const initial = partsOf(new Date(from.getTime() + 1000));\n let cursor = dateOf(\n initial.year,\n initial.month,\n initial.day,\n initial.hour,\n initial.minute,\n initial.second,\n );\n\n const results: Date[] = [];\n let iterations = 0;\n while (results.length < count && iterations < MAX_ITERATIONS) {\n iterations += 1;\n const parts = partsOf(cursor);\n if (parts.year > limitYear) break;\n\n if (!monthSet.has(parts.month)) {\n cursor = dateOf(parts.year, parts.month + 1, 1, 0, 0, 0);\n continue;\n }\n if (!dayMatches(parts)) {\n cursor = dateOf(parts.year, parts.month, parts.day + 1, 0, 0, 0);\n continue;\n }\n const hour = atLeast(hours, parts.hour);\n if (hour === null) {\n cursor = dateOf(parts.year, parts.month, parts.day + 1, 0, 0, 0);\n continue;\n }\n if (hour !== parts.hour) {\n cursor = dateOf(parts.year, parts.month, parts.day, hour, 0, 0);\n continue;\n }\n const minute = atLeast(minutes, parts.minute);\n if (minute === null) {\n cursor = dateOf(parts.year, parts.month, parts.day, parts.hour + 1, 0, 0);\n continue;\n }\n if (minute !== parts.minute) {\n cursor = dateOf(parts.year, parts.month, parts.day, parts.hour, minute, 0);\n continue;\n }\n const second = atLeast(seconds, parts.second);\n if (second === null) {\n cursor = dateOf(parts.year, parts.month, parts.day, parts.hour, parts.minute + 1, 0);\n continue;\n }\n if (second !== parts.second) {\n cursor = dateOf(parts.year, parts.month, parts.day, parts.hour, parts.minute, second);\n continue;\n }\n\n results.push(new Date(cursor.getTime()));\n cursor = new Date(cursor.getTime() + 1000);\n }\n\n return results;\n}\n","import { CronTimeZoneError } from \"../errors\";\n\n/**\n * 自然言語(日本語)側の既定のタイムゾーン。\n *\n * cron 式は常に UTC のサーバーで動くものとして扱い、日本語はこのゾーンの壁時計として読む。\n */\nexport const DEFAULT_TIME_ZONE = \"Asia/Tokyo\";\n\n/** 実行環境のタイムゾーンを指す特別な値 */\nexport const LOCAL_TIME_ZONE = \"local\";\n\n/** cron 式が動くサーバーのタイムゾーン。固定 */\nexport const SERVER_TIME_ZONE = \"UTC\";\n\n/**\n * ある瞬間をタイムゾーンで読んだ壁時計。\n */\nexport interface WallClock {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n dayOfWeek: number;\n}\n\n/** Intl.DateTimeFormat の生成は重いのでゾーンごとに使い回す */\nconst formatters = new Map<string, Intl.DateTimeFormat>();\n\nfunction formatter(timeZone: string): Intl.DateTimeFormat {\n const cached = formatters.get(timeZone);\n if (cached !== undefined) return cached;\n const created = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n // hour12: false は環境によって 0 時を 24 と読ませるため h23 を使う\n hourCycle: \"h23\",\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n formatters.set(timeZone, created);\n return created;\n}\n\n/**\n * `'local'` を実行環境のゾーン名に、未指定を {@link DEFAULT_TIME_ZONE} に解決し、\n * IANA の正規名に揃えて返す。\n *\n * @throws {CronTimeZoneError} 実行環境が知らないゾーン名の場合\n */\nexport function resolveTimeZone(tz?: string): string {\n if (tz === undefined) return DEFAULT_TIME_ZONE;\n const requested =\n tz === LOCAL_TIME_ZONE ? new Intl.DateTimeFormat().resolvedOptions().timeZone : tz;\n try {\n return new Intl.DateTimeFormat(\"en-US\", { timeZone: requested }).resolvedOptions().timeZone;\n } catch {\n throw new CronTimeZoneError(`タイムゾーン '${tz}' を解釈できません`, tz);\n }\n}\n\n/** 壁時計を UTC とみなしたミリ秒 */\nfunction asUtc(wall: WallClock): number {\n return Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour, wall.minute, wall.second);\n}\n\n/** その瞬間の壁時計と、そのときのゾーンオフセット(分) */\nexport function wallClockWithOffset(\n timeZone: string,\n date: Date,\n): { wall: WallClock; offset: number } {\n const found: Record<string, string> = {};\n for (const part of formatter(timeZone).formatToParts(date)) {\n if (part.type !== \"literal\") found[part.type] = part.value;\n }\n const year = Number(found.year);\n const month = Number(found.month);\n const day = Number(found.day);\n const wall: WallClock = {\n year,\n month,\n day,\n // h23 でも 24 を返す実装が過去にあったため丸めておく\n hour: Number(found.hour) % 24,\n minute: Number(found.minute),\n second: Number(found.second),\n // 曜日は暦から求める。ICU の短縮形に依存すると、読めない綴りを黙って日曜にしてしまう\n dayOfWeek: new Date(Date.UTC(year, month - 1, day)).getUTCDay(),\n };\n return { wall, offset: (asUtc(wall) - Math.floor(date.getTime() / 1000) * 1000) / 60_000 };\n}\n\n/** その瞬間のゾーンオフセット(分)。UTC より東が正 */\nfunction offsetMinutes(timeZone: string, date: Date): number {\n return wallClockWithOffset(timeZone, date).offset;\n}\n\n/**\n * 壁時計 → 瞬間。オフセットを 2 回反復して収束させる。\n *\n * 夏時間の境界にあたる壁時計では厳密には決まらないが、探索の起点にしか使わないので\n * 近い側に寄せれば足りる。\n */\nexport function instantAt(\n timeZone: string,\n year: number,\n month: number,\n day: number,\n hour: number,\n minute: number,\n second: number,\n): Date {\n const guess = Date.UTC(year, month - 1, day, hour, minute, second);\n const first = guess - offsetMinutes(timeZone, new Date(guess)) * 60_000;\n return new Date(guess - offsetMinutes(timeZone, new Date(first)) * 60_000);\n}\n\nconst fixedOffsets = new Map<string, number>();\n\n/**\n * 変わらないゾーンオフセット(分)を返す。\n *\n * cron 式の書き換えは固定のオフセットでしか行えないため、オフセットが動くゾーンは\n * ここで弾く。書き換えた式は crontab に貼られたあと何年も動き続けるので、\n * 今年だけでなく**翌年まで**を 1 か月ごとにサンプルして、すべて同じであることを確かめる\n * (夏時間を来年から始める国を今年のぶんだけ見て通すと、半年ずれた式を黙って出すことになる)。\n *\n * @throws {CronTimeZoneError} 期間内でオフセットが変わる場合\n */\nexport function fixedOffsetMinutes(timeZone: string, reference: Date = new Date()): number {\n const year = reference.getUTCFullYear();\n const key = `${timeZone}@${year}`;\n const cached = fixedOffsets.get(key);\n if (cached !== undefined) return cached;\n\n const offsets = new Set<number>();\n for (let month = 0; month < 24; month += 1) {\n offsets.add(offsetMinutes(timeZone, new Date(Date.UTC(year, month, 15, 12))));\n }\n const [offset] = [...offsets];\n if (offsets.size > 1 || offset === undefined) {\n throw new CronTimeZoneError(\n `${timeZone} は ${year}-${year + 1} 年にオフセットが変わる(夏時間など)ため、` +\n \"cron 式を固定のオフセットに書き換えられません\",\n timeZone,\n );\n }\n fixedOffsets.set(key, offset);\n return offset;\n}\n","import { CronTimeZoneError } from \"../errors\";\nimport type { CronAST, FieldAST, ParserOptions } from \"../types\";\nimport { DOM_SPEC, DOW_SPEC, type FieldSpec, HOUR_SPEC, MINUTE_SPEC, MONTH_SPEC } from \"./fields\";\nimport { parseExpression } from \"./parser\";\nimport { coversAll, expandField, formatExpression, hasExtension, isAny, toRanges } from \"./values\";\nimport { fixedOffsetMinutes, SERVER_TIME_ZONE } from \"./zone\";\n\n/**\n * 書き換えの向き。\n * - `'toLocal'`: cron 式(UTC) → `timeZone` の壁時計(explain)\n * - `'toServer'`: `timeZone` の壁時計 → cron 式(UTC)(parse)\n */\nexport type ShiftDirection = \"toLocal\" | \"toServer\";\n\nconst MINUTES_PER_DAY = 1440;\n\n/** 日をまたぐ書き換えが月の長さに左右されないのは 1-28 日の範囲だけ */\nconst SAFE_DAY_MIN = 1;\nconst SAFE_DAY_MAX = 28;\n\nfunction mod(value: number, size: number): number {\n return ((value % size) + size) % size;\n}\n\nfunction sorted(values: Iterable<number>): number[] {\n return [...new Set(values)].sort((a, b) => a - b);\n}\n\nfunction sameValues(left: number[], right: number[]): boolean {\n return left.length === right.length && left.every((value, index) => value === right[index]);\n}\n\n/** 「+9:00」「-4:30」 */\nfunction formatOffset(minutes: number): string {\n const absolute = Math.abs(minutes);\n const hour = Math.floor(absolute / 60);\n const minute = absolute % 60;\n return `${minutes < 0 ? \"-\" : \"+\"}${hour}:${String(minute).padStart(2, \"0\")}`;\n}\n\n/**\n * 値の並びから、なるべく自然な構文木を組み立てる。\n *\n * 連番は範囲に、等間隔は刻みに畳む。説明文の質がここで決まる\n * (`1,3,5,…,23` を並べ立てず `1-23/2` にする)。\n */\nfunction fromValues(values: number[], spec: FieldSpec): FieldAST {\n const first = values[0];\n const last = values[values.length - 1];\n /* c8 ignore next -- 呼び出し側が空配列を渡さない */\n if (first === undefined || last === undefined) return { kind: \"any\" };\n if (values.length === spec.max - spec.min + 1) return { kind: \"any\" };\n if (values.length === 1) return { kind: \"value\", value: first };\n\n const step = (values[1] as number) - first;\n const evenlySpaced =\n values.length > 2 &&\n step > 1 &&\n values.every((value, index) => index === 0 || value - (values[index - 1] as number) === step);\n if (evenlySpaced) {\n // 下限から刻んで上限に届いているなら `*/N`。`0-22/2` より `*/2` の方が説明しやすい\n const fromMin = first === spec.min && last + step > spec.max;\n const base: FieldAST = fromMin ? { kind: \"any\" } : { kind: \"range\", from: first, to: last };\n return { kind: \"step\", base, step };\n }\n\n const items = toRanges(values).map(\n ([from, to]): FieldAST =>\n from === to ? { kind: \"value\", value: from } : { kind: \"range\", from, to },\n );\n return items.length === 1 ? (items[0] as FieldAST) : { kind: \"list\", items };\n}\n\n/**\n * cron 式(UTC) と `timeZone` の壁時計の間で、フィールドをずらす。\n *\n * cron 式は「フィールドごとに独立した値の集合」しか表せないので、ずらした結果が\n * その形に収まらない場合は書き換えられない。収まらないまま近い式を返すと、\n * 半年ずれた予定を黙って出すことになるため {@link CronTimeZoneError} で失敗させる。\n *\n * @throws {CronTimeZoneError} ゾーンのオフセットが動く、または結果が cron 式で表せない場合\n */\nexport function shiftAst(ast: CronAST, timeZone: string, direction: ShiftDirection): CronAST {\n // UTC のままなら書き換えも夏時間の検査も要らない\n if (timeZone === SERVER_TIME_ZONE) return ast;\n\n const zoneOffset = fixedOffsetMinutes(timeZone);\n const deltaMinutes = direction === \"toLocal\" ? zoneOffset : -zoneOffset;\n if (deltaMinutes === 0) return ast;\n\n // 表示するのは常にゾーンのオフセット。向きによって符号が変わると読み手が混乱する\n const offset = formatOffset(zoneOffset);\n const fail = (reason: string): never => {\n throw new CronTimeZoneError(`${timeZone}(時差 ${offset})では${reason}`, timeZone);\n };\n\n const minutes = expandField(ast.minute, MINUTE_SPEC);\n const hours = expandField(ast.hour, HOUR_SPEC);\n if (minutes.length === 0 || hours.length === 0) {\n return fail(\"分・時のフィールドを展開できないため、cron 式に書き換えられません\");\n }\n\n // 1 日の中の分(0-1439)に直してからずらす\n const moved = new Set<number>();\n const carries = new Set<number>();\n for (const hour of hours) {\n for (const minute of minutes) {\n const value = hour * 60 + minute + deltaMinutes;\n moved.add(mod(value, MINUTES_PER_DAY));\n carries.add(Math.floor(value / MINUTES_PER_DAY));\n }\n }\n\n const newMinutes = sorted([...moved].map((value) => value % 60));\n const newHours = sorted([...moved].map((value) => Math.floor(value / 60)));\n // cron の分と時は独立した集合なので、直積に戻らない組み合わせは表せない\n if (newMinutes.length * newHours.length !== moved.size) {\n return fail(\n \"分と時の組み合わせが崩れるため、cron 式に書き換えられません\" +\n \"(分の繰り上がりが時刻によって変わります)\",\n );\n }\n\n // 日と曜日が「指定されているか」は書き方で決まる(`*` / `?` だけが指定なし)。\n // `0-6` のように全域を覆っていても、標準の cron では OR 条件の一方として数える。\n // ここで coversAll を使うと、毎日動く式を「15 日だけ」と見て日をずらしてしまう\n const domRestricted = !isAny(ast.dayOfMonth);\n const dowRestricted = !isAny(ast.dayOfWeek);\n const monthRestricted = !coversAll(ast.month, MONTH_SPEC);\n const everyDay = !domRestricted && !dowRestricted && !monthRestricted;\n\n const [onlyCarry] = [...carries];\n const dayShift = carries.size === 1 && onlyCarry !== undefined ? onlyCarry : null;\n if (dayShift === null && !everyDay) {\n return fail(\"日付をまたぐ時刻とまたがない時刻が混ざるため、cron 式に書き換えられません\");\n }\n\n let dayOfMonth = ast.dayOfMonth;\n let dayOfWeek = ast.dayOfWeek;\n if (dayShift !== null && dayShift !== 0 && !everyDay) {\n if (hasExtension(ast.dayOfMonth) || hasExtension(ast.dayOfWeek)) {\n return fail(\"日付が 1 日ずれるため、L / # / W を含む式は書き換えられません\");\n }\n // 月フィールドが絞られていると、月末の実行が翌月へこぼれる。\n // 日で絞られていて月をまたがないと分かっている場合だけ通す\n if (monthRestricted && (!domRestricted || dowRestricted)) {\n return fail(\"日付が 1 日ずれて月をまたぐため、cron 式に書き換えられません\");\n }\n if (domRestricted) {\n const days = expandField(ast.dayOfMonth, DOM_SPEC);\n const shiftedDays = days.map((day) => day + dayShift);\n // 29-31 日は月によって存在したりしなかったりするので、ずらすと意味が変わる\n const safe = days.every(\n (day, index) =>\n day <= SAFE_DAY_MAX &&\n (shiftedDays[index] as number) >= SAFE_DAY_MIN &&\n (shiftedDays[index] as number) <= SAFE_DAY_MAX,\n );\n if (!safe) {\n return fail(\n \"日付が 1 日ずれて月をまたぐ可能性があるため、cron 式に書き換えられません\" +\n \"(1-28 日の範囲に収まる指定であれば書き換えられます)\",\n );\n }\n dayOfMonth = fromValues(shiftedDays, DOM_SPEC);\n }\n if (dowRestricted) {\n const weekdays = expandField(ast.dayOfWeek, DOW_SPEC);\n dayOfWeek = fromValues(sorted(weekdays.map((day) => mod(day + dayShift, 7))), DOW_SPEC);\n }\n }\n\n return {\n ...ast,\n minute: sameValues(newMinutes, minutes) ? ast.minute : fromValues(newMinutes, MINUTE_SPEC),\n hour: sameValues(newHours, hours) ? ast.hour : fromValues(newHours, HOUR_SPEC),\n dayOfMonth,\n dayOfWeek,\n };\n}\n\n/**\n * cron 式の文字列を {@link shiftAst} と同じ規則でずらす。\n *\n * @throws {CronSyntaxError} 式が不正な場合\n * @throws {CronTimeZoneError} ゾーンのオフセットが動く、または結果が cron 式で表せない場合\n */\nexport function shiftExpression(\n expression: string,\n timeZone: string,\n direction: ShiftDirection,\n options: ParserOptions = {},\n): string {\n if (timeZone === SERVER_TIME_ZONE) return expression;\n const { ast } = parseExpression(expression, options);\n return formatExpression(shiftAst(ast, timeZone, direction));\n}\n","import { CronSyntaxError } from \"../errors\";\nimport type { ParserOptions, ValidationError, ValidationResult } from \"../types\";\nimport { DOM_SPEC, MONTH_SPEC } from \"./fields\";\nimport { parseExpression } from \"./parser\";\nimport { expandField, hasExtension, isAny } from \"./values\";\n\nconst DAYS_IN_MONTH = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\nconst MONTH_LABELS = [\n \"1月\",\n \"2月\",\n \"3月\",\n \"4月\",\n \"5月\",\n \"6月\",\n \"7月\",\n \"8月\",\n \"9月\",\n \"10月\",\n \"11月\",\n \"12月\",\n];\n\n/**\n * cron 式を検証する。構文エラーは throw せず {@link ValidationResult} として返す。\n */\nexport function validate(expression: string, options: ParserOptions = {}): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: string[] = [];\n\n let parsed: ReturnType<typeof parseExpression>;\n try {\n parsed = parseExpression(expression, options);\n } catch (error) {\n if (error instanceof CronSyntaxError) {\n const entry: ValidationError = {\n field: error.field ?? \"expression\",\n message: error.message,\n };\n if (error.position !== undefined) entry.position = error.position;\n errors.push(entry);\n return { valid: false, errors, warnings };\n }\n /* c8 ignore next 2 -- parseExpression は CronSyntaxError しか投げない */\n throw error;\n }\n\n const { ast, extensions } = parsed;\n\n if (extensions.includes(\"L\") || extensions.includes(\"#\") || extensions.includes(\"W\")) {\n const used = extensions.filter((extension) => extension !== \"?\").join(\"', '\");\n warnings.push(`'${used}' は Quartz 拡張です。標準の cron(Vixie cron)では動作しません`);\n warnings.push(\"拡張構文を含む式では次回実行日時(next)を計算できません\");\n }\n\n if (!isAny(ast.dayOfMonth) && !isAny(ast.dayOfWeek)) {\n warnings.push(\n \"標準の cron では日と曜日を同時に指定すると OR 条件になり、どちらかに一致する日に実行されます\",\n );\n }\n\n if (\n !isAny(ast.month) &&\n !isAny(ast.dayOfMonth) &&\n !hasExtension(ast.dayOfMonth) &&\n !hasExtension(ast.month)\n ) {\n const months = expandField(ast.month, MONTH_SPEC);\n const days = expandField(ast.dayOfMonth, DOM_SPEC);\n const impossible: string[] = [];\n let anyPossible = false;\n for (const month of months) {\n const limit = DAYS_IN_MONTH[month - 1] ?? 31;\n for (const day of days) {\n if (day <= limit) {\n anyPossible = true;\n } else {\n impossible.push(`${MONTH_LABELS[month - 1] ?? `${month}月`}${day}日`);\n }\n }\n }\n if (!anyPossible && impossible.length > 0) {\n warnings.push(`${impossible.join(\"、\")}は存在しないため、このジョブは実行されません`);\n } else if (impossible.length > 0) {\n warnings.push(`${impossible.join(\"、\")}は存在しないため、その日は実行されません`);\n }\n if (months.includes(2) && days.includes(29)) {\n warnings.push(\"2月29日はうるう年にのみ実行されます\");\n }\n }\n\n return { valid: true, errors, warnings };\n}\n","export interface TimeStyle {\n style: \"casual\" | \"formal\";\n hour: \"12h\" | \"24h\";\n}\n\nfunction pad2(value: number): string {\n return value < 10 ? `0${value}` : String(value);\n}\n\n/**\n * 「午前9時」「15時」のように時だけを表す。\n */\nexport function formatHour(hour: number, style: TimeStyle): string {\n if (style.hour === \"24h\") return `${hour}時`;\n if (hour < 12) return `午前${hour}時`;\n return `午後${hour - 12}時`;\n}\n\n/**\n * 「午前9時」「午後6時30分」「正午」のように時刻を表す。\n */\nexport function formatTime(hour: number, minute: number, style: TimeStyle): string {\n if (style.style === \"casual\" && style.hour === \"12h\" && hour === 12 && minute === 0) {\n return \"正午\";\n }\n const base = formatHour(hour, style);\n if (style.style === \"formal\") return `${base}${pad2(minute)}分`;\n return minute === 0 ? base : `${base}${minute}分`;\n}\n","import {\n DOM_SPEC,\n DOW_LABELS,\n DOW_SPEC,\n HOUR_SPEC,\n MINUTE_SPEC,\n MONTH_SPEC,\n SECOND_SPEC,\n} from \"../cron/fields\";\nimport {\n coversAll,\n expandField,\n fullRangeStep,\n hasExtension,\n rangeStep,\n toRanges,\n} from \"../cron/values\";\nimport type { FieldAST } from \"../types\";\nimport { formatHour, type TimeStyle } from \"./time\";\n\n/** 「AとB」「A、B、C」 */\nexport function joinJa(items: string[]): string {\n if (items.length === 0) return \"\";\n if (items.length === 1) return items[0] ?? \"\";\n if (items.length === 2) return `${items[0]}と${items[1]}`;\n return items.join(\"、\");\n}\n\n/**\n * 値の並びを、連続部分を範囲に畳みながら日本語にする。\n */\nexport function describeValues(\n values: number[],\n point: (value: number) => string,\n range: (from: number, to: number) => string,\n): string {\n const texts: string[] = [];\n for (const [from, to] of toRanges(values)) {\n // 3 個以上連続している場合のみ範囲に畳む\n if (to - from >= 2) {\n texts.push(range(from, to));\n } else {\n for (let value = from; value <= to; value++) texts.push(point(value));\n }\n }\n return joinJa(texts);\n}\n\nexport function describeMinuteValues(ast: FieldAST): string {\n const values = expandField(ast, MINUTE_SPEC);\n return describeValues(\n values,\n (value) => `${value}分`,\n (from, to) => `${from}分から${to}分まで`,\n );\n}\n\n/** 分フィールドの、時と組み合わせるための表現 */\nexport type MinutePart =\n | { kind: \"any\" }\n | { kind: \"step\"; text: string }\n | { kind: \"rangeStep\"; from: number; to: number; step: number }\n | { kind: \"single\"; value: number }\n | { kind: \"values\"; text: string };\n\n/**\n * 分フィールドを、文の組み立てに使える形に分解する。\n * 文単位(`compose.ts`)とフィールド単位({@link describeMinuteField})で\n * 同じ規則を使うため、判定はここだけに置く。\n */\nexport function minutePart(ast: FieldAST): MinutePart {\n if (coversAll(ast, MINUTE_SPEC)) return { kind: \"any\" };\n const step = fullRangeStep(ast, MINUTE_SPEC);\n if (step !== undefined) return { kind: \"step\", text: `${step}分ごと` };\n const ranged = rangeStep(ast, MINUTE_SPEC);\n if (ranged !== undefined) return { kind: \"rangeStep\", ...ranged };\n const values = expandField(ast, MINUTE_SPEC);\n const first = values[0];\n if (values.length === 1 && first !== undefined) return { kind: \"single\", value: first };\n return { kind: \"values\", text: describeMinuteValues(ast) };\n}\n\n/** 前に何も置かずに単独で読める分の表現 */\nexport function minuteBare(part: MinutePart): string {\n switch (part.kind) {\n case \"any\":\n return \"毎分\";\n case \"step\":\n return part.text;\n case \"rangeStep\":\n return `${part.from}分から${part.to}分まで${part.step}分ごと`;\n case \"single\":\n return `${part.value}分`;\n case \"values\":\n return part.text;\n }\n}\n\n/**\n * 時の節に続けるときの、時の中での分の表現。\n * 刻みは時をまたがないので、上限が 59 分なら「59分まで」は何も足さない。\n * 時の範囲の「まで」と重なって読みにくくするだけなので落とす。\n */\nexport function minuteWithinHour(part: MinutePart): string {\n if (part.kind !== \"rangeStep\") return minuteBare(part);\n const { from, to, step } = part;\n if (to === MINUTE_SPEC.max) return `${from}分から${step}分ごと`;\n return `${from}分から${to}分まで${step}分ごと`;\n}\n\n/** 分フィールドの説明。全域は「毎分」、ステップ指定は「N分ごと」 */\nexport function describeMinuteField(ast: FieldAST): string {\n return minuteBare(minutePart(ast));\n}\n\nexport function describeSecondField(ast: FieldAST): string {\n if (coversAll(ast, SECOND_SPEC)) return \"毎秒\";\n const step = fullRangeStep(ast, SECOND_SPEC);\n if (step !== undefined) return `${step}秒ごと`;\n const values = expandField(ast, SECOND_SPEC);\n return describeValues(\n values,\n (value) => `${value}秒`,\n (from, to) => `${from}秒から${to}秒まで`,\n );\n}\n\nexport function describeHourValues(ast: FieldAST, style: TimeStyle): string {\n const values = expandField(ast, HOUR_SPEC);\n return describeValues(\n values,\n (value) => formatHour(value, style),\n (from, to) => `${formatHour(from, style)}から${formatHour(to, style)}まで`,\n );\n}\n\nexport function describeHourField(ast: FieldAST, style: TimeStyle): string {\n if (coversAll(ast, HOUR_SPEC)) return \"毎時\";\n const step = fullRangeStep(ast, HOUR_SPEC);\n if (step !== undefined) return `${step}時間ごと`;\n const ranged = rangeStep(ast, HOUR_SPEC);\n if (ranged !== undefined) {\n const from = formatHour(ranged.from, style);\n const to = formatHour(ranged.to, style);\n return `${from}から${to}まで${ranged.step}時間ごと`;\n }\n return describeHourValues(ast, style);\n}\n\nexport function describeMonthField(ast: FieldAST): string {\n if (coversAll(ast, MONTH_SPEC)) return \"毎月\";\n const step = fullRangeStep(ast, MONTH_SPEC);\n if (step !== undefined) return `${step}か月ごと`;\n const values = expandField(ast, MONTH_SPEC);\n return describeValues(\n values,\n (value) => `${value}月`,\n (from, to) => `${from}月から${to}月まで`,\n );\n}\n\nexport function describeDayOfMonthField(ast: FieldAST): string {\n if (coversAll(ast, DOM_SPEC)) return \"毎日\";\n if (ast.kind === \"last\") {\n return ast.offset === undefined ? \"月末\" : `月末の${ast.offset}日前`;\n }\n if (ast.kind === \"nearestWeekday\") return `${ast.day}日に最も近い平日`;\n // parse 側が「1日から3日ごと」を解釈できず往復が壊れるため、起点は明示しない。\n // 「毎月」が前置されるので、月をまたいで数え直す点は文脈から読み取れる。\n const step = fullRangeStep(ast, DOM_SPEC);\n if (step !== undefined) return `${step}日ごと`;\n if (ast.kind === \"list\" && hasExtension(ast)) {\n return joinJa(ast.items.map(describeDayOfMonthField));\n }\n const values = expandField(ast, DOM_SPEC);\n return describeValues(\n values,\n (value) => `${value}日`,\n (from, to) => `${from}日から${to}日まで`,\n );\n}\n\nexport interface DowOptions {\n /** 「毎週」を前置するか */\n weekly: boolean;\n /** 「平日」「週末」に畳むか */\n collapse: boolean;\n}\n\nfunction dowLabel(value: number): string {\n return DOW_LABELS[value] ?? `${value}`;\n}\n\nexport function describeDayOfWeekField(ast: FieldAST, options: DowOptions): string {\n if (ast.kind === \"any\" || ast.kind === \"noSpecific\") return \"毎日\";\n if (ast.kind === \"nth\") {\n const label = dowLabel(ast.weekday);\n return ast.nth === -1 ? `最終${label}` : `第${ast.nth}${label}`;\n }\n if (ast.kind === \"list\" && hasExtension(ast)) {\n return joinJa(\n ast.items.map((item) => describeDayOfWeekField(item, { ...options, weekly: false })),\n );\n }\n\n const values = expandField(ast, DOW_SPEC);\n if (values.length === 7) return \"毎日\";\n if (options.collapse) {\n const key = values.join(\",\");\n if (key === \"1,2,3,4,5\") return \"平日\";\n if (key === \"0,6\") return \"週末\";\n }\n const text = describeValues(\n values,\n dowLabel,\n (from, to) => `${dowLabel(from)}から${dowLabel(to)}まで`,\n );\n return options.weekly ? `毎週${text}` : text;\n}\n","import {\n DOM_SPEC,\n DOW_SPEC,\n HOUR_SPEC,\n MINUTE_SPEC,\n MONTH_SPEC,\n SECOND_SPEC,\n} from \"../cron/fields\";\nimport { coversAll, expandField, fullRangeStep, isAny, rangeStep, toRanges } from \"../cron/values\";\nimport type { CronAST } from \"../types\";\nimport {\n describeDayOfMonthField,\n describeDayOfWeekField,\n describeHourValues,\n describeMonthField,\n describeSecondField,\n joinJa,\n type MinutePart,\n minuteBare,\n minutePart,\n minuteWithinHour,\n} from \"./field\";\nimport { formatHour, formatTime, type TimeStyle } from \"./time\";\n\nexport interface ComposeOptions extends TimeStyle {\n collapseWeekdays: boolean;\n}\n\n/** 「毎分」「15分ごと」「毎時0分」のように、時を限定しない文での分の表現 */\nfunction minuteAlone(part: MinutePart): string {\n switch (part.kind) {\n case \"any\":\n case \"step\":\n case \"rangeStep\":\n return minuteBare(part);\n case \"single\":\n return `毎時${part.value}分`;\n case \"values\":\n return `毎時${part.text}`;\n }\n}\n\n/**\n * 時の節に続けるときの分の表現。\n * 「AからBまでNごと」を自己完結した形のまま置くと、時の範囲の「まで」と重なって\n * 「午前9時から午後5時まで5分から59分まで15分ごと」のように読めなくなる。\n * 「毎時」で分の節の始まりを示し、時の中での位置として組み立てる。\n */\nfunction minuteAfterHours(part: MinutePart): string {\n if (part.kind === \"rangeStep\") return `毎時${minuteWithinHour(part)}`;\n return minuteAlone(part);\n}\n\nexport interface TimeDescription {\n text: string;\n /** 「毎分」「N分ごと」のように頻度そのものを表す表現か */\n frequency: boolean;\n}\n\n/**\n * 時刻部分を組み立てる。\n */\nexport function describeTime(ast: CronAST, options: ComposeOptions): TimeDescription {\n const minute = minutePart(ast.minute);\n const hour = ast.hour;\n let result: TimeDescription;\n\n const hourStep = fullRangeStep(hour, HOUR_SPEC);\n const hourRange = rangeStep(hour, HOUR_SPEC);\n\n if (coversAll(hour, HOUR_SPEC)) {\n result = { text: minuteAlone(minute), frequency: true };\n } else if (hourStep !== undefined) {\n result = { text: `${hourStep}時間ごと(${minuteAfterHours(minute)})`, frequency: true };\n } else if (hourRange !== undefined) {\n const from = formatHour(hourRange.from, options);\n const to = formatHour(hourRange.to, options);\n const step = `${hourRange.step}時間ごと(${minuteAfterHours(minute)})`;\n result = { text: `${from}から${to}まで${step}`, frequency: false };\n } else {\n const values = expandField(hour, HOUR_SPEC);\n const ranges = toRanges(values);\n // describeHourValues は 3 個以上連続したときだけ範囲に畳む。同じ閾値で判定しないと、\n // 12,13 のような 2 個の連なりが「範囲になった」扱いのまま点として並び、\n // 「午後0時と午後1時毎時0分」のように接続が抜けた文になる\n const allPoints = ranges.every(([from, to]) => to - from < 2);\n if (allPoints && minute.kind === \"single\") {\n result = {\n text: joinJa(values.map((value) => formatTime(value, minute.value, options))),\n frequency: false,\n };\n } else if (allPoints) {\n // 「台」は各時に付ける。「午後2時と午後6時台」では 2 時に掛からない\n const hours = joinJa(values.map((value) => `${formatHour(value, options)}台`));\n // 「台」自体が時の中を指すので、ここでは「毎時」を前置しない\n result = { text: `${hours}の${minuteWithinHour(minute)}`, frequency: false };\n } else {\n result = {\n text: `${describeHourValues(hour, options)}${minuteAfterHours(minute)}`,\n frequency: false,\n };\n }\n }\n\n const seconds = ast.seconds;\n if (seconds === undefined) return result;\n // 「0 秒ちょうど」は既定の挙動なので触れない\n if (seconds.kind === \"value\" && seconds.value === 0) return result;\n\n if (coversAll(ast.hour, HOUR_SPEC) && coversAll(ast.minute, MINUTE_SPEC)) {\n if (coversAll(seconds, SECOND_SPEC)) return { text: \"毎秒\", frequency: true };\n const secondStep = fullRangeStep(seconds, SECOND_SPEC);\n if (secondStep !== undefined) return { text: `${secondStep}秒ごと`, frequency: true };\n }\n return { text: `${result.text}の${describeSecondField(seconds)}`, frequency: result.frequency };\n}\n\nexport interface DateDescription {\n text: string;\n /** 時刻表現と「の」で繋ぐか */\n joinWithNo: boolean;\n /** 日付を一切限定していないか */\n everyDay: boolean;\n}\n\n/**\n * 日付部分を組み立てる。\n */\nexport function describeDate(ast: CronAST, options: ComposeOptions): DateDescription {\n const domAll = coversAll(ast.dayOfMonth, DOM_SPEC);\n const monthAny = coversAll(ast.month, MONTH_SPEC);\n const dowAll = coversAll(ast.dayOfWeek, DOW_SPEC);\n\n // 標準の cron では、日と曜日を「両方とも」指定すると OR 条件になる(`*` / `?` は指定と\n // 見なさない)。片方が全域を覆っていれば、もう片方が何であれ毎日一致する。\n // `0 0 15 * 0-7` は「毎月15日」ではなく毎日動く\n const orCoversEveryDay = !isAny(ast.dayOfMonth) && !isAny(ast.dayOfWeek) && (domAll || dowAll);\n const domAny = domAll || orCoversEveryDay;\n const dowAny = dowAll || orCoversEveryDay;\n\n if (domAny && monthAny && dowAny) {\n return { text: \"毎日\", joinWithNo: false, everyDay: true };\n }\n\n const monthText = describeMonthField(ast.month);\n\n if (domAny && !dowAny) {\n const dow = describeDayOfWeekField(ast.dayOfWeek, {\n weekly: true,\n collapse: options.collapseWeekdays,\n });\n const text = monthAny ? dow : `${monthText}の${dow}`;\n return { text, joinWithNo: true, everyDay: false };\n }\n\n if (!domAny && dowAny) {\n const dom = describeDayOfMonthField(ast.dayOfMonth);\n if (monthAny) return { text: `毎月${dom}`, joinWithNo: true, everyDay: false };\n if (ast.month.kind === \"value\" && ast.dayOfMonth.kind === \"value\") {\n return { text: `毎年${monthText}${dom}`, joinWithNo: true, everyDay: false };\n }\n return { text: `${monthText}の${dom}`, joinWithNo: true, everyDay: false };\n }\n\n if (!domAny && !dowAny) {\n const dom = describeDayOfMonthField(ast.dayOfMonth);\n const dow = describeDayOfWeekField(ast.dayOfWeek, {\n weekly: false,\n collapse: options.collapseWeekdays,\n });\n const base = monthAny\n ? `毎月${dom}`\n : ast.month.kind === \"value\" && ast.dayOfMonth.kind === \"value\"\n ? `毎年${monthText}${dom}`\n : `${monthText}の${dom}`;\n return { text: `${base}および${dow}`, joinWithNo: true, everyDay: false };\n }\n\n // 月だけが指定されている\n return { text: `${monthText}の毎日`, joinWithNo: false, everyDay: false };\n}\n\n/**\n * 日付部分と時刻部分を 1 文に組み立てる。\n */\nexport function compose(ast: CronAST, options: ComposeOptions): string {\n const time = describeTime(ast, options);\n const date = describeDate(ast, options);\n if (date.everyDay && time.frequency) return time.text;\n return `${date.text}${date.joinWithNo ? \"の\" : \"\"}${time.text}`;\n}\n","import {\n DOM_SPEC,\n DOW_SPEC,\n expandField,\n type FieldSpec,\n formatExpression,\n formatField,\n HOUR_SPEC,\n hasExtension,\n MINUTE_SPEC,\n MONTH_SPEC,\n next,\n parseExpression,\n resolveTimeZone,\n SECOND_SPEC,\n shiftAst,\n validate,\n} from \"../cron\";\nimport type {\n ExplainOptions,\n Explanation,\n FieldAST,\n FieldExplanation,\n ParserOptions,\n} from \"../types\";\nimport type { ComposeOptions } from \"./compose\";\nimport { compose } from \"./compose\";\nimport {\n describeDayOfMonthField,\n describeDayOfWeekField,\n describeHourField,\n describeMinuteField,\n describeMonthField,\n describeSecondField,\n} from \"./field\";\n\nfunction resolve(options: ExplainOptions): ComposeOptions {\n return {\n style: options.style ?? \"casual\",\n hour: options.hour ?? \"12h\",\n collapseWeekdays: options.collapseWeekdays ?? true,\n };\n}\n\nfunction parserOptions(options: ExplainOptions): ParserOptions {\n return options.seconds === true ? { seconds: true } : {};\n}\n\n/**\n * cron 式を 1 文の日本語に変換する。\n *\n * 式は UTC のサーバーで動くものとして読み、`options.tz`(既定 `'Asia/Tokyo'`)の\n * 壁時計に直してから日本語にする。\n *\n * ```ts\n * explain('0 4 * * 1-5'); // '平日の午後1時'(UTC 04:00 = JST 13:00)\n * explain('0 9 * * 1-5', { tz: 'UTC' }); // '平日の午前9時'(変換しない)\n * ```\n *\n * @throws {CronSyntaxError} 式が不正な場合\n * @throws {CronTimeZoneError} `tz` を解釈できない、または cron 式に書き換えられない場合\n */\nexport function explain(expression: string, options: ExplainOptions = {}): string {\n const parsed = parseExpression(expression, parserOptions(options));\n const timeZone = resolveTimeZone(options.tz);\n const text = compose(shiftAst(parsed.ast, timeZone, \"toLocal\"), resolve(options));\n return options.showTimeZone === true ? `${text}(${timeZone})` : text;\n}\n\nfunction kindOf(ast: FieldAST): FieldExplanation[\"kind\"] {\n if (hasExtension(ast) || ast.kind === \"noSpecific\") return \"extension\";\n switch (ast.kind) {\n case \"any\":\n return \"any\";\n case \"value\":\n return \"value\";\n case \"range\":\n return \"range\";\n case \"step\":\n return \"step\";\n case \"list\":\n return \"list\";\n /* c8 ignore next 2 -- 拡張構文は上で処理済み */\n default:\n return \"extension\";\n }\n}\n\nfunction explainField(raw: string, ast: FieldAST, spec: FieldSpec, text: string): FieldExplanation {\n return {\n raw,\n kind: kindOf(ast),\n values: hasExtension(ast) ? [] : expandField(ast, spec),\n text,\n };\n}\n\n/**\n * cron 式をフィールド別の内訳・注意書き・次回実行日時つきで説明する。\n *\n * `fields` は `options.tz` の壁時計に直したあとの値を説明する(`localExpression` と対応)。\n * `expression` は入力(UTC)を正規化したもの、`next` は UTC として解釈した絶対時刻。\n *\n * @throws {CronSyntaxError} 式が不正な場合\n * @throws {CronTimeZoneError} `tz` を解釈できない、または cron 式に書き換えられない場合\n */\nexport function explainDetailed(expression: string, options: ExplainOptions = {}): Explanation {\n const parsed = parseExpression(expression, parserOptions(options));\n const composeOptions = resolve(options);\n const timeZone = resolveTimeZone(options.tz);\n const ast = shiftAst(parsed.ast, timeZone, \"toLocal\");\n\n const normalized = formatExpression(parsed.ast);\n const localized = ast === parsed.ast ? normalized : formatExpression(ast);\n // 書き換わったフィールドだけ raw を差し替える。触っていないフィールドは\n // 入力の字面(JAN や MON-FRI)をそのまま見せる\n const raw = (field: keyof typeof parsed.raw, before: FieldAST, after: FieldAST): string =>\n before === after ? (parsed.raw[field] ?? formatField(after)) : formatField(after);\n const dowOptions = { weekly: false, collapse: composeOptions.collapseWeekdays };\n\n const fields: Explanation[\"fields\"] = {\n minute: explainField(\n raw(\"minute\", parsed.ast.minute, ast.minute),\n ast.minute,\n MINUTE_SPEC,\n describeMinuteField(ast.minute),\n ),\n hour: explainField(\n raw(\"hour\", parsed.ast.hour, ast.hour),\n ast.hour,\n HOUR_SPEC,\n describeHourField(ast.hour, composeOptions),\n ),\n dayOfMonth: explainField(\n raw(\"dayOfMonth\", parsed.ast.dayOfMonth, ast.dayOfMonth),\n ast.dayOfMonth,\n DOM_SPEC,\n describeDayOfMonthField(ast.dayOfMonth),\n ),\n month: explainField(\n raw(\"month\", parsed.ast.month, ast.month),\n ast.month,\n MONTH_SPEC,\n describeMonthField(ast.month),\n ),\n dayOfWeek: explainField(\n raw(\"dayOfWeek\", parsed.ast.dayOfWeek, ast.dayOfWeek),\n ast.dayOfWeek,\n DOW_SPEC,\n describeDayOfWeekField(ast.dayOfWeek, dowOptions),\n ),\n };\n if (ast.seconds !== undefined) {\n fields.second = explainField(\n raw(\"seconds\", parsed.ast.seconds ?? ast.seconds, ast.seconds),\n ast.seconds,\n SECOND_SPEC,\n describeSecondField(ast.seconds),\n );\n }\n\n const composed = compose(ast, composeOptions);\n const text = options.showTimeZone === true ? `${composed}(${timeZone})` : composed;\n const { warnings } = validate(expression, parserOptions(options));\n\n return {\n text,\n expression: normalized,\n localExpression: localized,\n tz: timeZone,\n fields,\n extensions: parsed.extensions,\n notes: warnings,\n next: next(expression, { ...parserOptions(options), count: 3 }),\n };\n}\n","import type { TimeOfDayWord } from \"../types\";\n\nexport const DOW: Record<string, number> = {\n 日曜日: 0,\n 日曜: 0,\n 月曜日: 1,\n 月曜: 1,\n 火曜日: 2,\n 火曜: 2,\n 水曜日: 3,\n 水曜: 3,\n 木曜日: 4,\n 木曜: 4,\n 金曜日: 5,\n 金曜: 5,\n 土曜日: 6,\n 土曜: 6,\n};\n\nexport const DOW_SET: Record<string, number[]> = {\n 平日: [1, 2, 3, 4, 5],\n 週末: [0, 6],\n 土日: [0, 6],\n 休日: [0, 6],\n};\n\n/**\n * 曜日で近似した語と、そのずれの説明。\n *\n * 「休日」は祝日・振替休日も指すが、cron は曜日しか持たないので土日に寄せるほかない。\n * 黙って寄せると祝日ぶんの取りこぼしに気づけないので、note と減点を付ける(§2.3.5)。\n * 減点の量は `fill` が持つ。\n */\nexport const DOW_SET_APPROX: Record<string, string> = {\n 休日:\n \"「休日」は祝日も指しますが、cron では曜日しか指定できないため、\" +\n \"週末(土日)として解釈しました。祝日には実行されません\",\n};\n\nexport interface TimeOfDaySpec {\n /** 既定の時。null は「時そのものは決まらない」 */\n default: number | null;\n /** その語が自然に指す時間帯 */\n range: readonly [number, number];\n}\n\nexport const TIME_OF_DAY: Record<TimeOfDayWord, TimeOfDaySpec> = {\n 早朝: { default: 6, range: [4, 7] },\n 朝: { default: 9, range: [6, 10] },\n 午前: { default: null, range: [0, 11] },\n 昼: { default: 12, range: [11, 13] },\n 正午: { default: 12, range: [12, 12] },\n 午後: { default: null, range: [12, 23] },\n 夕方: { default: 18, range: [16, 19] },\n 夜: { default: 21, range: [19, 23] },\n 晩: { default: 21, range: [19, 23] },\n 深夜: { default: 2, range: [0, 4] },\n 夜中: { default: 2, range: [0, 4] },\n};\n\nexport type FreqUnit = \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n\nexport const FREQ: Record<string, FreqUnit> = {\n 毎分: \"minute\",\n 毎時: \"hour\",\n 毎日: \"day\",\n 毎週: \"week\",\n 毎月: \"month\",\n 毎年: \"year\",\n};\n\nexport const DOM_SPECIAL: Record<string, \"L\" | number> = { 月末: \"L\", 月初: 1 };\n\nexport const NTH: Record<string, number> = {\n 第1: 1,\n 第2: 2,\n 第3: 3,\n 第4: 4,\n 第5: 5,\n 最終: -1,\n 最後: -1,\n};\n\n/** 曜日語として認識する表記(「月」「日」単独は月名・日付と衝突するため含めない) */\nexport const DOW_HEADS = [\"日\", \"月\", \"火\", \"水\", \"木\", \"金\", \"土\"] as const;\n","import { DOM_SPEC, type FieldSpec, HOUR_SPEC, MINUTE_SPEC, MONTH_SPEC } from \"../cron/fields\";\nimport { formatField } from \"../cron/values\";\nimport { formatHour } from \"../explain/time\";\nimport type {\n Ambiguity,\n CronExtension,\n FieldAST,\n ParseOptions,\n TimeOfDayWord,\n Token,\n} from \"../types\";\nimport { DOW_SET_APPROX, type FreqUnit, TIME_OF_DAY } from \"./dictionary\";\nimport type { IntervalUnit, IntervalValue, TimeValue } from \"./tokenize\";\n\nexport interface Penalty {\n reason: string;\n amount: number;\n}\n\nexport interface Slots {\n minute: FieldAST;\n hour: FieldAST;\n dom: FieldAST;\n month: FieldAST;\n dow: FieldAST;\n extensions: Set<CronExtension>;\n penalties: Penalty[];\n ambiguities: Ambiguity[];\n notes: string[];\n /** 意味のあるトークンが 1 つも無かった */\n empty: boolean;\n}\n\nconst ANY: FieldAST = { kind: \"any\" };\n\nconst FREQ_LABELS: Record<FreqUnit, string> = {\n minute: \"毎分\",\n hour: \"毎時\",\n day: \"毎日\",\n week: \"毎週\",\n month: \"毎月\",\n year: \"毎年\",\n};\n\nconst INTERVAL_LABELS: Record<IntervalUnit, string> = {\n minute: \"分\",\n hour: \"時\",\n day: \"日\",\n week: \"週\",\n month: \"月\",\n};\n\n/** 値の並びを持つスロット。時刻は時と分を持つため別扱い */\ntype ListName = \"minute\" | \"dom\" | \"dow\" | \"month\";\n\n/** 間隔の単位と、その起点になる値の並び */\nconst INTERVAL_LIST: Partial<Record<IntervalUnit, ListName>> = {\n minute: \"minute\",\n day: \"dom\",\n month: \"month\",\n};\n\n/** 値の並びの 1 要素。`from === to` は単独の値、それ以外は「AからBまで」 */\ninterface Span {\n from: number;\n to: number;\n}\n\ninterface ValueList {\n items: Span[];\n /** 「から」を読んだが、範囲の終端がまだ来ていない */\n pendingRange: boolean;\n /** 刻みの起点、あるいは分の値として読み終えた(二重指定として数えない) */\n consumed: boolean;\n}\n\nfunction emptyList(): ValueList {\n return { items: [], pendingRange: false, consumed: false };\n}\n\nfunction pushValue(list: ValueList, value: number): void {\n const last = list.items[list.items.length - 1];\n if (list.pendingRange && last !== undefined) {\n last.to = value;\n list.pendingRange = false;\n return;\n }\n list.items.push({ from: value, to: value });\n}\n\n/** 値の並びを、連続部分を範囲に畳んだ構文木にする */\nfunction valuesToAst(values: number[]): FieldAST {\n const sorted = [...new Set(values)].sort((a, b) => a - b);\n const first = sorted[0];\n if (first === undefined) return ANY;\n if (sorted.length === 1) return { kind: \"value\", value: first };\n\n const items: FieldAST[] = [];\n let from = first;\n let previous = first;\n const flush = () => {\n if (previous - from >= 2) items.push({ kind: \"range\", from, to: previous });\n else for (let value = from; value <= previous; value++) items.push({ kind: \"value\", value });\n };\n for (const value of sorted.slice(1)) {\n if (value === previous + 1) {\n previous = value;\n continue;\n }\n flush();\n from = value;\n previous = value;\n }\n flush();\n const only = items[0];\n /* c8 ignore next -- items は必ず 1 個以上になる */\n if (only === undefined) return ANY;\n return items.length === 1 ? only : { kind: \"list\", items };\n}\n\n/**\n * 値の並びを構文木にする。\n * 「AからBまで」と書かれた範囲は範囲のまま残す(`valuesToAst` は 3 個以上の連なりしか\n * 範囲に畳まないため、`28,31` のように意味が変わってしまう)。\n */\nfunction spansToAst(spans: Span[]): FieldAST {\n if (spans.every((span) => span.from === span.to)) {\n return valuesToAst(spans.map((span) => span.from));\n }\n const items = spans.map<FieldAST>((span) =>\n span.from === span.to\n ? { kind: \"value\", value: span.from }\n : { kind: \"range\", from: span.from, to: span.to },\n );\n const only = items[0];\n /* c8 ignore next -- 範囲を含むなら 1 個以上ある */\n if (only === undefined) return ANY;\n return items.length === 1 ? only : { kind: \"list\", items };\n}\n\nfunction listToAst(list: ValueList): FieldAST {\n return spansToAst(list.items);\n}\n\n/**\n * 「AからBまでNごと」「AからNごと」の起点を取り出す。\n * 範囲として書かれていなければ null を返し、値の並びは値のまま残す。\n */\nfunction consumeBase(list: ValueList, spec: FieldSpec): FieldAST | null {\n const span = list.items[0];\n if (span === undefined || list.items.length !== 1) return null;\n if (!list.pendingRange && span.from === span.to) return null;\n list.consumed = true;\n return { kind: \"range\", from: span.from, to: list.pendingRange ? spec.max : span.to };\n}\n\n/**\n * 時刻の並びの 1 要素。時間帯語は `fill` で解決するまで語のまま持つ\n * ({@link resolveWord} が曖昧さと減点を積むため、`collect` では決められない)。\n */\ntype TimeAtom =\n | { kind: \"time\"; hour: number; minute: number }\n | { kind: \"word\"; word: TimeOfDayWord };\n\n/** 時刻の並びの 1 要素。`to === null` は単独の時刻、それ以外は「AからBまで」 */\ninterface TimeSpan {\n from: TimeAtom;\n to: TimeAtom | null;\n}\n\n/** 値の並び({@link ValueList})の時刻版。範囲を 2 つ以上持てる */\ninterface TimeList {\n items: TimeSpan[];\n /** 「から」を読んだが、範囲の終端がまだ来ていない */\n pendingRange: boolean;\n}\n\nfunction pushTime(list: TimeList, atom: TimeAtom): void {\n const last = list.items[list.items.length - 1];\n if (list.pendingRange && last !== undefined) {\n last.to = atom;\n list.pendingRange = false;\n return;\n }\n list.items.push({ from: atom, to: null });\n}\n\n/** 時間帯語を解決した時刻 */\ninterface ResolvedTime {\n hour: number;\n minute: number;\n}\n\ninterface ResolvedSpan {\n from: ResolvedTime;\n to: ResolvedTime | null;\n}\n\n/** 刻みの構文木。起点が全域を覆うなら省く(`1-31/3` は「3日ごと」と同じ集合) */\nfunction stepAst(base: FieldAST | null, step: number, spec: FieldSpec): FieldAST {\n if (base === null) return { kind: \"step\", base: ANY, step };\n if (base.kind === \"range\" && base.from === spec.min && base.to === spec.max) {\n return { kind: \"step\", base: ANY, step };\n }\n return { kind: \"step\", base, step };\n}\n\n/**\n * 時から時間帯語の範囲までの距離(時間)。時計は巡回するので 23 時と 0 時は 1 時間差。\n */\nfunction gapToRange(hour: number, [low, high]: readonly [number, number]): number {\n if (hour >= low && hour <= high) return 0;\n return Math.min((low - hour + 24) % 24, (hour - high + 24) % 24);\n}\n\n/**\n * 時間帯語と並んだ時を読む。\n *\n * 12 時までの数字は 12 時間制の書き方なので、そのままの時と 12 時間ずらした時のうち、\n * 語の指す時間帯に近い方を採る(「夜6時」→ 18時、「午後3時」→ 15時)。\n * 13 時以降は 24 時間制としか読めないので、そのまま採る(「朝22時」→ 22時)。\n *\n * 範囲に入っていなくても近い方を採るのは、境界のすぐ外側で読みが裏返らないようにするため。\n * 「夜」は 19 時からだが、「夜6時」を午前 6 時と読むのは行き過ぎで、離れたぶんは\n * {@link fill} が note と減点で伝える(§2.3.5)。\n *\n * 12 時のもう一方の読みは 0 時なので、「午前12時」「夜12時」はどちらも 0 時になる。\n */\nfunction readHour(word: TimeOfDayWord, hour: number): { hour: number; gap: number } {\n const range = TIME_OF_DAY[word].range;\n const literal = { hour, gap: gapToRange(hour, range) };\n if (hour > 12) return literal;\n const shifted = (hour + 12) % 24;\n const alternative = { hour: shifted, gap: gapToRange(shifted, range) };\n return alternative.gap < literal.gap ? alternative : literal;\n}\n\nfunction hourCandidates(from: number, to: number): Ambiguity[\"candidates\"] {\n const candidates: Ambiguity[\"candidates\"] = [];\n for (let hour = from; hour <= to; hour++) {\n candidates.push({ value: hour, label: formatHour(hour, { style: \"casual\", hour: \"12h\" }) });\n }\n return candidates;\n}\n\ninterface Collected {\n times: TimeList;\n /** 「9時台」のように、時そのものではなく時の中を指している */\n hourSpan: boolean;\n lists: Record<ListName, ValueList>;\n intervals: Partial<Record<IntervalUnit, number>>;\n /** 同じ単位の間隔が 2 回書かれた */\n duplicateIntervals: IntervalUnit[];\n /** 値の並びと間隔のどちらが後に書かれたか(§2.3.5 の後勝ち) */\n lastAssign: Partial<Record<ListName, \"values\" | \"interval\">>;\n nths: Array<{ weekday: number; nth: number }>;\n domSpecial: \"L\" | number | null;\n freqs: FreqUnit[];\n unknown: number;\n meaningful: number;\n todNotes: string[];\n /** 時間帯の語と時刻がずれたぶんの減点 */\n todPenalties: Penalty[];\n /** 曜日で近似した語(「休日」)の説明 */\n approxNotes: string[];\n}\n\nfunction collect(tokens: Token[]): Collected {\n const state: Collected = {\n times: { items: [], pendingRange: false },\n hourSpan: false,\n lists: { minute: emptyList(), dom: emptyList(), dow: emptyList(), month: emptyList() },\n intervals: {},\n duplicateIntervals: [],\n lastAssign: {},\n nths: [],\n domSpecial: null,\n freqs: [],\n unknown: 0,\n meaningful: 0,\n todNotes: [],\n todPenalties: [],\n approxNotes: [],\n };\n\n let pendingWord: TimeOfDayWord | null = null;\n /** 範囲の始点に掛かっていた時間帯語。終端に語が無ければこれを引き継ぐ */\n let spanWord: TimeOfDayWord | null = null;\n let pendingNth: number | null = null;\n /** 直前に読んだ値がどのスロットのものか(「から」の係り先) */\n let last: ListName | \"time\" | null = null;\n\n /**\n * 時刻の並びに 1 つ足す。範囲の始点なら、掛かっていた語を終端が引き継げるよう覚える\n * (終端に語が無い「夜6時から9時まで」を 18-21 と読むため)。\n */\n const addTime = (atom: TimeAtom, word: TimeOfDayWord | null) => {\n if (!state.times.pendingRange) spanWord = word;\n pushTime(state.times, atom);\n };\n\n /** 時刻に結び付かなかった時間帯語を、書かれた位置のまま並びに置く */\n const flushWord = () => {\n if (pendingWord !== null) {\n addTime({ kind: \"word\", word: pendingWord }, pendingWord);\n pendingWord = null;\n }\n };\n\n /** 値を並びに足し、「から」の係り先として返す */\n const addValues = (name: ListName, values: number[]): ListName => {\n for (const value of values) pushValue(state.lists[name], value);\n state.lastAssign[name] = \"values\";\n return name;\n };\n\n for (const token of tokens) {\n if (token.type !== \"UNKNOWN\" && token.type !== \"SEP\") state.meaningful += 1;\n\n switch (token.type) {\n case \"AMPM\":\n case \"TIME_OF_DAY\":\n flushWord();\n pendingWord = token.value as TimeOfDayWord;\n last = \"time\";\n break;\n\n case \"TIME\": {\n const time = token.value as TimeValue;\n let hour = time.hour;\n // 「夜6時から9時まで」の 9 時は始点と同じ時間帯の中。語が書かれていない\n // 範囲の終端は、始点に掛かっていた語で読む(→ 18-21)\n const inherited = state.times.pendingRange ? spanWord : null;\n const word = pendingWord ?? inherited;\n if (word !== null) {\n const reading = readHour(word, hour);\n hour = reading.hour;\n // 書かれた語だけを note にする。引き継いだ語のずれを書くと、\n // 利用者が書いていない語のせいで減点されたように見える\n if (reading.gap > 0 && pendingWord !== null) {\n // 語の指す時間帯から外れた読みしか無い。採った理由は言えないので、\n // どう読んだかを note にして、離れたぶんだけ減点する\n const [low, high] = TIME_OF_DAY[pendingWord].range;\n state.todNotes.push(\n `「${pendingWord}」は通常 ${low}時から${high}時ですが、${hour}時と解釈しました`,\n );\n state.todPenalties.push({\n reason: \"時間帯の語と時刻のずれ\",\n amount: Math.min(0.3, reading.gap * 0.1),\n });\n }\n }\n addTime({ kind: \"time\", hour, minute: time.minute }, pendingWord);\n pendingWord = null;\n last = \"time\";\n break;\n }\n\n case \"MINUTE\":\n flushWord();\n last = addValues(\"minute\", [token.value as number]);\n break;\n\n case \"INTERVAL\": {\n flushWord();\n const interval = token.value as IntervalValue;\n if (state.intervals[interval.unit] !== undefined) {\n state.duplicateIntervals.push(interval.unit);\n }\n state.intervals[interval.unit] = interval.n;\n const name = INTERVAL_LIST[interval.unit];\n if (name !== undefined) state.lastAssign[name] = \"interval\";\n // cron に週の刻みは無い。「毎週」として扱い、fill で note を付ける\n if (interval.unit === \"week\") state.freqs.push(\"week\");\n // 「3か月ごと」だけでは何日に動くか決まらないので「毎月」と同じ期待を置く\n if (interval.unit === \"month\") state.freqs.push(\"month\");\n break;\n }\n\n case \"RANGE_FROM\":\n if (last === \"time\") {\n // 「朝から17時まで」の「朝」は 17 時の修飾語ではなく、範囲の始点\n flushWord();\n if (state.times.items.length > 0) state.times.pendingRange = true;\n } else if (last !== null && state.lists[last].items.length > 0) {\n state.lists[last].pendingRange = true;\n }\n break;\n\n case \"RANGE_TO\":\n break;\n\n case \"NTH\":\n flushWord();\n pendingNth = token.value as number;\n break;\n\n case \"DOW\": {\n flushWord();\n const weekday = token.value as number;\n if (pendingNth !== null) {\n state.nths.push({ weekday, nth: pendingNth });\n pendingNth = null;\n } else {\n last = addValues(\"dow\", [weekday]);\n }\n break;\n }\n\n case \"DOW_SET\": {\n flushWord();\n // 「休日」のように曜日と厳密には一致しない語は、寄せたことを fill で note にする\n const approx = DOW_SET_APPROX[token.raw];\n if (approx !== undefined) state.approxNotes.push(approx);\n last = addValues(\"dow\", token.value as number[]);\n break;\n }\n\n case \"DOM\":\n flushWord();\n last = addValues(\"dom\", [token.value as number]);\n break;\n\n case \"DOM_SPECIAL\": {\n flushWord();\n const value = token.value as \"L\" | number;\n if (value === \"L\") state.domSpecial = \"L\";\n else last = addValues(\"dom\", [value]);\n break;\n }\n\n case \"MONTH\":\n flushWord();\n last = addValues(\"month\", [token.value as number]);\n break;\n\n case \"FREQ\":\n flushWord();\n state.freqs.push(token.value as FreqUnit);\n break;\n\n case \"AND\":\n // 「午前0時と正午」の「正午」は 2 つ目の時刻。前の語をここで切る\n flushWord();\n break;\n\n case \"HOUR_SPAN\":\n state.hourSpan = true;\n break;\n\n default:\n if (token.type === \"UNKNOWN\") state.unknown += 1;\n break;\n }\n }\n\n flushWord();\n return state;\n}\n\n/**\n * トークン列から cron の各フィールドを埋める。\n */\nexport function fill(tokens: Token[], options: ParseOptions = {}): Slots {\n const requested = options.defaultHour ?? 9;\n const defaultHour =\n Number.isInteger(requested) && requested >= 0 && requested <= 23 ? requested : 9;\n const state = collect(tokens);\n\n const slots: Slots = {\n minute: ANY,\n hour: ANY,\n dom: ANY,\n month: ANY,\n dow: ANY,\n extensions: new Set<CronExtension>(),\n penalties: [],\n ambiguities: [],\n notes: [...state.todNotes],\n empty: state.meaningful === 0,\n };\n if (slots.empty) return slots;\n\n const penalize = (reason: string, amount: number) => {\n slots.penalties.push({ reason, amount });\n };\n\n /** 同じフィールドに 2 通りの指定が並んだとき(§2.3.5 の「2 回代入」) */\n const noteConflict = (label: string) => {\n slots.notes.push(`「${label}」の指定が 2 通りあるため、後に書かれた方を採用しました`);\n penalize(\"同じフィールドへの二重指定\", 0.2);\n };\n\n // 時間帯の語と時刻のずれ(note は collect が積んでいる)\n for (const penalty of state.todPenalties) slots.penalties.push(penalty);\n\n for (const unit of state.duplicateIntervals) noteConflict(INTERVAL_LABELS[unit]);\n\n // 曜日に寄せた語は、指す日がずれるぶんを減点する(cron に祝日は書けない)\n for (const note of state.approxNotes) {\n slots.notes.push(note);\n penalize(\"曜日で近似した語\", 0.2);\n }\n\n /** 時間帯の語を時に落とす。幅のある語は曖昧さとして報告する */\n const resolveWord = (word: TimeOfDayWord): number => {\n const spec = TIME_OF_DAY[word];\n const override = options.timeOfDay?.[word];\n // 「正午」のように時が一意に定まる語は曖昧ではない\n if (spec.range[0] !== spec.range[1] && override === undefined) {\n slots.ambiguities.push({\n field: \"hour\",\n question: `「${word}」は何時ですか?`,\n candidates: hourCandidates(spec.range[0], spec.range[1]),\n });\n penalize(\"時刻を表す語が曖昧\", 0.3);\n }\n return override ?? spec.default ?? defaultHour;\n };\n\n // 時刻に結び付かなかった時間帯語は、それ自体が 1 つの時刻(「午前0時と正午」)。\n // 並びの位置は `collect` が保っているので、書かれた順のまま解決する\n const resolveAtom = (atom: TimeAtom): ResolvedTime =>\n atom.kind === \"time\"\n ? { hour: atom.hour, minute: atom.minute }\n : { hour: resolveWord(atom.word), minute: 0 };\n const spans = state.times.items.map<ResolvedSpan>((span) => ({\n from: resolveAtom(span.from),\n to: span.to === null ? null : resolveAtom(span.to),\n }));\n\n /* ---------------- 時刻 ---------------- */\n\n const minutes = state.lists.minute;\n const minuteStep = state.intervals.minute;\n const hourStep = state.intervals.hour;\n const hasTime = spans.length > 0;\n const hasRange = spans.some((span) => span.to !== null);\n // 時刻の側に書かれた分。範囲の終端が持つ 0 分は「まで」の側なので採らない\n // (「9時30分から17時まで」の分は 30 であって 0,30 ではない)\n const spanMinutes = [...new Set(spans.map((span) => span.from.minute))];\n\n /** 時刻の並びを時フィールドにする。書かれた範囲は範囲のまま残す */\n const hourList = (): FieldAST =>\n spansToAst(spans.map((span) => ({ from: span.from.hour, to: (span.to ?? span.from).hour })));\n\n /**\n * 時の刻み。「AからBまでN時間ごと」は範囲ごとに掛かるので、書かれた範囲それぞれに適用する。\n * 範囲が 1 つも無ければ起点を持たない全域からの刻み。\n */\n const hourStepAst = (step: number): FieldAST => {\n if (!hasRange) return { kind: \"step\", base: ANY, step };\n const items = spans.map<FieldAST>((span) =>\n span.to === null\n ? { kind: \"value\", value: span.from.hour }\n : stepAst({ kind: \"range\", from: span.from.hour, to: span.to.hour }, step, HOUR_SPEC),\n );\n const only = items[0];\n /* c8 ignore next -- hasRange が真なら 1 個以上ある */\n if (only === undefined) return { kind: \"step\", base: ANY, step };\n return items.length === 1 ? only : { kind: \"list\", items };\n };\n\n /** 「N時まで」が N 時台を含むことを断る。終端ごとに曖昧なので範囲の数だけ付ける */\n const noteHourRanges = () => {\n for (const span of spans) {\n const to = span.to;\n if (to === null) continue;\n slots.notes.push(\n `「${to.hour}時まで」を ${to.hour}時台まで(${span.from.hour}-${to.hour})と解釈しました。` +\n `${to.hour}:00 で終える場合は ${span.from.hour}-${to.hour - 1} を指定してください`,\n );\n penalize(\"時刻範囲の終端が曖昧\", 0.1);\n }\n };\n\n if (state.freqs.includes(\"minute\")) {\n slots.minute = ANY;\n if (hourStep !== undefined) {\n // 「2時間ごと(毎分)」の時の刻み。毎分だけを見て捨てると刻みが消える\n slots.hour = hourStepAst(hourStep);\n } else if (hasTime) {\n // 「午前9時台の毎分」のように時が書かれていれば、その時の中での毎分\n slots.hour = hourList();\n }\n noteHourRanges();\n } else if (minuteStep !== undefined || hourStep !== undefined) {\n if (minuteStep !== undefined) {\n // 「1分から59分まで2分ごと」の起点。範囲が書かれていなければ全域からの刻み\n slots.minute = stepAst(consumeBase(minutes, MINUTE_SPEC), minuteStep, MINUTE_SPEC);\n }\n if (hourStep !== undefined) {\n slots.hour = hourStepAst(hourStep);\n if (minuteStep === undefined) {\n slots.minute =\n minutes.items.length > 0\n ? listToAst(minutes)\n : { kind: \"value\", value: spanMinutes[0] ?? 0 };\n minutes.consumed = true;\n }\n } else if (hasRange) {\n slots.hour = hourList();\n }\n\n noteHourRanges();\n if (!hasRange && hasTime) {\n // 「午前9時台と午後6時台の5分ごと」のように時が並ぶことがあるので、全部を採る\n if (minuteStep !== undefined) slots.hour = hourList();\n // 「9時台の10分ごと」は「その時の中で N 分ごと」で、読み方は 1 つしかない。\n // 「9時に10分ごと」のように時が一点を指すときだけ、どちらの意味か決まらない\n const spanned = state.hourSpan && minuteStep !== undefined && hourStep === undefined;\n if (!spanned) {\n slots.ambiguities.push({\n field: \"hour\",\n question: \"「〜ごと」と時刻の両方が指定されています。どちらの意味ですか?\",\n candidates: [\n { value: \"interval\", label: \"指定した間隔で繰り返す\" },\n { value: \"at\", label: \"指定した時刻にだけ実行する\" },\n ],\n });\n penalize(\"間隔と時刻の併用\", 0.2);\n }\n }\n\n if (minutes.items.length > 0 && !minutes.consumed) {\n noteConflict(INTERVAL_LABELS.minute);\n if (state.lastAssign.minute === \"values\") slots.minute = listToAst(minutes);\n }\n } else if (hasTime) {\n // 「午前9時台の10分と44分」のように分が別に書かれていれば、そちらが分フィールド。\n // 「9時」が持つ 0 分は書かれた値ではないので、時だけを取る\n const writtenMinutes = minutes.items.length > 0;\n // 「9時30分と45分」のように時刻の側にも分が書かれていれば、分の二重指定\n if (writtenMinutes && spanMinutes.some((minute) => minute !== 0)) {\n noteConflict(INTERVAL_LABELS.minute);\n }\n\n slots.hour = hourList();\n noteHourRanges();\n\n const only = spanMinutes[0];\n if (writtenMinutes) {\n slots.minute = listToAst(minutes);\n } else if (spanMinutes.length === 1 && only !== undefined) {\n slots.minute = { kind: \"value\", value: only };\n } else {\n slots.minute = valuesToAst(spanMinutes);\n slots.notes.push(\"複数の時刻が指定されているため、時と分のすべての組み合わせで実行されます\");\n penalize(\"時と分の組み合わせが曖昧\", 0.1);\n }\n } else if (state.freqs.includes(\"hour\")) {\n slots.hour = ANY;\n slots.minute = minutes.items.length > 0 ? listToAst(minutes) : { kind: \"value\", value: 0 };\n } else if (minutes.items.length > 0) {\n slots.hour = ANY;\n slots.minute = listToAst(minutes);\n } else {\n slots.hour = { kind: \"value\", value: defaultHour };\n slots.minute = { kind: \"value\", value: 0 };\n const freqLabel = state.freqs[0] === undefined ? undefined : FREQ_LABELS[state.freqs[0]];\n slots.ambiguities.push({\n field: \"hour\",\n question: freqLabel === undefined ? \"何時に実行しますか?\" : `「${freqLabel}」は何時ですか?`,\n candidates: hourCandidates(0, 23),\n });\n penalize(\"時刻が指定されていない\", 0.4);\n }\n\n /* ---------------- 日付・曜日 ---------------- */\n\n const doms = state.lists.dom;\n const dows = state.lists.dow;\n const months = state.lists.month;\n const dayStep = state.intervals.day;\n const monthStep = state.intervals.month;\n\n if (state.nths.length > 0) {\n const items = state.nths.map<FieldAST>((entry) => ({\n kind: \"nth\",\n weekday: entry.weekday,\n nth: entry.nth,\n }));\n const first = items[0];\n /* c8 ignore next -- nths.length > 0 なら必ず取れる */\n slots.dow = items.length === 1 && first !== undefined ? first : { kind: \"list\", items };\n for (const entry of state.nths) slots.extensions.add(entry.nth === -1 ? \"L\" : \"#\");\n } else if (dows.items.length > 0) {\n slots.dow = listToAst(dows);\n }\n\n if (state.domSpecial === \"L\") {\n slots.dom = { kind: \"last\" };\n slots.extensions.add(\"L\");\n if (dayStep !== undefined) noteConflict(INTERVAL_LABELS.day);\n } else if (dayStep !== undefined) {\n // 「1日から3日ごと」は 1 日を起点にした刻み\n slots.dom = stepAst(consumeBase(doms, DOM_SPEC), dayStep, DOM_SPEC);\n if (doms.items.length > 0 && !doms.consumed) {\n noteConflict(INTERVAL_LABELS.day);\n if (state.lastAssign.dom === \"values\") slots.dom = listToAst(doms);\n }\n } else if (doms.items.length > 0) {\n slots.dom = listToAst(doms);\n }\n\n if (monthStep !== undefined) {\n slots.month = stepAst(consumeBase(months, MONTH_SPEC), monthStep, MONTH_SPEC);\n if (months.items.length > 0 && !months.consumed) {\n noteConflict(INTERVAL_LABELS.month);\n if (state.lastAssign.month === \"values\") slots.month = listToAst(months);\n }\n } else if (months.items.length > 0) {\n slots.month = listToAst(months);\n }\n\n const weekStep = state.intervals.week;\n if (weekStep !== undefined) {\n slots.notes.push(\n `cron には週単位の刻みが無いため「${weekStep}週間ごと」は表現できません。` +\n \"毎週として解釈しました\",\n );\n penalize(\"週単位の刻み\", 0.3);\n }\n\n /* ---------------- 頻度語の期待 ---------------- */\n\n const domSpecified = slots.dom.kind !== \"any\";\n const dowSpecified = slots.dow.kind !== \"any\";\n\n for (const freq of state.freqs) {\n if (freq === \"day\" && (domSpecified || dowSpecified)) {\n slots.notes.push(\n \"「毎日」と日付・曜日の指定が同時にあるため、日付・曜日の指定を優先しました\",\n );\n penalize(\"頻度語と日付指定の不一致\", 0.1);\n }\n if (freq === \"week\" && !dowSpecified) {\n slots.dow = { kind: \"value\", value: 1 };\n slots.ambiguities.push({\n field: \"dayOfWeek\",\n question: \"「毎週」は何曜日ですか?\",\n candidates: [\n { value: 0, label: \"日曜日\" },\n { value: 1, label: \"月曜日\" },\n { value: 2, label: \"火曜日\" },\n { value: 3, label: \"水曜日\" },\n { value: 4, label: \"木曜日\" },\n { value: 5, label: \"金曜日\" },\n { value: 6, label: \"土曜日\" },\n ],\n });\n penalize(\"「毎週」の曜日が未指定\", 0.3);\n }\n // 「3か月ごとの毎日」は日が決まっている。「毎日」が無いときだけ日を補う\n if (freq === \"month\" && !domSpecified && !dowSpecified && !state.freqs.includes(\"day\")) {\n slots.dom = { kind: \"value\", value: 1 };\n slots.ambiguities.push({\n field: \"dayOfMonth\",\n question: \"「毎月」は何日ですか?\",\n candidates: [\n { value: 1, label: \"1日\" },\n { value: 15, label: \"15日\" },\n { value: \"L\", label: \"月末\" },\n ],\n });\n penalize(\"「毎月」の日が未指定\", 0.3);\n }\n if (freq === \"year\" && slots.month.kind === \"any\") {\n slots.month = { kind: \"value\", value: 1 };\n if (slots.dom.kind === \"any\") slots.dom = { kind: \"value\", value: 1 };\n slots.ambiguities.push({\n field: \"month\",\n question: \"「毎年」は何月ですか?\",\n candidates: Array.from({ length: 12 }, (_, index) => ({\n value: index + 1,\n label: `${index + 1}月`,\n })),\n });\n penalize(\"「毎年」の月が未指定\", 0.3);\n }\n }\n\n /* ---------------- 衝突・減点 ---------------- */\n\n if (slots.dom.kind !== \"any\" && slots.dow.kind !== \"any\") {\n slots.notes.push(\n \"標準の cron では日と曜日を同時に指定すると OR 条件になり、どちらかに一致する日に実行されます\",\n );\n penalize(\"日と曜日の同時指定\", 0.2);\n }\n\n const hasDateToken =\n dows.items.length > 0 ||\n state.nths.length > 0 ||\n doms.items.length > 0 ||\n state.domSpecial !== null ||\n months.items.length > 0;\n const hasInterval = Object.keys(state.intervals).length > 0;\n if (state.freqs.length === 0 && !hasDateToken && !hasInterval) {\n slots.notes.push(\"頻度が明示されていないため、毎日として解釈しました\");\n penalize(\"頻度語が無い\", 0.2);\n }\n\n if (slots.extensions.size > 0 && options.allowExtensions !== true) {\n const used = [...slots.extensions].join(\"', '\");\n slots.notes.push(\n `'${used}' は Quartz 拡張です。標準の cron では動作しません(allowExtensions で抑制できます)`,\n );\n penalize(\"拡張構文の使用\", 0.1);\n }\n\n if (state.unknown > 0) {\n penalize(\"解釈できない語\", Math.min(0.3, state.unknown * 0.1));\n }\n\n return slots;\n}\n\n/** スロットを cron 式にする */\nexport function emit(slots: Slots): string {\n return [slots.minute, slots.hour, slots.dom, slots.month, slots.dow].map(formatField).join(\" \");\n}\n","const KANJI_DIGITS: Record<string, number> = {\n 〇: 0,\n 零: 0,\n 一: 1,\n 二: 2,\n 三: 3,\n 四: 4,\n 五: 5,\n 六: 6,\n 七: 7,\n 八: 8,\n 九: 9,\n};\n\nconst KANJI_RUN = /[〇零一二三四五六七八九十]+/g;\n\nfunction convertRun(run: string): string {\n if (!run.includes(\"十\")) {\n let digits = \"\";\n for (const char of run) {\n const digit = KANJI_DIGITS[char];\n /* c8 ignore next -- KANJI_RUN が一致した文字は必ず辞書にある */\n if (digit === undefined) return run;\n digits += String(digit);\n }\n return digits;\n }\n\n let total = 0;\n let current = 0;\n for (const char of run) {\n if (char === \"十\") {\n total += (current === 0 ? 1 : current) * 10;\n current = 0;\n } else {\n const digit = KANJI_DIGITS[char];\n /* c8 ignore next -- KANJI_RUN が一致した文字は必ず辞書にある */\n if (digit === undefined) return run;\n current = digit;\n }\n }\n return String(total + current);\n}\n\n/** 漢数字を算用数字に変換する(「半」はそのまま残す) */\nexport function kanjiToArabic(text: string): string {\n return text.replace(KANJI_RUN, (run) => convertRun(run));\n}\n\n/** 文末の動詞句・丁寧表現を落とす */\nconst TAIL_PATTERNS: RegExp[] = [\n /(に|で)?(実行|起動|開始|動作)(する|して|し|す)?(たい|ください|下さい|ます|ましょう|よう)?$/,\n /(して)?(ください|下さい|ほしい|欲しい|たい)$/,\n /(です|ます|だ|である)(か)?$/,\n /[。!!??、,\\s]+$/,\n];\n\nexport function stripTail(text: string): string {\n let result = text;\n for (let i = 0; i < 5; i++) {\n let changed = false;\n for (const pattern of TAIL_PATTERNS) {\n const next = result.replace(pattern, \"\");\n if (next !== result && next.length > 0) {\n result = next;\n changed = true;\n }\n }\n if (!changed) break;\n }\n return result;\n}\n\n/**\n * 解析前の前処理。NFKC 正規化 → 漢数字変換 → 文末表現の除去。\n */\nexport function normalize(text: string): string {\n return stripTail(kanjiToArabic(text.normalize(\"NFKC\")).trim()).trim();\n}\n","import type { TimeOfDayWord, Token } from \"../types\";\nimport { DOM_SPECIAL, DOW, DOW_SET, FREQ, type FreqUnit, NTH } from \"./dictionary\";\n\nexport type IntervalUnit = \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\";\n\nexport interface IntervalValue {\n unit: IntervalUnit;\n n: number;\n}\n\nexport interface TimeValue {\n hour: number;\n minute: number;\n}\n\ntype Rule = [RegExp, (match: RegExpMatchArray) => Omit<Token, \"raw\" | \"position\"> | null];\n\nfunction int(text: string | undefined): number {\n return Number(text ?? \"0\");\n}\n\n/** 範囲外の数値はトークンにしない(後続のルール、最終的には UNKNOWN に回す) */\nfunction inRange(value: number, min: number, max: number): boolean {\n return Number.isInteger(value) && value >= min && value <= max;\n}\n\n/**\n * 長い表現から順に試すため、並び順に意味がある。\n *\n * 「毎」で終わる間隔(「15分毎」)は、後ろに頻度語の単位が続く場合だけ採らない。\n * 「1月毎日」を「1か月ごと」+「日」と切ってしまうのを避けるため。\n */\nconst RULES: Rule[] = [\n [\n /^(\\d{1,2})時間(?:ごと|おき|毎(?![分時日週月年]))に?/,\n (m) => {\n const n = int(m[1]);\n if (!inRange(n, 1, 23)) return null;\n return { type: \"INTERVAL\", value: { unit: \"hour\", n } satisfies IntervalValue };\n },\n ],\n [\n /^(\\d{1,2})分(?:ごと|おき|毎(?![分時日週月年]))に?/,\n (m) => {\n const n = int(m[1]);\n if (!inRange(n, 1, 59)) return null;\n return { type: \"INTERVAL\", value: { unit: \"minute\", n } satisfies IntervalValue };\n },\n ],\n [\n /^(\\d{1,2})日(?:ごと|おき|毎(?![分時日週月年]))に?/,\n (m) => {\n const n = int(m[1]);\n if (!inRange(n, 1, 31)) return null;\n return { type: \"INTERVAL\", value: { unit: \"day\", n } satisfies IntervalValue };\n },\n ],\n [\n // 「か月」の表記ゆれ(か / ヶ / ヵ / ケ / カ / 箇)と、「3月ごと」の省略形を受ける\n /^(\\d{1,2})[かカヵケヶ箇]?月(?:ごと|おき|毎(?![分時日週月年]))に?/,\n (m) => {\n const n = int(m[1]);\n if (!inRange(n, 1, 12)) return null;\n return { type: \"INTERVAL\", value: { unit: \"month\", n } satisfies IntervalValue };\n },\n ],\n [\n /^(\\d{1,2})週間?(?:ごと|おき|毎(?![分時日週月年]))に?/,\n (m) => {\n const n = int(m[1]);\n if (!inRange(n, 1, 52)) return null;\n return { type: \"INTERVAL\", value: { unit: \"week\", n } satisfies IntervalValue };\n },\n ],\n [\n /^(\\d{1,2}):(\\d{2})/,\n (m) => {\n const hour = int(m[1]);\n const minute = int(m[2]);\n if (!inRange(hour, 0, 23) || !inRange(minute, 0, 59)) return null;\n return { type: \"TIME\", value: { hour, minute } satisfies TimeValue };\n },\n ],\n [\n /^(\\d{1,2})時(半|(\\d{1,2})分)?/,\n (m) => {\n const hour = int(m[1]);\n const minute = m[2] === \"半\" ? 30 : int(m[3]);\n if (!inRange(hour, 0, 23) || !inRange(minute, 0, 59)) return null;\n return { type: \"TIME\", value: { hour, minute } satisfies TimeValue };\n },\n ],\n [\n /^(\\d{1,2})分/,\n (m) => {\n const value = int(m[1]);\n return inRange(value, 0, 59) ? { type: \"MINUTE\", value } : null;\n },\n ],\n [\n /^(第[1-5]|最終|最後)(週|の)?/,\n (m) => {\n const nth = NTH[m[1] ?? \"\"];\n return nth === undefined ? null : { type: \"NTH\", value: nth };\n },\n ],\n [\n /^(\\d{1,2})月/,\n (m) => {\n const value = int(m[1]);\n return inRange(value, 1, 12) ? { type: \"MONTH\", value } : null;\n },\n ],\n [\n /^(\\d{1,2})日/,\n (m) => {\n const value = int(m[1]);\n return inRange(value, 1, 31) ? { type: \"DOM\", value } : null;\n },\n ],\n [\n /^(平日|週末|土日|休日)/,\n (m) => {\n const values = DOW_SET[m[1] ?? \"\"];\n return values === undefined ? null : { type: \"DOW_SET\", value: [...values] };\n },\n ],\n [\n /^(日|月|火|水|木|金|土)曜日?/,\n (m) => {\n const value = DOW[`${m[1]}曜`];\n return value === undefined ? null : { type: \"DOW\", value };\n },\n ],\n [\n /^毎?(月末|月初)/,\n (m) => {\n const value = DOM_SPECIAL[m[1] ?? \"\"];\n return value === undefined ? null : { type: \"DOM_SPECIAL\", value };\n },\n ],\n [\n /^(早朝|朝|正午|昼|夕方|夜中|深夜|夜|晩|午前|午後)/,\n (m) => {\n const word = m[1] as TimeOfDayWord;\n if (word === \"午前\" || word === \"午後\") return { type: \"AMPM\", value: word };\n return { type: \"TIME_OF_DAY\", value: word };\n },\n ],\n [\n /^毎(分|時|日|週|月|年)/,\n (m) => {\n const unit: FreqUnit | undefined = FREQ[`毎${m[1]}`];\n return unit === undefined ? null : { type: \"FREQ\", value: unit };\n },\n ],\n [\n // 「毎晩」「毎朝」は「毎日」+時間帯語。「毎」だけを頻度語として読み、\n // 続く時間帯語は次の周回で時間帯語の規則に任せる\n /^毎(?=早朝|朝|正午|昼|夕方|夜中|深夜|夜|晩)/,\n () => ({ type: \"FREQ\", value: \"day\" satisfies FreqUnit }),\n ],\n [/^(から|以降)/, () => ({ type: \"RANGE_FROM\" })],\n [/^(まで|以前)/, () => ({ type: \"RANGE_TO\" })],\n [/^(および|かつ|と|、|,)/, () => ({ type: \"AND\" })],\n // 「9時台」は「9時00分」ではなく 9 時の中を指す。区切りとして捨てると\n // 「9時台の10分ごと」が間隔と単独時刻の併用に見えるので、専用のトークンにする\n [/^台/, () => ({ type: \"HOUR_SPAN\" })],\n [/^(の|に|は|が|を|\\s|。)+/, () => ({ type: \"SEP\" })],\n];\n\n/**\n * 正規化済みの日本語をトークン列に分解する。\n */\nexport function tokenize(text: string): Token[] {\n const tokens: Token[] = [];\n let position = 0;\n\n while (position < text.length) {\n const rest = text.slice(position);\n let matched = false;\n\n for (const [pattern, build] of RULES) {\n const match = pattern.exec(rest);\n if (match === null || match[0] === \"\") continue;\n const token = build(match);\n /* c8 ignore next -- 辞書引きに失敗した場合のみ。通常は起きない */\n if (token === null) continue;\n tokens.push({ ...token, raw: match[0], position });\n position += match[0].length;\n matched = true;\n break;\n }\n\n if (!matched) {\n tokens.push({ type: \"UNKNOWN\", raw: text[position] ?? \"\", position });\n position += 1;\n }\n }\n\n return tokens;\n}\n","import { resolveTimeZone, shiftExpression } from \"../cron\";\nimport { ParseAmbiguityError } from \"../errors\";\nimport type { ParseOptions, ParseResult } from \"../types\";\nimport { emit, fill } from \"./fill\";\nimport { normalize } from \"./normalize\";\nimport { tokenize } from \"./tokenize\";\n\nfunction round2(value: number): number {\n return Math.round(value * 100) / 100;\n}\n\n/**\n * 日本語の予定表現を cron 式に変換する。\n *\n * 日本語は `options.tz`(既定 `'Asia/Tokyo'`)の壁時計として読み、UTC のサーバーで\n * 動かすための cron 式を返す。\n *\n * ```ts\n * parse('毎日午後1時').expression; // '0 4 * * *'(JST 13:00 = UTC 04:00)\n * parse('平日の朝9時', { tz: 'UTC' }).expression; // '0 9 * * 1-5'(変換しない)\n * ```\n *\n * @throws {ParseAmbiguityError} `strict: true` かつ解釈が曖昧な場合\n * @throws {CronTimeZoneError} `tz` を解釈できない、または UTC の cron 式に書き換えられない場合\n */\nexport function parse(text: string, options: ParseOptions = {}): ParseResult {\n const timeZone = resolveTimeZone(options.tz);\n\n const tokens = tokenize(normalize(text));\n const slots = fill(tokens, options);\n\n if (slots.empty) {\n const result: ParseResult = {\n expression: null,\n localExpression: null,\n tz: timeZone,\n confidence: 0,\n ambiguities: [],\n notes: [\"時間表現が見つかりませんでした\"],\n tokens,\n };\n if (options.strict === true) {\n throw new ParseAmbiguityError(\"時間表現が見つかりませんでした\", result);\n }\n return result;\n }\n\n const total = slots.penalties.reduce((sum, penalty) => sum + penalty.amount, 0);\n const local = emit(slots);\n const result: ParseResult = {\n expression: shiftExpression(local, timeZone, \"toServer\"),\n localExpression: local,\n tz: timeZone,\n confidence: round2(Math.max(0, 1 - total)),\n ambiguities: slots.ambiguities,\n notes: slots.notes,\n tokens,\n };\n\n if (options.strict === true && result.ambiguities.length > 0) {\n const first = result.ambiguities[0];\n throw new ParseAmbiguityError(\n `解釈が曖昧です: ${first?.question ?? \"入力を特定できません\"}`,\n result,\n );\n }\n\n return result;\n}\n\nexport * from \"./dictionary\";\nexport { emit, fill } from \"./fill\";\nexport { kanjiToArabic, normalize, stripTail } from \"./normalize\";\nexport { tokenize } from \"./tokenize\";\n"],"mappings":"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"}