storiesDating a charm
also: the methods note · how /time/ is built · astronomical years
storieEverywhere
The timeline on this site is drawn from one field. Every record may carry a `dating` block with a start year, an end year, a flag saying whether people still carry the thing, and a word saying how the date is known. Those four values put a bar on /time/ and nothing else does. This record is the methods note that page links to: what the numbers mean, what the four kinds of date are worth against each other, why the years are stored in a form no museum label uses, and why a record with no bar is a statement about this project rather than about the object.
citedWhen
2026, when this atlas was built, to now still carried cited
| Period | the convention as applied in this build |
|---|---|
| How the date is known | textual — a dated text describes it |
| Note | This record dates itself, not its subject. The astronomical-year convention is much older than this project; the fields, the anchors and the counts described here are of this repository as read on 17 September 2026. |
Years are stored astronomically — 1 CE is 1, 1 BCE is 0, 500 BCE is −499 — and printed the way a reader says them. How these dates are made.
Astronomical years, and why the arithmetic needs them
This atlas stores years as astronomical integers. 1 CE is 1. 1 BCE is 0. 500 BCE is −499. 3000 BCE is −2999.
The reason is a gap. The conventional era has no year zero: 1 BCE is followed directly by 1 CE. Subtract across that boundary in the conventional numbering and the answer is wrong by one, every time, silently. A span from 500 BCE to 100 CE is not 600 years; it is 599. Astronomical numbering closes the gap by naming 1 BCE as zero, after which every span in this atlas is ordinary integer subtraction and every sort is an ordinary sort.
The conversion back out is one line, and it lives in `tools/common.py`, `tools/viz.py` and `tools/cards.py` identically:
return f"{1 - y} BCE" if y <= 0 else f"{y} CE"
So a reader never sees a negative number. −2999 prints as 3000 BCE, 79 prints as 79 CE, and a null prints as "now". The convention is for the code; the label is for the reader; the two are kept apart on purpose.
Inference — the cost of this choice is that an author writing a record has to convert, and converting is where an error would enter. That is why every `dating` block in the atlas also carries `label`, the span in words as a person would say it, and `note`, saying which fact the year was taken from. Two fields that a reader can check against the integer.
Six ways a date is known, and they are not equivalent
The `method` field takes one of seven values: excavated, inscribed, textual, art-historical, dated-object, ethnographic, undated.
Counted across the 234 records written as of 17 September 2026, 195 carry years. Their methods:
textual — 105
excavated — 48
dated-object — 19
art-historical — 14
ethnographic — 7
inscribed — 1
undated but with a period name — 1
Inference — that distribution is a portrait of the sources, not of the subject. This atlas was built largely from encyclopedia articles, museum pages and published scholarship, so more than half its dates are textual — somebody read a text that mentions the thing. An excavated date is an object in a layer. An inscribed date is the object saying its own year. A dated-object date means a single example is dated and the form behind it is not. An ethnographic date is the year somebody stood in front of the practice and wrote it down.
Those are four different claims and a timeline bar makes them look identical. `method` is the only thing on the page that prevents a reader treating a Middle Kingdom excavation and a Victorian folklorist's notebook as the same kind of fact, which is why the field is required reading and not decoration. On the chart, one distinction is drawn in ink: a bar whose method is inference, undated or art-historical is dashed rather than solid.
What "still carried" means, exactly
An open end is a claim, and the schema forces it to be an explicit one.
`to_year: null` plus `living: true` means people carry the thing as of the record's `updated` date. The validator refuses `living: true` with a `to_year` set — a living practice runs to null — and refuses any `to_year` later than 2026, the year the checker is pinned to. On the chart the bar runs to the right-hand gutter and ends in an open circle rather than a stop.
154 of the 195 dated records are open in this sense. That is a large share and it should be read carefully. It does not mean the practice is thriving, widespread, or unchanged. It means this project read a source saying somebody still does it, and it dates from `updated`, not from now. A record last touched in September 2026 saying `living: true` is a claim about September 2026 and it will age.
The opposite case is written the same way. `the-charm-in-the-wall` closes at 1991 and is not marked living, because the account read here reports the British custom of hiding shoes as having died out during the twentieth century. A closed bar is as much a sourced claim as an open one.
The axis is not linear, and the page says so out loud
Five thousand years drawn to a single scale gives the last two centuries about a millimetre of chart, and the last two centuries are where half these records live.
So the axis is piecewise. The anchors, in `tools/viz.py`, map years to fractions of the width:
−11000 → 0.00 · −3000 → 0.14 · −1000 → 0.28 · 0 → 0.40 · 500 → 0.48 · 1000 → 0.56 · 1500 → 0.66 · 1800 → 0.76 · 1900 → 0.84 · 1950 → 0.90 · 2000 → 0.96 · 2026 → 1.00
Read those as a statement of bias, because that is what they are. The twenty-six years from 2000 to 2026 get 4 per cent of the width. The eight thousand years from 11,000 BCE to 3000 BCE get 14 per cent. A century near the right-hand end is drawn roughly two hundred times wider than a century at the left.
Every anchor gets a printed tick, and a label is dropped only where it would overprint its neighbour — the tick stays, so a reader can see the stretching happening rather than be fooled by it. Inference — a chart that quietly rescales is worse than one that does not rescale at all, because the reader takes distance as time. Printing the ticks is the whole defence.
An undated record is not an undated object
Nineteen amulet, tradition, sign and practice records carry no start year as of 17 September 2026, and the /time/ page lists them by name rather than dropping them: the mirror sign, the horn, the footprint, the phallic sign, ping an fu, hei matau, ojo de venado, rudraksha, palad khik, nimbu mirchi, the yantra plate, the bagua mirror, the navaratna ring, the worry stone, patua, hei tiki, tupilaq, milagro, and washing off ink.
The build's own note on that list is the sentence this record exists to explain: an undated record is one nobody here could date from a source, not one with no history.
The horn is the sharpest case. Roman use is dated through the fascinum. Illyrians used horn shapes against the same harm. Southern Italy cuts a cornicello today. What this project has not read is a published date range for the sign as a class — and stitching one together from the three would be inventing a span and then drawing it as if it were measured.
The opposite failure is also visible in the data and is handled by naming it. The gau box and the sungkhor both carry `method: dated-object` with the note that the dated example is of the 2000s while the form is older and undated here. Their bars start in the twenty-first century, which is wrong about the object and right about the evidence, and the note says which.
Inference — the two oldest bars in the atlas are jet and the swastika sign, both starting at −9999, both excavated, both drawn from the earliest published attestation of the material or the shape rather than of any amulet. Length of bar is not antiquity of practice. It is the reach of somebody's spade plus the reach of somebody's publication, and a reader who takes the left-hand edge as the beginning of anything is reading the collecting history of archaeology.
What this is near
What names this one
Each in its own words, from its own page.
Where this came from
- tools/build.py, tools/harvest_commons.py and the tables in build/api/ — Amulet Atlas — this repository read 2026-09-17
- schema/node.schema.json and tools/validate.py — Amulet Atlas — this repository read 2026-09-16
- tools/viz.py — every drawn thing on this site, as inline SVG — Amulet Atlas — this repository read 2026-09-16
- data/vocab/*.json — the controlled vocabularies, and the records in data/nodes/ — Amulet Atlas — this repository read 2026-09-17
Record updated 2026-09-17. This record as JSON. Every field carries its own provenance; the tier chips above say which.