Dominik Krzemiński

Zapis decyzji 0004Przyjęta

Dates carry month precision, not day precision

Ta strona nie została jeszcze przetłumaczona — czytasz angielski oryginał.

Context

Every period in the corpus — project timelines, employment — is naturally known to the month. Nobody remembers the day a project started, and no consumer of this data needs it. Modelling these as full dates forces an invented day, and that invented day then gets rendered, indexed, and cited as if it were a fact.

Decision

Periods use a YYYY-MM string in frontmatter, validated by a regex in Zod and parsed into a YearMonth readonly record struct in C#.

YearMonth implements IParsable<YearMonth> and IComparable<YearMonth>, has comparison operators, and serializes to and from its canonical string form through a JsonConverter. TypeScript keeps it as a validated string, which compares correctly with localeCompare precisely because the format is zero-padded and fixed-width.

period.end is optional; its absence means “current”, and Period.IsCurrent exposes that rather than making every consumer re-derive it.

Consequences

  • No invented precision reaches JSON-LD, the profile dump, or a RAG answer.
  • Sorting is lexicographic on the wire and structural in C#; both agree.
  • ToDateOnly() exists for the rare consumer that genuinely needs a DateOnly, and the widening to the first of the month is explicit at the call site.
  • A future need for day precision is a schema-version bump, not a silent change.

Alternatives rejected

z.coerce.date() / DateOnly. Fabricates a day and invites time-zone bugs in a value that has no time-zone meaning.

Free-text period strings (“Jan 2024 – present”). Unsortable, unlocalizable, and unparseable by the machine surface.

Wszystkie notatki