2026-09-18 09:09:32 -04:00
|
|
|
# typikon
|
|
|
|
|
|
2026-09-18 10:53:03 -04:00
|
|
|
The Orthodox liturgical day: feasts, seasons and the fast, computed rather
|
2026-09-21 07:46:58 -04:00
|
|
|
than fetched. Twenty Orthodox jurisdictions and four Byzantine Catholic
|
|
|
|
|
churches, across the Julian, Revised Julian and Gregorian reckonings.
|
2026-09-18 09:09:32 -04:00
|
|
|
|
|
|
|
|
Everything derives from the paschalion and the fixed calendar, so it needs no
|
|
|
|
|
network, cannot go stale, and answers for any year you ask about. No API key,
|
|
|
|
|
no service that might be gone next year, no cache to invalidate.
|
|
|
|
|
|
|
|
|
|
```console
|
2026-09-18 12:44:09 -04:00
|
|
|
$ typikon --jurisdiction rocor --date 2026-03-18
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
Wednesday 18 March 2026 — 5 March in the church calendar
|
2026-09-18 12:44:09 -04:00
|
|
|
Russian Orthodox Church Outside Russia · the Typikon · slavic usage
|
2026-09-18 09:09:32 -04:00
|
|
|
|
|
|
|
|
🥬 The Holy Martyr Conon
|
|
|
|
|
|
|
|
|
|
xerophagy — no oil or wine
|
|
|
|
|
a weekday of the Great Fast
|
|
|
|
|
Great Fast
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
A week at a time, which is what you want the day before a fast begins:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --jurisdiction antiochian --date 2027-04-26 --days 7
|
|
|
|
|
|
|
|
|
|
Antiochian Orthodox Church · the Typikon
|
|
|
|
|
|
|
|
|
|
🥬 Mon 26 Apr xerophagy — no oil or wine The Holy Hieromartyr Basil, Bishop…
|
|
|
|
|
🥬 Tue 27 Apr xerophagy — no oil or wine The Holy Hieromartyr Symeon, kinsman…
|
|
|
|
|
🥬 Wed 28 Apr xerophagy — no oil or wine The Holy Apostles Jason and Sosipater
|
|
|
|
|
🫒 Thu 29 Apr wine and oil permitted Great and Holy Thursday
|
|
|
|
|
⛔ Fri 30 Apr no food until evening Great and Holy Friday
|
|
|
|
|
🥬 Sat 1 May xerophagy — no oil or wine Great and Holy Saturday
|
|
|
|
|
🍖 Sun 2 May no fast The Radiant and Life-giving…
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## Install
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
One static binary, no runtime to install first.
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
```console
|
2026-09-18 11:13:10 -04:00
|
|
|
$ cargo install --git https://git.pumpin.online/funkpower/typikon
|
2026-09-18 09:09:32 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-18 13:40:37 -04:00
|
|
|
Rust 1.85 or newer. The name `typikon` on crates.io belongs to an unrelated
|
|
|
|
|
project, so `cargo install typikon` and a `typikon = "1"` dependency will not
|
|
|
|
|
get you this; install and depend on it by git URL.
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
Or build it from a checkout:
|
2026-09-18 09:09:32 -04:00
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ git clone https://git.pumpin.online/funkpower/typikon
|
2026-09-18 11:13:10 -04:00
|
|
|
$ cd typikon && cargo build --release
|
|
|
|
|
$ install -Dm755 target/release/typikon ~/.local/bin/typikon
|
2026-09-18 09:09:32 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
The menologion is compiled in, so the binary answers for every day of the year
|
|
|
|
|
on its own: no data file to find, no network, nothing to go stale.
|
|
|
|
|
|
2026-09-18 11:27:51 -04:00
|
|
|
For Python, there is a wheel:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ pip install typikon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The menologion is compiled into that too, so it carries no data files and needs
|
2026-09-18 13:40:37 -04:00
|
|
|
no network either. Wheels are built for Linux on x86-64 and aarch64; everywhere
|
|
|
|
|
else pip falls back to the source distribution, which needs a Rust toolchain of
|
|
|
|
|
1.85 or newer on the installing machine.
|
2026-09-18 11:27:51 -04:00
|
|
|
|
2026-09-18 14:55:31 -04:00
|
|
|
For JavaScript and TypeScript, there is a package:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ npm install typikon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
WebAssembly, so the one package serves Node, Deno, Bun and the browser with no
|
|
|
|
|
native build to go wrong.
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## Which calendar?
|
|
|
|
|
|
|
|
|
|
Three things get conflated constantly, and keeping them apart is most of what
|
|
|
|
|
this library is for:
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
|---|---|
|
2026-09-18 10:53:03 -04:00
|
|
|
| **Paschalion** | which table gives Pascha, Julian or Gregorian |
|
2026-09-18 09:09:32 -04:00
|
|
|
| **Menologion** | which calendar the fixed feasts are read on |
|
|
|
|
|
| **Rule** | which fasting discipline is kept |
|
|
|
|
|
|
|
|
|
|
Almost every Orthodox Church keeps the **Julian Paschalion**. What divides them
|
|
|
|
|
is the menologion. The old-calendar churches read the fixed feasts on the
|
|
|
|
|
Julian calendar too; the new-calendar churches read them on the Revised Julian,
|
|
|
|
|
which agrees with the Gregorian for every date until 2800. So a new-calendar
|
2026-09-18 10:53:03 -04:00
|
|
|
church keeps the Nativity with the West and Pascha with the East, not a
|
2026-09-18 09:09:32 -04:00
|
|
|
compromise but exactly what the 1923 congress decided.
|
|
|
|
|
|
2026-09-18 11:28:40 -04:00
|
|
|
### Greek or Slavic usage
|
|
|
|
|
|
|
|
|
|
Both keep the same Typikon and read it a little differently. Two of those
|
|
|
|
|
differences are modelled, and each is visible in the output:
|
|
|
|
|
|
|
|
|
|
| | Slavic | Greek |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| The Protection, 1 October | great feast | lower rank; Greece keeps it on 28 October besides |
|
|
|
|
|
| Fish in the Nativity Fast | Saturdays and Sundays | any day but Wednesday and Friday, until 17 December |
|
|
|
|
|
|
|
|
|
|
Every jurisdiction carries the usage its books follow. `--tradition slavic` or
|
|
|
|
|
`--tradition greek` overrides it, which is what you want for a parish that does
|
|
|
|
|
not match its jurisdiction's default.
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
```console
|
|
|
|
|
$ typikon -j goarch --date 2026-10-01 --format tsv --fields rank,sign,fast,title
|
|
|
|
|
rank sign fast title
|
|
|
|
|
vigil ✚ none The Protection of our Most Holy Lady the Theotokos
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon -j goarch --date 2026-10-01 --tradition slavic --format tsv --fields rank,sign,fast,title
|
|
|
|
|
rank sign fast title
|
|
|
|
|
great ⊕ none The Protection of our Most Holy Lady the Theotokos
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The rank is not decoration: it is what lifts a Wednesday or Friday fast, so the
|
|
|
|
|
usage changes what you eat as well as what you sing.
|
|
|
|
|
|
2026-09-18 11:28:40 -04:00
|
|
|
### Which calendar?
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
Pick a reckoning without naming a church:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --calendar old # Julian throughout
|
|
|
|
|
$ typikon --calendar new # Revised Julian fixed feasts, Julian Pascha
|
|
|
|
|
$ typikon --calendar western # Gregorian throughout
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Or name one, which also picks up its fasting rule and any local saints:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --jurisdiction rocor
|
|
|
|
|
$ typikon --jurisdiction antiochian --days 7
|
|
|
|
|
$ typikon --list # every accepted value
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The first run writes your choice to `~/.config/typikon/config.toml` and stops
|
2026-09-18 12:29:57 -04:00
|
|
|
asking. `--set-default` remembers the whole invocation, not just the
|
|
|
|
|
jurisdiction:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --set-default ruthenian --typikon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
records the discipline and the usage alongside the church, so a terminal and a
|
|
|
|
|
desktop widget on the same machine cannot end up disagreeing about the same
|
|
|
|
|
day. Override any of it for one run with the flags, or set
|
|
|
|
|
`TYPIKON_JURISDICTION`.
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 13:03:52 -04:00
|
|
|
Twenty Orthodox jurisdictions ship: the old-calendar churches (Moscow, ROCOR,
|
|
|
|
|
Serbia, Georgia, Jerusalem, the Holy Mountain, Poland, Macedonia, ACROD), the
|
2026-09-18 09:09:32 -04:00
|
|
|
new-calendar ones (Constantinople, Greece, GOARCH, Antioch, the OCA, Romania,
|
2026-09-18 13:03:52 -04:00
|
|
|
Bulgaria, Cyprus, Albania, Ukraine), and the Finnish Orthodox Church, alone
|
|
|
|
|
among the Orthodox in keeping the Gregorian Paschalion. Four Byzantine
|
|
|
|
|
Catholic churches ship alongside them.
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 13:03:13 -04:00
|
|
|
## The Byzantine Catholic churches
|
|
|
|
|
|
|
|
|
|
Four are modelled, and they are not a footnote on the Orthodox ones: they keep
|
|
|
|
|
different paschalions, and their fasting is a different kind of thing.
|
|
|
|
|
|
|
|
|
|
| | calendar | fasting |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `ruthenian` | Gregorian throughout | Ruthenian particular law, sourced |
|
|
|
|
|
| `ugcc` | Revised Julian feasts, Julian Pascha since 2023 | its own; not modelled |
|
|
|
|
|
| `melkite` | Gregorian; Middle Eastern parishes often keep Julian Pascha | its own; not modelled |
|
|
|
|
|
| `romanian-catholic` | Gregorian throughout | its own; not modelled |
|
|
|
|
|
|
|
|
|
|
**A church's law is never borrowed from another.** Ruthenian particular law is
|
|
|
|
|
sourced from the Metropolia of Pittsburgh and is reported for that church only.
|
|
|
|
|
The rest are shown at the Typikon's discipline with **nothing reported as
|
|
|
|
|
binding**, because their own law has not been sourced and inventing one would
|
|
|
|
|
tell a Melkite that fourteen days a year oblige him under a law that was never
|
|
|
|
|
his. When a church's law is added, its entry will say so and its obligations
|
|
|
|
|
will appear. A test holds that line.
|
|
|
|
|
|
|
|
|
|
See [the law and the fast](#the-law-and-the-fast-are-not-the-same-question)
|
|
|
|
|
for what `--typikon` does with this, which is the flag most Byzantine Catholics
|
|
|
|
|
will want.
|
|
|
|
|
|
2026-09-18 13:19:59 -04:00
|
|
|
Ten of the fourteen Byzantine-rite Eastern Catholic churches have no entry of
|
|
|
|
|
their own. Each keeps one of the three reckonings, and
|
2026-09-18 13:40:37 -04:00
|
|
|
[docs/calendars.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/calendars.md) sets out which questions decide it.
|
2026-09-18 13:15:21 -04:00
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## The fast
|
|
|
|
|
|
|
|
|
|
Six levels, ordered from strictest to laxest. They are the Typikon's own
|
|
|
|
|
distinctions, not a simplification of them:
|
|
|
|
|
|
|
|
|
|
| | |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `strict` | no food until evening |
|
|
|
|
|
| `xerophagy` | no oil, no wine; no meat, fish, eggs or dairy |
|
|
|
|
|
| `wine_oil` | wine and oil permitted |
|
|
|
|
|
| `fish` | fish, wine and oil permitted |
|
|
|
|
|
| `dairy` | dairy, eggs and fish permitted; no meat |
|
|
|
|
|
| `none` | no fast |
|
|
|
|
|
|
|
|
|
|
A calendar that reports xerophagy and wine-and-oil both as "fasting" has thrown
|
|
|
|
|
away the information its reader wanted.
|
|
|
|
|
|
|
|
|
|
**Level and obligation are separate questions.** The Orthodox Church legislates
|
|
|
|
|
fasting as tradition rather than as precept, so every Orthodox day here reports
|
|
|
|
|
as customary. The Eastern Catholic churches do have law about it, and it
|
2026-09-18 10:53:03 -04:00
|
|
|
requires very much less than the Typikon describes, so those jurisdictions
|
2026-09-18 09:09:32 -04:00
|
|
|
report both the level at which the day is kept and the minimum that actually
|
|
|
|
|
binds. A calendar saying "obligatory" where nothing obliges is worse than no
|
|
|
|
|
calendar; one reporting only the binding minimum makes the obligatory days look
|
|
|
|
|
laxer than the voluntary ones beside them.
|
|
|
|
|
|
2026-09-18 12:21:06 -04:00
|
|
|
### The law and the fast are not the same question
|
|
|
|
|
|
|
|
|
|
For an Eastern Catholic church the two come apart sharply, and reporting only
|
|
|
|
|
the law makes the Great Fast look like four days of abstinence a year. That is
|
|
|
|
|
what binds; it is not what is kept.
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
What the law requires, which is the first four days of the Great Fast:
|
|
|
|
|
|
2026-09-18 12:21:06 -04:00
|
|
|
```console
|
2026-09-18 12:44:09 -04:00
|
|
|
$ typikon -j ruthenian --no-typikon --days 4 --date 2026-02-16
|
|
|
|
|
|
|
|
|
|
Byzantine Catholic Metropolia of Pittsburgh · Ruthenian particular law
|
|
|
|
|
|
|
|
|
|
🥬 Mon 16 Feb* no meat, fish, eggs or dairy Clean Monday — the first day of the…
|
|
|
|
|
🥬 Tue 17 Feb no meat, fish, eggs or dairy The Holy Great Martyr Theodore the…
|
2026-09-18 14:03:46 -04:00
|
|
|
🥬 Wed 18 Feb* no meat, fish, eggs or dairy Our Holy Father Leo the Great, Pope…
|
|
|
|
|
🥬 Thu 19 Feb no meat, fish, eggs or dairy The Holy Apostles Archippus and…
|
2026-09-18 12:44:09 -04:00
|
|
|
|
|
|
|
|
* obligatory. Everything unmarked is customary and does not bind.
|
2026-09-18 12:21:06 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
And what is kept, with `--typikon`:
|
2026-09-18 12:21:06 -04:00
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
```console
|
|
|
|
|
$ typikon -j ruthenian --typikon --days 4 --date 2026-02-16
|
|
|
|
|
|
|
|
|
|
Byzantine Catholic Metropolia of Pittsburgh · the Typikon, obliging under Ruthenian particular law
|
|
|
|
|
|
|
|
|
|
⛔ Mon 16 Feb* no food until evening Clean Monday — the first day of the…
|
|
|
|
|
🫒 Tue 17 Feb wine and oil permitted The Holy Great Martyr Theodore the…
|
2026-09-18 14:03:46 -04:00
|
|
|
🥬 Wed 18 Feb* xerophagy — no oil or wine Our Holy Father Leo the Great, Pope…
|
|
|
|
|
🥬 Thu 19 Feb xerophagy — no oil or wine The Holy Apostles Archippus and…
|
2026-09-18 12:44:09 -04:00
|
|
|
|
|
|
|
|
* obligatory. Everything unmarked is customary and does not bind.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The same three days are starred in both. That is the point: the flag changes
|
|
|
|
|
what is *kept*, not what *binds*. Tuesday relaxes to wine and oil because St
|
|
|
|
|
Theodore the Recruit is of polyeleos rank, which is the menologion doing its
|
|
|
|
|
work.
|
|
|
|
|
|
|
|
|
|
`--no-typikon` forces the law back, for when the config remembers otherwise.
|
|
|
|
|
Either way it is a no-op for a jurisdiction already reckoning by the Typikon.
|
2026-09-18 12:21:06 -04:00
|
|
|
|
2026-09-18 10:53:03 -04:00
|
|
|
Where usages differ (Great Thursday, the Exaltation, Lazarus Saturday), this
|
2026-09-18 09:09:32 -04:00
|
|
|
follows the common published rule and names it in the day's reason so you can
|
|
|
|
|
disagree with it. Monastic practice, and the Holy Mountain in particular, is
|
|
|
|
|
stricter than all of it. A calendar cannot settle that; your bishop and your
|
|
|
|
|
spiritual father can.
|
|
|
|
|
|
|
|
|
|
## Output
|
|
|
|
|
|
|
|
|
|
```console
|
2026-09-18 11:15:22 -04:00
|
|
|
$ typikon --days 7 # for a person
|
|
|
|
|
$ typikon --format json --days 7 # for a bar, a widget, a script
|
|
|
|
|
$ typikon --format ics --days 365 > orthodox.ics
|
2026-09-18 12:44:09 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-21 09:25:56 -04:00
|
|
|
The calendar is thinned to the days worth marking: a subscription that fills
|
|
|
|
|
all 365 squares is one nobody keeps. `--every-day` is for the other kind of
|
|
|
|
|
reader, who wants the saint of each morning and does not mind a full year.
|
|
|
|
|
Either way the description carries the day's commemorations, the fast and its
|
|
|
|
|
reason, and where the day sits in the year.
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon -j ruthenian --days 467 --ics --every-day > byzantine.ics
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
Delimited output, for a spreadsheet or a pipeline. RFC 4180 quoting, one header
|
|
|
|
|
row, one row per day:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon -j rocor --date 2026-03-16 --days 3 --format csv \
|
|
|
|
|
--fields date,church_date,fast,title
|
|
|
|
|
|
|
|
|
|
date,church_date,fast,title
|
|
|
|
|
2026-03-16,3 March,xerophagy,"The Holy Martyrs Eutropius, Cleonicus and Basiliscus"
|
|
|
|
|
2026-03-17,4 March,xerophagy,Our Venerable Father Gerasimus of the Jordan
|
|
|
|
|
2026-03-18,5 March,xerophagy,The Holy Martyr Conon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
A year's key dates, to check against the one your parish prints:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --year 2027 -j goarch
|
|
|
|
|
|
|
|
|
|
2027 · Greek Orthodox Archdiocese of America
|
|
|
|
|
|
|
|
|
|
publican pharisee 2027-02-21 Sun
|
|
|
|
|
meatfare 2027-03-07 Sun
|
|
|
|
|
cheesefare 2027-03-14 Sun
|
|
|
|
|
clean monday 2027-03-15 Mon
|
|
|
|
|
great fast end 2027-04-23 Fri
|
|
|
|
|
lazarus saturday 2027-04-24 Sat
|
|
|
|
|
palm sunday 2027-04-25 Sun
|
|
|
|
|
great friday 2027-04-30 Fri
|
|
|
|
|
pascha 2027-05-02 Sun
|
|
|
|
|
…
|
2026-09-18 09:09:32 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-21 09:25:56 -04:00
|
|
|
Outside the Triodion and the Pentecostarion, whose Sundays carry names, `week`
|
|
|
|
|
says where the day falls in the count from Pentecost: `the 32nd Sunday after
|
|
|
|
|
Pentecost`, or `the 32nd week after Pentecost` on the days between. It is a
|
|
|
|
|
column in the delimited formats and a line in the single-day view.
|
|
|
|
|
|
2026-09-18 11:28:40 -04:00
|
|
|
Every day of vigil rank or above carries the mark its books print beside it:
|
|
|
|
|
⊕ for a great feast, ✚ for a vigil, ☩ for a polyeleos. It is the `sign`
|
|
|
|
|
field in the JSON and a column in the delimited formats.
|
|
|
|
|
|
2026-09-18 11:15:22 -04:00
|
|
|
`--no-emoji` drops the glyphs from every format, for a terminal or a bar
|
|
|
|
|
without them. `--list-fields` prints the columns `csv` and `tsv` can take, and
|
|
|
|
|
`--fields` picks a subset in the order you name them. `--json` and `--ics`
|
|
|
|
|
still work as shorthand.
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
The JSON shape is flat and stable. Front ends are the thing most likely to be
|
|
|
|
|
written by someone else, and a schema that shifts underneath them is a bad
|
|
|
|
|
neighbour.
|
|
|
|
|
|
2026-09-18 12:44:09 -04:00
|
|
|
```console
|
|
|
|
|
$ typikon -j rocor --date 2026-03-18 --json --indent 2
|
|
|
|
|
{
|
|
|
|
|
"date": "2026-03-18",
|
|
|
|
|
"weekday": "Wednesday",
|
|
|
|
|
"jurisdiction": "rocor",
|
|
|
|
|
"calendar": "old",
|
|
|
|
|
"churchDate": "5 March",
|
|
|
|
|
"season": "Great Fast",
|
|
|
|
|
"cycle": null,
|
2026-09-21 09:25:56 -04:00
|
|
|
"week": null,
|
2026-09-18 12:44:09 -04:00
|
|
|
"feast": null,
|
|
|
|
|
"rank": null,
|
|
|
|
|
"sign": null,
|
|
|
|
|
"tradition": "slavic",
|
|
|
|
|
"title": "The Holy Martyr Conon",
|
|
|
|
|
"commemorations": [
|
|
|
|
|
"The Holy Martyr Conon"
|
|
|
|
|
],
|
|
|
|
|
"fast": "xerophagy",
|
|
|
|
|
"fastLabel": "xerophagy — no oil or wine",
|
|
|
|
|
"emoji": "🥬",
|
|
|
|
|
"reason": "a weekday of the Great Fast",
|
|
|
|
|
"obligation": "customary",
|
2026-09-18 13:46:57 -04:00
|
|
|
"binds": null,
|
2026-09-18 12:44:09 -04:00
|
|
|
"pascha": "2026-04-12",
|
|
|
|
|
"daysToPascha": 25,
|
|
|
|
|
"julianOffset": 13
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
One day is an object; several are `{"days": [...]}`.
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## As a library
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
```rust
|
|
|
|
|
use typikon::calendars::Date;
|
|
|
|
|
use typikon::day::describe;
|
|
|
|
|
use typikon::jurisdictions::resolve;
|
|
|
|
|
|
|
|
|
|
let rocor = resolve(Some("rocor"))?;
|
|
|
|
|
let day = describe(Date::from_ymd(2026, 9, 18).unwrap(), rocor);
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
day.church_date; // "5 September"
|
|
|
|
|
day.fast; // Level::Xerophagy
|
|
|
|
|
day.title(); // "The Holy Prophet Zachariah, father of the Forerunner"
|
|
|
|
|
day.is_obligatory(); // false
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
typikon::paschalion::julian_pascha(2027); // 2027-05-02
|
|
|
|
|
typikon::paschalion::gregorian_pascha(2027); // 2027-03-28
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The levels are an ordered enum, strictest first, so `a < b` reads as "a is
|
|
|
|
|
stricter than b" and a feast can only ever relax a fast:
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
```rust
|
|
|
|
|
Level::Xerophagy.relaxed_to(Level::Fish, Level::WineOil) // WineOil: no saint
|
|
|
|
|
// brings fish into Lent
|
|
|
|
|
Level::Fish.relaxed_to(Level::WineOil, Level::WineOil) // Fish: never tightens
|
2026-09-18 09:09:32 -04:00
|
|
|
```
|
|
|
|
|
|
2026-09-18 11:27:51 -04:00
|
|
|
## From Python
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
import datetime, typikon
|
|
|
|
|
|
|
|
|
|
day = typikon.describe(datetime.date(2026, 9, 18))
|
|
|
|
|
|
|
|
|
|
day.church_date # '5 September'
|
|
|
|
|
day.fast # 'xerophagy'
|
|
|
|
|
day.title # 'The Holy Prophet Zachariah, father of the Forerunner'
|
|
|
|
|
day.is_obligatory() # False
|
|
|
|
|
|
|
|
|
|
typikon.today()
|
|
|
|
|
typikon.pascha(2027) # datetime.date(2027, 5, 2)
|
|
|
|
|
typikon.week(datetime.date(2026, 4, 12), 7) # seven consecutive days
|
|
|
|
|
typikon.describe(d, jurisdiction='rocor')
|
|
|
|
|
[j['key'] for j in typikon.jurisdictions()]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Dates in and out are `datetime.date`. `to_dict()` gives exactly the fields
|
|
|
|
|
`--json` gives, so anything already reading the CLI's output can read a `Day`
|
|
|
|
|
without changing shape — there is a test that holds the two to that.
|
|
|
|
|
|
|
|
|
|
Given no `jurisdiction=`, the library reads the same configured default the
|
|
|
|
|
command line does. Calling the engine's own resolver instead would have quietly
|
|
|
|
|
answered for a different church than `typikon --set-default` selected, which is
|
|
|
|
|
the kind of disagreement nobody notices until a fast day is wrong.
|
|
|
|
|
|
|
|
|
|
The wheel is abi3, so one build serves every Python from 3.9 up. It ships
|
|
|
|
|
`py.typed` and a stub file, and `mypy --strict` is clean against it.
|
|
|
|
|
|
2026-09-18 14:46:25 -04:00
|
|
|
## From C, and anything with an FFI
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cargo build --release --features capi # target/release/libtypikon.so
|
|
|
|
|
cc -Iinclude yours.c -ltypikon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
#include <typikon.h>
|
|
|
|
|
|
|
|
|
|
typikon_day *d = typikon_describe(typikon_today(), "rocor");
|
|
|
|
|
if (!d) { fputs(typikon_last_error(), stderr); return 1; }
|
|
|
|
|
|
|
|
|
|
typikon_day_church_date(d); /* "5 September" */
|
|
|
|
|
typikon_day_fast(d); /* "xerophagy" */
|
|
|
|
|
typikon_day_emoji(d); /* the glyph for the level */
|
|
|
|
|
typikon_day_title(d); /* the feast, else the principal commemoration */
|
|
|
|
|
typikon_day_is_obligatory(d); /* 0 */
|
|
|
|
|
|
|
|
|
|
typikon_day_free(d);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Dates cross the boundary as **Julian Day Numbers**, so no struct layout is part
|
|
|
|
|
of the ABI and there is nothing for a caller to keep in step;
|
|
|
|
|
`typikon_jdn_from_ymd` converts. A day is opaque and owns its strings: an
|
|
|
|
|
accessor returns the same borrowed pointer every time, so reading one in a
|
|
|
|
|
render loop allocates nothing, and nothing it returns should be freed. NULL
|
|
|
|
|
from an accessor means the day has no such field, which is not an error. A call
|
|
|
|
|
that can fail returns NULL or 0 and leaves a message in `typikon_last_error()`.
|
|
|
|
|
|
|
|
|
|
[`include/typikon.h`](https://git.pumpin.online/funkpower/typikon/src/branch/main/include/typikon.h)
|
|
|
|
|
is the whole surface: it carries every field of the JSON, so a statusline does
|
|
|
|
|
not need a parser. [`examples/c/demo.c`](https://git.pumpin.online/funkpower/typikon/src/branch/main/examples/c/demo.c)
|
|
|
|
|
is a working one.
|
|
|
|
|
|
|
|
|
|
### From Lua
|
|
|
|
|
|
|
|
|
|
[`examples/lua/typikon.lua`](https://git.pumpin.online/funkpower/typikon/src/branch/main/examples/lua/typikon.lua)
|
|
|
|
|
is a LuaJIT FFI binding, for AwesomeWM, WezTerm, Neovim and anything else that
|
|
|
|
|
embeds LuaJIT and should not be spawning a process on every redraw.
|
|
|
|
|
|
|
|
|
|
```lua
|
|
|
|
|
local typikon = require("typikon")
|
|
|
|
|
|
|
|
|
|
local day = assert(typikon.today({ jurisdiction = "rocor" }))
|
|
|
|
|
day.church_date -- "5 September"
|
|
|
|
|
day.fast -- "xerophagy"
|
|
|
|
|
day.title -- "The Holy Prophet Zachariah, father of the Forerunner"
|
|
|
|
|
day.commemorations
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-18 14:55:31 -04:00
|
|
|
## From JavaScript and TypeScript
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
npm install typikon
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
import { today } from "typikon";
|
|
|
|
|
|
|
|
|
|
const day = today({ jurisdiction: "rocor" });
|
|
|
|
|
|
|
|
|
|
day.churchDate; // "5 September"
|
|
|
|
|
day.fast; // "xerophagy"
|
|
|
|
|
day.emoji; // the glyph for the level
|
|
|
|
|
day.title; // "The Holy Prophet Zachariah, father of the Forerunner"
|
|
|
|
|
day.season; // null in ordinary time
|
|
|
|
|
day.daysToPascha;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
import { describe, describeIso, week, pascha, jurisdictions } from "typikon";
|
|
|
|
|
|
|
|
|
|
describeIso("2026-04-12", { jurisdiction: "moscow" });
|
|
|
|
|
describe(new Date(), { jurisdiction: "goarch", tradition: "greek" });
|
|
|
|
|
week(new Date(), 7, { jurisdiction: "oca" }); // seven consecutive days
|
|
|
|
|
pascha(2027, "old"); // 2027-05-02
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
It is WebAssembly, so it is one package for Node, Deno, Bun, a browser and
|
|
|
|
|
anything built on them, with no native build to go wrong. Node loads it itself;
|
|
|
|
|
in a browser or a bundler, `await init()` first. A day comes back as a plain
|
|
|
|
|
object, not a handle: the same document `--json` emits, with nothing to free
|
|
|
|
|
and `JSON.stringify` working on it. TypeScript types ship with the package and
|
|
|
|
|
`tsc --strict` is clean against them.
|
|
|
|
|
|
|
|
|
|
There is no remembered default here, because a browser has nowhere to keep one:
|
|
|
|
|
the default is the New Calendar, and anything else is passed. That is the only
|
|
|
|
|
place this binding differs from the others.
|
|
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## The menologion
|
|
|
|
|
|
|
|
|
|
The fixed calendar ships as data and is indexed by **ecclesiastical** date, so
|
|
|
|
|
one file serves every jurisdiction. An old-calendar church and a new-calendar
|
|
|
|
|
church both keep the Nativity on 25 December; they disagree about which morning
|
|
|
|
|
that is, and that disagreement lives in the calendar conversion, not in the
|
|
|
|
|
data.
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
`data/menologion.json`, compiled into the binary, covers all 366 days with the principal
|
2026-09-18 09:09:32 -04:00
|
|
|
commemorations of the common Byzantine tradition, ranked so the fasting rules
|
|
|
|
|
know when a feast lifts a Wednesday. It was composed for this project and is
|
|
|
|
|
under the same licence as the code. It is a working set, not a complete
|
|
|
|
|
Synaxarion; additions are welcome.
|
|
|
|
|
|
|
|
|
|
Some churches also keep their own saints, and those lists are usually published
|
|
|
|
|
by a body that holds the copyright in the wording. Those are **not** shipped.
|
|
|
|
|
Fetch one onto your own machine instead:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ typikon --list-menaia
|
|
|
|
|
$ typikon --update-menaion ruthenian
|
|
|
|
|
```
|
|
|
|
|
|
2026-09-18 11:13:10 -04:00
|
|
|
It lands in `~/.local/share/typikon/` and is overlaid automatically.
|
2026-09-18 09:09:32 -04:00
|
|
|
|
2026-09-18 13:19:59 -04:00
|
|
|
## Further reading
|
|
|
|
|
|
2026-09-18 13:40:37 -04:00
|
|
|
- [docs/calendars.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/calendars.md) sets out which churches keep which
|
2026-09-18 13:23:54 -04:00
|
|
|
reckoning, how the split came about, what is modelled here and what is not.
|
2026-09-18 13:40:37 -04:00
|
|
|
- [docs/versioning.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/versioning.md) says what counts as the public
|
2026-09-18 13:23:54 -04:00
|
|
|
surface, and how a correction to the calendar itself is announced.
|
2026-09-18 13:40:37 -04:00
|
|
|
- [CHANGELOG.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/CHANGELOG.md) carries those announcements.
|
2026-09-18 13:19:59 -04:00
|
|
|
|
2026-09-18 09:09:32 -04:00
|
|
|
## Accuracy
|
|
|
|
|
|
2026-09-18 13:40:37 -04:00
|
|
|
`typikon` is pinned against published calendars: the paschalion for eleven
|
|
|
|
|
named years and its invariants across the two centuries from 1900, 146,000
|
|
|
|
|
calendar round-trips from 1800 to 2200, the fast on every day that is not open
|
|
|
|
|
to interpretation, and every jurisdiction over the twenty-one years from 2020.
|
2026-09-18 13:46:57 -04:00
|
|
|
Every title the program can print is cut at every width it can be asked to
|
|
|
|
|
print at, because that is where it once crashed.
|
2026-09-18 09:09:32 -04:00
|
|
|
|
|
|
|
|
It is a calendar, not an authority. If it disagrees with the one your parish
|
|
|
|
|
prints, your parish is right. Please open an issue.
|
|
|
|
|
|
|
|
|
|
## Front ends
|
|
|
|
|
|
2026-09-18 10:53:03 -04:00
|
|
|
[`menologion`](https://git.pumpin.online/funkpower/menologion): desktop
|
2026-09-18 09:52:31 -04:00
|
|
|
widgets for Hyprland (Quickshell), waybar and eww, all reading the JSON above.
|
|
|
|
|
|
2026-09-18 10:53:03 -04:00
|
|
|

|
2026-09-18 09:09:32 -04:00
|
|
|
|
|
|
|
|
## Licence
|
|
|
|
|
|
2026-09-18 13:40:37 -04:00
|
|
|
GPL-2.0-only. The source for any published release is the source distribution
|
|
|
|
|
beside it on PyPI, and `Cargo.lock` pins every dependency to an exact version.
|
|
|
|
|
See [LICENSE](https://git.pumpin.online/funkpower/typikon/src/branch/main/LICENSE). The menologion is under it too;
|
2026-09-18 11:13:10 -04:00
|
|
|
`data/LICENSE` says so and notes what the fetched sets are not.
|