Metric Calendar date conversion — a rational decimal calendar system
Project description
metric_calendar
A Python library for the Metric Calendar — a rational decimal calendar system built on the March equinox.
The Metric Calendar divides the solar year into 12 months of exactly 30 days each, organised into 10-day weeks. The year begins at the vernal equinox (March 20) with three intercalary Turning days, and includes two or three Yule days at midsummer to keep the calendar aligned with the solar year. Every date is fully deterministic from standard Gregorian input.
Installation
pip install metric_calendar
Requires Python 3.8 or later. No external dependencies.
Quick Start
import datetime
from metric_calendar import today, gregorian_to_metric, metric_to_gregorian
# Get today's Metric date
md = today()
print(md.month_name, md.day, md.year) # e.g. "Unil 1 56"
# Convert a specific Gregorian date
md = gregorian_to_metric(datetime.date(2026, 3, 23))
print(md)
# MetricDate(year=56, month=1, month_name='Unil', day=1, week_day=1,
# day_name='Primday', week=1, season_index=0, ...)
# Convert back to Gregorian
d = metric_to_gregorian(56, 'month', 1, 1)
print(d) # 2026-03-23
Calendar Structure
The Metric Calendar year starts at the March equinox (March 20) and is structured as follows:
| Period | Days | Notes |
|---|---|---|
| The Turning | 3 | Vigil, Balance, Dawn — year-opening intercalary days |
| Months 1–9 (Unil–Novil) | 270 | 9 months × 30 days |
| Yule | 2–3 | Yule Eve, Midwinter, and Kindling (leap years only) |
| Months 10–12 (Decil–Duodecil) | 90 | 3 months × 30 days |
Each month contains three 10-day weeks. Days 8, 9, and 10 of each week (Octday, Novday, Decday) are rest days.
Metric year epoch: Year 0 = 1970 CE. Year 56 spans March 2026 – March 2027.
Month Names
| # | Name | # | Name |
|---|---|---|---|
| 1 | Unil | 7 | Septil |
| 2 | Duil | 8 | Octil |
| 3 | Tril | 9 | Novil |
| 4 | Quadril | 10 | Decil |
| 5 | Quintil | 11 | Undecil |
| 6 | Sextil | 12 | Duodecil |
Day Names
| # | Name | Rest? |
|---|---|---|
| 1 | Primday | |
| 2 | Duoday | |
| 3 | Triday | |
| 4 | Quadday | |
| 5 | Quintday | |
| 6 | Hexday | |
| 7 | Septday | |
| 8 | Octday | rest |
| 9 | Novday | rest |
| 10 | Decday | rest |
Special Days
| Name | Description |
|---|---|
| Vigil | First Turning day (March 20) |
| Balance | Second Turning day (March 21) |
| Dawn | Third Turning day (March 22) |
| Yule Eve | First Yule day |
| Midwinter | Second Yule day |
| Kindling | Third Yule day (leap years only) |
| Midsummer | Quadril 1 — first day of the fourth month |
| Spiral | Quintil 18 — golden-ratio day of the year |
API Reference
gregorian_to_metric(date: datetime.date) -> MetricDate
Convert a Gregorian datetime.date to a MetricDate.
import datetime
from metric_calendar import gregorian_to_metric
md = gregorian_to_metric(datetime.date(2026, 6, 21))
print(md.is_midsummer) # True
print(md.month_name) # 'Quadril'
print(md.day) # 1
metric_to_gregorian(year, period_type, period_value, day_of_month=1) -> datetime.date
Convert a Metric Calendar date back to a Gregorian datetime.date.
Parameters:
year— Metric year (0 = 1970 CE)period_type— one of'turning','month', or'yule'period_value:'turning':0(Vigil),1(Balance),2(Dawn)'month': month number1–12'yule':0(Yule Eve),1(Midwinter),2(Kindling, leap years only)
day_of_month— day within the month,1–30(only used whenperiod_type='month')
from metric_calendar import metric_to_gregorian
# Unil 1, Year 56
metric_to_gregorian(56, 'month', 1, 1) # datetime.date(2026, 3, 23)
# The Turning — Vigil, Year 56
metric_to_gregorian(56, 'turning', 0) # datetime.date(2026, 3, 20)
# Yule Eve, Year 56
metric_to_gregorian(56, 'yule', 0) # datetime.date(2026, 12, 18)
is_rest_day(date: datetime.date) -> bool
Return True if the given Gregorian date falls on a Metric rest day (Octday, Novday, or Decday).
from metric_calendar import is_rest_day
import datetime
is_rest_day(datetime.date(2026, 4, 1)) # True — Decday
is_rest_day(datetime.date(2026, 3, 23)) # False — Primday
today() -> MetricDate
Return today's date as a MetricDate.
from metric_calendar import today
md = today()
print(f"{md.day_name}, {md.month_name} {md.day}, Year {md.year}")
MetricDate
An immutable dataclass with the following fields:
| Field | Type | Description |
|---|---|---|
year |
int |
Metric year (epoch 1970) |
month |
int |
Month number 1–12; 0 for Turning/Yule days |
month_name |
str |
e.g. 'Unil'; empty for Turning/Yule days |
day |
int |
Day of month 1–30; 0 for Turning/Yule days |
week_day |
int |
Day of week 1–10; 0 for Turning/Yule days |
day_name |
str |
e.g. 'Primday'; empty for Turning/Yule days |
week |
int |
Week of year 1–36; 0 for Turning/Yule days |
season_index |
int |
Season 0–3 (Spring/Summer/Autumn/Winter); -1 for Turning/Yule days |
is_leap_year |
bool |
Whether this Metric year has a Kindling day |
is_turning |
bool |
True for Vigil, Balance, or Dawn |
is_yule |
bool |
True for Yule Eve, Midwinter, or Kindling |
is_midsummer |
bool |
True on Quadril 1 |
is_spiral |
bool |
True on Quintil 18 (golden-ratio day) |
is_rest |
bool |
True when week_day >= 8 |
special_day |
str |
Name of the special day, or empty string |
Running the Tests
python -m pytest tests/
# or
python -m unittest discover tests/
License
MIT. See metricweek.com for the full calendar specification.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file metric_calendar-1.0.0.tar.gz.
File metadata
- Download URL: metric_calendar-1.0.0.tar.gz
- Upload date:
- Size: 5.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7622ff37ee068e99f4f9a87d6e2d08c567cf370f797c31e812d70b8c31b1125
|
|
| MD5 |
157e55010987cab59a7c4e6ca1d87531
|
|
| BLAKE2b-256 |
002689dc062c22bef990774b3935b3279c16e52c1b69dc554c79ef1f55cd7907
|
Provenance
The following attestation bundles were made for metric_calendar-1.0.0.tar.gz:
Publisher:
publish-python.yml on alexrabarts/metric-calendar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metric_calendar-1.0.0.tar.gz -
Subject digest:
e7622ff37ee068e99f4f9a87d6e2d08c567cf370f797c31e812d70b8c31b1125 - Sigstore transparency entry: 1110562774
- Sigstore integration time:
-
Permalink:
alexrabarts/metric-calendar@7a8f1971d5b41080087b3c3eb032df87c18091c8 -
Branch / Tag:
refs/tags/libs/python/v1.0.0 - Owner: https://github.com/alexrabarts
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@7a8f1971d5b41080087b3c3eb032df87c18091c8 -
Trigger Event:
push
-
Statement type:
File details
Details for the file metric_calendar-1.0.0-py3-none-any.whl.
File metadata
- Download URL: metric_calendar-1.0.0-py3-none-any.whl
- Upload date:
- Size: 5.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
666e8001c6fb0bc6e50dc2bbddc97c4c6805fe831427047ad544d587717d0d1e
|
|
| MD5 |
cd56528656feba0d6aa397149cdfe755
|
|
| BLAKE2b-256 |
3d9d17353cf6d9d8a22b89d3b1d72b08741f106b452db45775e053cdd8d2d1ed
|
Provenance
The following attestation bundles were made for metric_calendar-1.0.0-py3-none-any.whl:
Publisher:
publish-python.yml on alexrabarts/metric-calendar
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
metric_calendar-1.0.0-py3-none-any.whl -
Subject digest:
666e8001c6fb0bc6e50dc2bbddc97c4c6805fe831427047ad544d587717d0d1e - Sigstore transparency entry: 1110562829
- Sigstore integration time:
-
Permalink:
alexrabarts/metric-calendar@7a8f1971d5b41080087b3c3eb032df87c18091c8 -
Branch / Tag:
refs/tags/libs/python/v1.0.0 - Owner: https://github.com/alexrabarts
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@7a8f1971d5b41080087b3c3eb032df87c18091c8 -
Trigger Event:
push
-
Statement type: