Yarunoka
Calendar-aware schedule DSL and pure occurrence query engine.
The name is the Japanese question やるのか?(yaru no ka?) — roughly “so, do we do it?”. That is the question this engine exists to answer.
Yarunoka is looking for a logo and an icon — want to contribute? Reach out on X: @chatii
Calendar rules, not clock rules
Real-world schedules are calendar rules. “Payday is the 25th — moved up to the previous business day when that falls on a weekend or a holiday.” “Collection day is the second Tuesday of every month.” “The poller runs every 90 minutes, but only within business hours.” Cron expressions and plain timestamps cannot carry these rules, so they end up as scattered application code — hard to store, hard to display, and impossible for users to edit safely.
Yarunoka is a small JSON DSL — Yrnk — that states such rules as data, plus an engine that answers questions about them.
A schedule is data
Payday: the 25th, shifted back to the previous business day.
{
"version": "1.1",
"timezone": "Asia/Tokyo",
"calendar": {
"holidays": ["2026-01-01", "2026-07-20"],
"business_holidays": [],
"business_days": []
},
"schedules": [
{"days": [25], "shift": ["prev", "or_same", "business_day"], "times": ["10:00"]}
]
}2026-07-25 is a Saturday, so the payday shifts back to Friday the 24th. Ask the engine:
matches 2026-07-24 10:00- true
matches 2026-07-25 10:00- false
Three parts
- Document
- A document carries a timezone, a calendar, and a list of schedules. The calendar is the definitions that give meaning to the calendar vocabulary: holidays, business holidays, extra business days, the workweek, business hours, and custom named date sets. A date set is written as a fixed date list or as the name of a resolver the application registers at runtime.
- Schedule
- A schedule combines a day expression (days of the month, weekdays, ordinal weekdays, calendar words such as
holiday, day cycles), an optional shift rule (“the previous business day”), and the times of day (fixed points, grids such as every 90 minutes, or all-day). - Engine
- The engine is pure. It executes no jobs and persists no state; it answers “does this date-time match?” and “was there an occurrence in this interval?”. Firing, catch-up, and throttling remain design decisions of the caller.
Get started
PHP
Install with Composer:
composer require yarunoka/core
Requires PHP 8.4 or newer. No runtime dependencies.
PHP (Laravel)
Install with Composer:
composer require yarunoka/laravel
Requires PHP 8.4 or newer and Laravel 13.
TypeScript
Install with npm:
npm install @yarunoka/core
Requires Node.js 26 or newer — or any runtime with the Temporal API, which a polyfill can supply. No runtime dependencies. ESM only.
TypeScript (Headless Builder)
Install with npm:
npm install @yarunoka/builder @yarunoka/core
Requires Node.js 26 or newer — or any runtime with the Temporal API,
which a polyfill can supply. @yarunoka/core is a peer dependency.
ESM only.
Repositories
- yarunoka-dev/spec
The language-independent DSL specification: JSON Schemas and the specification text.
- yarunoka-dev/test
The conformance test kit: the authored cases and the runner that judges them, in one binary.
- yarunoka-dev/php-core
The PHP implementation: parser, builder, and the pure evaluator.
- yarunoka-dev/php-laravel
The Laravel bridge for php-core.
Roadmap
- TypeScript core and UI libraries.