A calculator for the time you have left: how many free hours you have, and where the rest of them go.
Welcome to site: denisdrobyshev.github.io/kairos · In russian
The Greeks had two words for time: chronos, time as measurable quantity, and kairos, time as quality and the right moment. This project is about converting the first into the second.
Calculators like this normally work by subtraction: take a lifespan, remove sleep, work, commuting and chores, and call the remainder your real life. The method has two defects.
Subtraction silently changes units. Once sleep is removed, the remainder is no longer measured in 24-hour days, so any further hours-per-day figure subtracted from it is nonsense. The hand calculation that started this project went wrong by a factor of 9.5 at exactly that step: it produced 4,902 discretionary hours where the same harsh assumptions actually give 46,800.
Subtraction passes a value judgement disguised as arithmetic. It asserts that work, meals and commuting are not your life. Dinner with someone you love lands in the column marked "eating, minus ninety minutes". That is the calculator author's decision, not a property of the world.
Here everything accumulates in hours from a single horizon and converts to other units only for display. Each category goes into one of three buckets, and the user assigns them:
- living — you count it as lived;
- cost — the price of existing;
- leak — you would take it back.
The same hour lands in different buckets for different people. The arithmetic does not settle that.
Commuting, chores, meals and exercise occupy your hands but not your attention, so a second activity can run on top: lectures on the train, a feed while washing up, a call on a walk. Those categories carry an "of that, spent on" row.
An overlap never changes the number of hours. The commute gets no shorter because you filled it — what changes is what those hours count as: the overlapped share leaves the host's bucket and joins the guest's. An unavoidable hour is not shortened, it is redeemed by what you put in it.
The share is declared on the host rather than the guest, which is not cosmetic. The commute is counted per working day and feeds per calendar day, so a share of the commute can only be expressed in the commute's own cadence — otherwise the arithmetic drifts, which is the exact error this project exists to correct.
Gompertz–Makeham: μ(x) = A + B·exp(C·x).
The parameters are not hand-tuned. They are generated by tools/fit_mortality.py from WHO life tables for 2021. Across every adult age from 22 to 83, the model reproduces published life expectancy to within 0.32 years. The check lives in the test suite and compares against a captured WHO extract rather than against a number in a comment.
The objective is the ex curve, not the mx curve. Weighting is the reason: mortality at 20 is three orders of magnitude below mortality at 85, so an even fit in log-rate space lands 1–2 years off on life expectancy — the quantity a reader actually reads.
Logistic old-age deceleration was tried and removed: the parameter is not identifiable from abridged tables that close at 85+, and the optimiser drove it to values around 1e-40.
Period and cohort. WHO tables freeze today's mortality forever. Over the past half-century, age-specific mortality has fallen by roughly 1–2% a year. The correction is a toggle and defaults to a cautious 1%; for a 22-year-old man in Russia it moves the median age at death from 70.6 to 76.0.
There is no single number. There is a distribution, and it is wide: 39 years separate the early and late outcomes for the same person. A calculator that hands you one date is lying through precision, so every figure here is shown as a range.
Magnitudes, not advice. One hour a day, held for the rest of the horizon, is worth about two and a half years — a single exchange rate, stated once.
What follows compares things of genuinely different size: a four-day week, working from home, stopping work five years earlier, ten more vacation days. Structural decisions almost always beat daily discipline, and the list is ranked by magnitude rather than by how virtuous each option sounds.
Habits enter the list only from the leak bucket. An earlier version pulled in any large category and recommended cutting an hour of sleep to anyone who had not moved the label. That inverts the design: the user does the classification, and the arithmetic does not get to overrule it.
Nothing is sent anywhere. The computation runs in the browser and state lives in the address bar and in localStorage. A link to a result is the entire result, and it stays readable: age=22&sex=male&c=sleep-8-n_work-8-n_….
npm install
npm run dev
npm test
npm run buildRegenerate the mortality constants from the WHO API:
python tools/fit_mortality.pyThe core in src/core/ knows nothing about the DOM and imports nothing from src/ui/. That is not aesthetics: the same code will consume tracker data.
The second half is not another activity tracker. RescueTime, ActivityWatch, Rize and Timing already exist, and writing one more means spending thousands of hours reproducing what is finished.
The gap is next to them. Every tracker answers how much today. None answers what it cost at the scale of a life. The bridge from daily telemetry to lifetime accounting is what the second half is for: events come from a local ActivityWatch instance over its REST API, fall into the same categories, and get compared against what the user entered by hand. The interesting quantity is the gap between those two numbers.
That is why categories in src/core/taxonomy.ts already carry an aw field of application and URL matchers the calculator never reads. Category ids are the contract between the two halves; renaming one breaks compatibility.
Design notes: docs/tracker.md.
MIT.