Every scheduler has a cron syntax, and most of them disagree. The five-field form Unix systems have used for decades puts the day of the week last and, when both day fields are restricted, fires on either. The Quartz dialect, used across the Java and .NET worlds, adds a seconds field, insists that one of the two day fields be a question mark, and until recently refused the expression Unix would accept. A major cloud provider's scheduler adds a year, evaluates only in UTC, and publishes worked examples rather than a test suite. A line that is legal in several of them can mean something different in each, and the person who typed it usually finds out which at three in the morning.
CronCal exists so that the finding-out happens before the job ships. Paste an expression, say which dialect it is written in, and it draws the fire times on a calendar — by month, by week, or as an agenda — says in plain English what the expression means, and gives you a link that shows anyone else exactly what you saw. It is the practice's own product: planned in April 2026, live on its own domain at the start of September after some months of quiet internal use, and signed off against production on 24 September, every item of its acceptance checklist re-run at a single commit.
What it does now
Four dialects — Unix, Quartz 3, Quartz 4 and a major cloud provider's — named the way their schedulers name them. Two time zones rather than one: the zone the rule is evaluated in and the zone the fire times are shown in, because a job scheduled in one country is usually watched from another. Month, week and agenda views; a plain-English description, generated deterministically and offline; a cheatsheet and a reference page for each dialect; a cookbook; and a builder for assembling an expression field by field. A compare mode that shows where two expressions' fire times differ, a diff of what will happen rather than of the text. Export to a calendar file. And a converter between dialects that says plainly when an expression has no equivalent, and why.
Everything it knows is in the address bar. There are no accounts and nothing is stored; the share link is the state, and a link that names a view zone reproduces that zone for whoever opens it rather than quietly substituting their own. It sets no cookies, and the whole calculation runs in the visitor's browser, as a .NET application compiled to WebAssembly, so nothing typed into it is sent anywhere. And it does not run anything. CronCal previews schedules; it is not a scheduler and not a monitor, and its own About page says so, because the narrowness is the point.
Right rather than plausible
A tool whose whole promise is to tell you what your scheduler will do cannot be approximately right. So the parsers behind the dialects are checked against the reference implementations' own test suites, not only against cases written here: 950 rows generated from the Unix reference implementation's tests, 140 curated from the tests of the library behind Quartz, and — since the cloud provider publishes no test suite for its dialect — 39 taken from its own documentation. Cases written here test what their author thought of; a reference implementation's own suite tests what its maintainers were bitten by.
Each corpus is pinned to the exact version of the library the application ships, and a test fails when the two disagree, so an automated dependency update cannot land until its corpus has been refreshed with it. That is deliberate, because the last major version to arrive changed what an expression means.
Two Quartzes
That major version is why there are two Quartzes. The investigation before adopting it found that it accepts an expression its predecessor rejects — a day-of-month and a day-of-week restricted together — and fires on either, the way Unix does. The same line now had two correct answers, depending on which version a reader's scheduler ran. Following the new version would have made CronCal confidently wrong for the much larger population still on the old one; staying put would have made it slowly wrong for everyone else. CronCal already models exactly that kind of divergence as a dialect, so the upgrade was held, the question was raised as a product decision rather than a dependency bump, and the answer, recorded as an architecture decision, was two dialects.
Quartz 3 and Quartz 4 now sit side by side, and plain Quartz still means the older, so a link anybody had already shared keeps the meaning it had when they shared it. One project cannot reference two major versions of the same package, so the newer engine is carried as source, each of its ten files pinned by hash, and three hundred cases from the new version's own tests passed on the first run. The converter refuses to carry a step counted from a named day, such as FRI/2, between the two Quartzes, and says why: it means different days in each.
The missing hour
A cron rule is written in wall-clock time, and wall clocks are not continuous. Twice a year in most of the world an hour is skipped or repeated, and what a scheduler does with a job due at half past one on such a night depends on which scheduler it is: Unix cron skips the missing hour and fires once in the repeated one; Quartz runs at the moment the clocks change; the cloud provider's classic rules are evaluated in UTC and are untouched. CronCal evaluates every rule in its own zone and resolves both hours the way each real engine does, marks the transition days on the calendar, and explains in the day's popover what will happen and why. Underneath that is a bridge between two models of a time zone that do not agree on their shapes, and the measure of exact was stated rather than assumed: all 597 zones in the public time-zone database round-trip without deviation from 2020 onwards, a test pins that range at zero, and the record says where, before 2020, it is not. A cron calendar schedules forwards.
— On tests —A test that cannot go red is decoration. Nothing here was believed until it had been seen to fail.
Believed only once seen to fail
The test suite is large — some two and a half thousand tests by September — and a large suite proves little if nobody has checked that it can fail. Mutation testing, which makes small deliberate changes to the code and expects a test to notice each one, had been blocked by tooling since June. When it could finally run, its verdicts were tested by hand before they were believed: one reported survivor was reproduced in the source, with all 1,966 tests of that project still passing, and two identical runs that disagreed on nineteen mutants proved another class of verdict unreliable, so that class is excluded, each exclusion with its reason beside it. The one parser written from scratch here, for the cloud provider's dialect, finished with every one of its 122 mutants detected.
The same habit governs smaller things. Accessibility scored one hundred on every audited page in both colour themes, and the second half of that sentence is the one that took the work, because the audit tool only ever checks the light scheme and CronCal's primary theme is dark. The guard that came out of it is a unit test that reads the design tokens and computes the contrast ratio for twenty-four text-on-surface pairs in both themes — no browser, milliseconds — and it was verified to go red with the fix removed. So was the test that every route fits a 320-pixel screen without sideways scrolling.
A target the arithmetic could not reach
The acceptance checklist was amended four times between April and September, each time for a recorded reason, and one is worth stating. The specification asked for a mobile performance score of at least ninety from the audit tool, and the audit established that the architecture cannot reach it: the home route ships about four megabytes, the throttled mobile profile downloads at about 184 kilobytes a second, and the division comes out at twenty-one seconds, which is the measured time to the largest paint almost exactly. The download is the metric. So the target moved rather than the architecture: a floor set a few points under the worst median observed, so that ordinary variance cannot trip it, because an ignored gate is worse than none; and a transfer budget tight enough that the next careless dependency will. Payload is the number actually under our control. Half a megabyte came off first load from a single line, and the score moved within noise.
What it costs to run
The brief said zero, and the brief nearly held. CronCal is static files on a hosting tier that costs nothing, deployed by a workflow that costs nothing, with analytics that set no cookies and a monitor outside, on a free plan, watching it every five minutes. Its one spend is the domain, about ten pounds a year, taken as a trade-off against an address nobody would remember. The domain sends no mail and says so: a sender policy that authorises nobody, a reject policy above it, and a null mail record telling anyone who tries to deliver there that nothing is listening.
There were no launch posts. The announcements planned for June were parked, the directory listings declined, and CronCal is found by search instead, verified with the search engines and its sitemap submitted. It ships a privacy notice, a vulnerability disclosure policy, and a credits page listing every library it depends on with its licence, because a free tool built on other people's work should say so.
CronCal is the practice working for itself, the one engagement where the brief, the deadline and the compromises are all ours. The habits are the ones a client gets: a thing that is right rather than plausible, with the measure of right stated; decisions written down where the next person will find them; a target moved when the arithmetic says it must be; and a test trusted only once it has been seen to fail.