Custom Calendars
Your world probably does not run on Gregorian months. A ten-month year, a six-day week, a Founding-era epoch, an irregular leap cycle — the Spiral encoder treats all of these as a pure labelling layer over the same multi-scale coordinate. Pick a built-in projection, or define your own in-world calendar once and reference it on every /v1/spiral call. The phase math never changes; only the human-readable label does.
The calendar query param
Every /v1/spiral response is labelled by a calendar projection. Omit the field and you get gregorian, a pure pass-through. Pass ?calendar=<id> on the REST endpoint (or the calendar argument in an SDK) to relabel the same coordinate in another system. The projection only changes the meta.calendar label — your physics step and rung phases are byte-for-byte identical across calendars.
The shipped projections:
gregorian— Default. Pure label pass-through, no shape change.holocene— Human Era — re-numbers the year (HE = Gregorian + 10,000).cosmological— Big-Bang-anchored deep time; accepts gyr / yrBP shorthand.stardate— Continuous fractional stardate count.julian— Julian Day Number (continuous day count).unix-day— Fractional days since the Unix epoch.mjd— Modified Julian Day (JDN − 2,400,000.5).ut1— Earth-rotation time (UT1).gmst— Greenwich Mean Sidereal Time.lmst— Local Mean Sidereal Time.j2000— Julian centuries since the J2000.0 epoch.
The astronomical projections (ut1, gmst, lmst, j2000) and the deep-time cosmological shorthand are Standard or higher. The registry lives at lib/temporalspiral/src/calendars/; adding a projection there ships it everywhere the encoder runs.
Define your own world calendar
When none of the built-ins match your world, register a custom calendar as data. A definition is a small JSON document scoped to your API key (Standard or higher), created with POST /v1/calendars. Once stored, reference it as calendar=custom:<id> on any spiral call.
# Define a 10-month, 300-day world calendar with a leap cycle.
# Standard+ tier. The definition is scoped to this API key.
curl -s -X POST "https://api.temporalblock.com/v1/calendars" \
-H "X-API-Key: tblk_live_yourkeyhere" \
-H "Content-Type: application/json" \
-d '{
"id": "eldoria",
"yearDays": 300,
"monthCount": 10,
"monthNames": [
"Frostwane","Seedfall","Greentide","Highsun","Embermonth",
"Goldharvest","Mistreach","Duskfall","Longnight","Yearturn"
],
"weekDays": 6,
"weekNames": ["Sunday","Moonday","Forgeday","Tideday","Vineday","Restday"],
"eraNames": ["Before Founding","After Founding"],
"epochUtcMs": 0,
"leapCycleDays": 1501
}'CRUD lives under /v1/calendars: POST to create or replace, GET to list ({ count, items }) or read one by id, and DELETE /v1/calendars/:id to remove it. Posting the same id again replaces the definition in place.
Definition fields
| Field | Required | Meaning |
|---|---|---|
id | yes | Slug you reference as calendar=custom:<id>. Matches /^[a-z0-9][a-z0-9_-]{0,63}$/i. |
yearDays | yes | Whole days in a standard (non-leap) year. 1–10,000,000. |
monthCount | yes | Number of months the year is divided into. 1–1000. Days are split as evenly as possible; the first (yearLength mod monthCount) months get one extra day. |
monthNames | no | Optional month names; length must equal monthCount. Falls back to “Month <n>”. |
weekDays | yes | Length of the weekday cycle. The epoch day is weekday index 0; the cycle runs continuously from there. |
weekNames | no | Optional weekday names; length must equal weekDays. Falls back to “Day <n>”. |
eraNames | no | Optional eras. [0] labels years before the epoch; the last entry labels years on/after it (a single entry applies to both). 1–8 entries. |
epochUtcMs | no | UTC epoch-ms of this calendar's day 0 (year 1, month 1, day 1). Default 0 = the Unix epoch. |
leapCycleDays | no | Total days in one repeating leap cycle (e.g. Earth's Julian cycle = 4×365 + 1 = 1461). The surplus over whole years is distributed as one leap day onto the last years of the cycle. Must be ≥ yearDays. |
The label math is fully deterministic and documented in lib/temporalspiral/src/calendars/customCalendar.ts: the same instant always projects to the same year / era / month / day / weekday, so replays and lock-step multiplayer stay reproducible.
Use it on a spiral call
Pass calendar=custom:<id> and the response meta.calendar block comes back in your system — including display, year, era, monthName, dayOfMonth, dayOfYear, and weekdayName. Drive your in-world clock, season banner, and date UI directly from those fields.
# Relabel any spiral coordinate in your world calendar.
# The spiral PHASE math is unchanged — only the calendar label is
# reinterpreted into your year / era / month / day / weekday.
curl -s "https://api.temporalblock.com/v1/spiral?calendar=custom:eldoria&atUtcMs=1750000000000" \
-H "X-API-Key: tblk_live_yourkeyhere"
# meta.calendar carries the in-world label, e.g.
# { "display": "Highsun 12, Year 56 After Founding",
# "year": 56, "era": "After Founding",
# "month": 4, "monthName": "Highsun",
# "dayOfMonth": 12, "dayOfYear": 102,
# "weekday": 3, "weekdayName": "Tideday" }Custom calendars require a Standard or higher key. The default gregorian, holocene, and stardate projections are available on every tier. Get a key at temporalblock.com.
Related
Temporal Spiral is patent pending — U.S. Provisional Application No. 64/065,213 (filed 2026-05-14).