目标:构建一个语言无关、数据优先、可社区穷尽扩展的全球历法与纪年知识库 + 计算框架,系统收录全世界文献中出现的历法与纪年体系,并妥善处理无法(或不适合)完全映射到儒略日(JD)的情况。采用 MIT 协议。
1. 项目愿景与成功标准
- 愿景:成为历史学家、程序员、语言学家、业余年代学爱好者共同维护的“全球时间本体”权威开放数据仓库。
- 核心目标:
- 穷尽(持续追求)文献中的历法与纪年。
- 支持绝对时间(JD/RD)与非绝对时间(相对、循环、文学、不确定区间)。
- 最大程度降低特定编程语言依赖。
- 高可维护性与可验证性。
- 成功标准(5 年内):
- 覆盖主流 + 大量冷门历法/年号(目标 200+ 体系)。
- 所有数据有文献来源与置信度。
- 任何语言都能直接消费核心数据。
- 活跃贡献者社区。
2. 核心设计原则
- 数据优先(Data-first):90% 以上内容是结构化数据,计算逻辑最小化并插件化。
- 语言无关(Language-agnostic):核心资产 = JSON/YAML + JSON Schema + Markdown。计算层可选(参考实现 + WASM)。
- 可列举 vs 不可列举:
- 可列举(年号、切换点、对照表、固定节日)→ 纯 JSON 数据。
- 不可列举(算术/天文规则)→ 计算插件或声明式规则。
- 非强制 JD:允许
jd_mappable: false/partial,支持本地时间线。 - 文献可追溯:每个条目必须附带来源、适用时间、已知局限、置信度。
- Schema 强制:所有数据必须通过 JSON Schema 验证。
- 渐进穷尽:先做高质量骨架,再社区补充。
3. 整体架构
用户 / 工具 ↓查询 / 转换 API(可选,多语言绑定) ↓┌─────────────────────────────────────┐│ 计算插件层(可选) ││ - 算术历法插件 ││ - 天文计算插件 ││ - WASM 通用实现 │└─────────────────────────────────────┘ ↓统一中间表示(TemporalID) - 优先 JD / Rata Die - 支持 local-timeline-id / interval / relative ↓┌─────────────────────────────────────┐│ 数据层(核心,语言无关) ││ - calendars/ ││ - eras/ ││ - chronologies/ ││ - transitions/ ││ - non-jd/ ││ - sources/ │└─────────────────────────────────────┘
TemporalID 是关键抽象:可以是精确 JD、JD 区间、相对表达式或纯本地标识。
4. 数据模型设计(JSON Schema 为核心)
主要 Schema(放在 schemas/):
calendar.schema.json:历法定义(类型、组件、算法引用、数据文件、范围、局限)。era.schema.json:纪年/年号(支持嵌套、重叠、废立、起止对应)。chronology.schema.json:完整时间线或对照表。transition.schema.json:历法切换点(按地区/政权)。temporal-expression.schema.json:时间表达(绝对/相对/区间/循环/文学)。source.schema.json:文献元数据(书名、作者、页码、DOI、置信度)。conversion-rule.schema.json:声明式转换规则(进一步减少代码)。
示例关键字段(历法):
json
{ "id": "chinese-qing-official", "names": {"en": "...", "zh": "清代官方历"}, "type": ["lunisolar", "historical", "hybrid"], "jd_mappable": "partial", "range": {"from": "1644-01-01", "to": "1911-12-31", "certainty": "high"}, "algorithm": "plugin:chinese-astronomical@1.2" 或 "tabular", "data_refs": ["data/calendars/chinese-qing/months.json"], "sources": ["src:xxx"], "limitations": ["部分年份与现代推算有 ±1 日差异"], "tags": ["east-asia", "imperial"]}
非 JD 体系单独放在 data/non-jd/,明确标记 expression_type 和对应关系说明。
5. 计算与插件系统
- 统一接口(用 OpenAPI 或简单 JSON 描述,语言无关):
to_temporal(date, calendar_id) → TemporalIDfrom_temporal(id, target_calendar) → datevalidate(date, calendar_id)list_components(calendar_id)
- 实现策略:
- 参考实现:Python(易读 + 科学计算)或 TypeScript。
- 通用运行时:编译为 WebAssembly,实现真正跨语言。
- 简单规则:支持纯 JSON 声明式规则(例如固定置闰周期),无需代码。
- 插件注册:通过
plugins/manifest.json声明支持的历法与版本。
6. 仓库结构
text
omnichronos/├── LICENSE # MIT├── README.md├── CONTRIBUTING.md├── CODE_OF_CONDUCT.md├── schemas/ # JSON Schema(强制)├── data/│ ├── calendars/│ ├── eras/│ ├── chronologies/│ ├── transitions/│ ├── non-jd/│ └── sources/├── rules/ # 声明式规则(可选)├── plugins/│ ├── reference/ # 参考实现│ ├── wasm/│ └── bindings/ # 其他语言示例├── tools/ # 验证、生成、测试脚本├── docs/│ ├── design.md│ ├── ontology.md│ ├── handling-non-jd.md│ └── how-to-add-calendar.md├── tests/│ ├── schema/│ ├── fixtures/ # 黄金测试用例│ └── crosschecks/└── .github/workflows/ # CI:Schema 校验 + 测试
7. 贡献与质量控制流程
- 新增/修改必须通过对应 Schema 验证。
- 必须提供至少 2 个独立文献来源。
- 必须附带测试用例(fixtures)。
- 非 JD 条目必须详细说明对应关系与局限。
- CI 自动运行 Schema 校验 + 转换一致性测试。
- 人工审核(初期由维护者,后期可引入领域专家标签)。
- 数据与 Schema 独立语义化版本(例如 data v1.2.0 + schema v0.9.0)。
8. 技术选型(最大化通用性)
- 数据格式:JSON(主)+ YAML(人类友好)+ Markdown(文档)。
- 验证:JSON Schema Draft 2020-12。
- 工具链:任意语言(推荐 Python/Node 写验证脚本),但运行时零依赖。
- 计算:参考实现可选;优先提供 WASM。
- 发布:数据可独立打包(npm、PyPI、crates、纯 git 子模块)。
- 查询界面(后期):静态站点或简单 API,非核心。
9. 处理非 JD 情况的专门设计
- 分类:relative、cyclical、interval、literary/mythical、observational-historical、fragmentary。
- 每个条目声明
jd_mappable和correspondence(可能的 JD 范围 + 置信度 + 假说)。 - 支持“本地时间线 ID”,允许纯内部推演而不强制外部锚点。
- 文档强制要求写清“为什么不能完全映射”以及已知外部对照点。
10. 版本、治理与社区
- 协议:MIT(数据与代码均适用)。
- 治理:初期单维护者 + 明确贡献指南;后期可成立小型核心团队 + 领域专家顾问。
- 版本策略:数据与 Schema 分开版本;破坏性变更需 major。
- 社区:GitHub Discussions + 定期数据质量报告;鼓励历史学者直接贡献 JSON。
11. 启动路线图(建议)
Phase 0(1–2 周)
确定最终名称、创建仓库、写完核心 Schema 与设计文档。
Phase 1(1–2 月)
实现 5–8 个代表性例子(格里高利、中国年号、伊斯兰表格历、一个非 JD 神话体系、一个历史切换点、希伯来、玛雅),搭建完整 CI。
Phase 2
完善文档与贡献模板,公开 v0.1,开始接受外部贡献。
Phase 3+
持续扩充数据、增加 WASM、多语言绑定、简单查询界面、与现有工具(HistoryCal、pycalcal 等)互操作。
12. 名称候选
- OmniChronos
- ChronoLexicon
- UniversalChronology
- Calendria
- TemporalAtlas
- WorldEra
这个设计把“穷尽文献 + 非 JD 支持 + 语言无关 + 高可维护”落到了可执行的架构上。它填补了当前空白,同时保持足够弹性,让历史学家和程序员都能参与。
附:OpenChronology 项目的 README.md 和 CONTRIBUTING.md 初稿
README.md 初稿
markdown
# OpenChronology
**A language-agnostic, data-first open knowledge base for the world’s calendars and chronologies.**
OmniChronos aims to systematically collect, structure, and make interoperable every calendar system and era-dating scheme attested in historical and contemporary literature — including those that cannot be fully mapped to the Julian Day Number (JD).
[](https://opensource.org/licenses/MIT)[](https://github.com/your-org/omnichronos/actions)
## Why OpenChronology?
Existing calendar libraries focus on algorithmic conversion of a limited set of well-known systems (usually 10–40 calendars) and almost always force everything through Julian Day / Rata Die.
No current open project systematically:
- Targets **exhaustive** coverage of calendars and era systems found in world literature- Properly handles **non-JD-mappable** cases (relative dating, cyclical systems, literary/mythical timelines, fragmentary records, pure observational calendars)- Keeps the core as pure, language-agnostic structured data- Makes it easy for historians and domain experts (not just programmers) to contribute
OmniChronos fills this gap.
## Key Features
- **Data-first architecture**: Most content lives in validated JSON/YAML files- **Language-agnostic**: Core data can be consumed by any programming language- **Full support for non-absolute time**: relative, cyclical, interval, literary, and uncertain expressions- **Strict provenance**: Every entry requires bibliographic sources and confidence information- **Plugin system** for algorithmic calendars (with reference implementations and WebAssembly targets)- **MIT licensed**
## Project Structure
omnichronos/ ├── schemas/ # JSON Schema definitions (the contract) ├── data/ │ ├── calendars/ # Calendar definitions │ ├── eras/ # Era / regnal / year-numbering systems │ ├── chronologies/ # Full timelines and conversion tables │ ├── transitions/ # Calendar change points by region │ ├── non-jd/ # Systems that cannot fully map to JD │ └── sources/ # Bibliographic records ├── plugins/ # Calculation plugins (optional) ├── tools/ # Validation and utility scripts └── docs/ # Design documents and guides
## Quick Start
### 1. Use the data directly
All data files are plain JSON and validated against the schemas in `/schemas`. You can load them with any language that supports JSON.
### 2. Validate locally
```bash# Example with ajv (Node.js)npm install -g ajv-cliajv validate -s schemas/calendar.schema.json -d data/calendars/**/*.json
3. Reference implementation (optional)
See /plugins/reference for a Python (or TypeScript) reference implementation of the conversion interface.
Status
Early design / v0.1 preparation
We currently provide:
- Complete JSON Schema drafts
- Core architecture documentation
- Contribution guidelines
The first concrete data sets and reference plugins will be added in the coming weeks.
Contributing
We warmly welcome contributions from historians, philologists, astronomers, and developers.
Please read CONTRIBUTING.md [blocked] before submitting data or code.
The most valuable contributions right now are:
- High-quality calendar / era definitions with solid sources
- Tabular data for historical systems
- Careful documentation of non-JD cases
License
This project is licensed under the MIT License.
See LICENSE [blocked] for details.
Data and schemas are also released under MIT so they can be freely reused in any context.
Acknowledgments
This project stands on the shoulders of many earlier efforts, especially:
- Calendrical Calculations by Dershowitz & Reingold
- HistoryCal
- Various East Asian calendar authority databases
- The broader open chronological and calendrical community
Maintainer note: This is an ambitious long-term project. Progress will be steady rather than explosive. Quality and provenance are valued over speed of coverage.
---
### CONTRIBUTING.md 初稿
```markdown# Contributing to OpenChronology
Thank you for your interest in contributing!
OmniChronos is a **data-first** project. The most valuable contributions are carefully researched calendar and era definitions with proper sources. Code contributions (plugins, tools, bindings) are also welcome.
## Ways to Contribute
1. **Add or improve calendar / era / chronology data** (highest priority)2. **Improve or extend JSON Schemas**3. **Write or improve calculation plugins**4. **Improve documentation**5. **Report issues or suggest missing systems**6. **Help with validation tooling and CI**
## Before You Start
1. Read the design documents in `/docs`2. Familiarize yourself with the schemas in `/schemas`3. Search existing issues and pull requests to avoid duplication
## Adding a New Calendar or Era
### Required steps
1. Create a new JSON file following the appropriate schema (`calendar.schema.json` or `era.schema.json`).2. Provide **at least two independent scholarly sources**.3. Clearly state the `jd_mappable` status (`true` / `false` / `partial`).4. Document limitations and known discrepancies.5. Add corresponding entries to `/data/sources/` if the sources are new.6. Include at least a few test fixtures if conversion is possible.
### File naming
- Use lowercase kebab-case: `chinese-qing-official.json`- Place files in the correct subdirectory under `/data`
### Validation
All submissions must pass schema validation. You can validate locally with any JSON Schema validator (ajv, check-jsonschema, etc.).
Example:
```bashajv validate -s schemas/calendar.schema.json -d data/calendars/my-new-calendar.json
Handling Non-JD Cases
If a system cannot be reliably mapped to Julian Day:
- Set
"jd_mappable": "false"or"partial" - Use the
temporal-expressionstructure carefully - Explain in the
notesandlimitationsfields why full mapping is impossible or problematic - Record any known external anchor points and their confidence
We explicitly welcome literary, mythical, cyclical, and fragmentary systems.
Code Contributions (Plugins & Tools)
- Prefer clear, well-documented code
- Reference implementations should stay readable (Python or TypeScript preferred)
- WebAssembly builds are highly encouraged for language independence
- Follow the plugin interface defined in
/docs/plugin-interface.md(to be finalized)
Pull Request Process
- Fork the repository
- Create a feature branch
- Make your changes
- Ensure all schemas validate and tests pass
- Open a Pull Request with a clear description
- Link related issues if applicable
Maintainers will review for:
- Schema compliance
- Source quality
- Clarity of limitations
- Consistency with existing data
Code of Conduct
This project follows a standard inclusive Code of Conduct (see CODE_OF_CONDUCT.md).
Be respectful, especially when discussing historical or cultural interpretations.
Questions?
Open a GitHub Discussion or an Issue with the question label.
Thank you for helping build a more complete and honest map of human timekeeping!
附:OmniChronos 项目的完整 JSON Schema 草案(基于 JSON Schema Draft 2020-12)
这些 Schema 设计遵循数据优先、语言无关、支持非 JD 映射、强制文献可追溯的原则。所有 Schema 都放在 schemas/ 目录下使用。
1. source.schema.json(文献来源)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/source.schema.json", "title": "Source", "description": "Bibliographic or digital source reference for calendars, eras, and chronologies.", "type": "object", "required": ["id", "title", "type"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^src:[a-z0-9][a-z0-9_-]*$", "description": "Unique source identifier, e.g. src:reingold-dershowitz-2018" }, "title": { "type": "string" }, "type": { "type": "string", "enum": ["book", "article", "database", "website", "manuscript", "inscription", "official", "other"] }, "authors": { "type": "array", "items": { "type": "string" } }, "year": { "type": "integer" }, "publisher": { "type": "string" }, "isbn": { "type": "string" }, "doi": { "type": "string" }, "url": { "type": "string", "format": "uri" }, "pages": { "type": "string" }, "language": { "type": "string", "description": "ISO 639-1 or 639-3 code" }, "notes": { "type": "string" }, "accessed": { "type": "string", "format": "date" } }}
2. temporal-expression.schema.json(时间表达,核心支持非 JD)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/temporal-expression.schema.json", "title": "Temporal Expression", "description": "Flexible representation of a point, interval, or relative time, including non-JD-mappable cases.", "type": "object", "required": ["expression_type"], "additionalProperties": false, "properties": { "expression_type": { "type": "string", "enum": [ "absolute", "relative", "interval", "cyclical", "literary", "observational", "fragmentary", "uncertain" ] }, "calendar_ref": { "type": "string", "description": "Reference to a calendar or era id" }, "value": { "description": "The actual temporal value. Structure depends on expression_type and calendar.", "oneOf": [ { "type": "object" }, { "type": "string" }, { "type": "number" }, { "type": "array" } ] }, "jd": { "type": "number", "description": "Exact Julian Day Number if fully mappable" }, "jd_range": { "type": "object", "properties": { "min": { "type": "number" }, "max": { "type": "number" } }, "required": ["min", "max"] }, "confidence": { "type": "number", "minimum": 0, "maximum": 1, "description": "0.0–1.0 confidence in the correspondence" }, "jd_mappable": { "type": "string", "enum": ["true", "false", "partial"] }, "notes": { "type": "string" }, "sources": { "type": "array", "items": { "type": "string", "pattern": "^src:" } }, "hypotheses": { "type": "array", "items": { "type": "string" }, "description": "Alternative interpretations when uncertain" } }}
3. calendar.schema.json(历法定义)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/calendar.schema.json", "title": "Calendar", "description": "Definition of a calendar system.", "type": "object", "required": ["id", "names", "type", "jd_mappable"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$", "description": "Unique calendar identifier, e.g. chinese-qing-official" }, "names": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Multilingual names. Keys are language codes (en, zh, ja, etc.)", "minProperties": 1 }, "type": { "type": "array", "items": { "type": "string", "enum": [ "solar", "lunar", "lunisolar", "arithmetic", "astronomical", "observational", "tabular", "hybrid", "historical", "proposed", "literary", "cyclical", "other" ] }, "minItems": 1, "uniqueItems": true }, "jd_mappable": { "type": "string", "enum": ["true", "false", "partial"] }, "range": { "type": "object", "properties": { "from": { "$ref": "temporal-expression.schema.json" }, "to": { "$ref": "temporal-expression.schema.json" }, "certainty": { "type": "string", "enum": ["high", "medium", "low", "unknown"] } } }, "components": { "type": "array", "items": { "type": "string" }, "description": "e.g. year, month, leap-month, day, ganzhi, weekday" }, "epoch": { "$ref": "temporal-expression.schema.json" }, "algorithm": { "type": "string", "description": "Plugin reference, e.g. plugin:gregorian@1.0 or 'tabular' or 'declarative'" }, "data_refs": { "type": "array", "items": { "type": "string" }, "description": "Paths to tabular data files" }, "rules_ref": { "type": "string", "description": "Reference to declarative rules file" }, "sources": { "type": "array", "items": { "type": "string", "pattern": "^src:" }, "minItems": 1 }, "limitations": { "type": "array", "items": { "type": "string" } }, "tags": { "type": "array", "items": { "type": "string" } }, "related": { "type": "array", "items": { "type": "string" }, "description": "Related calendar or era ids" }, "notes": { "type": "string" } }}
4. era.schema.json(纪年 / 年号)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/era.schema.json", "title": "Era", "description": "A named era, regnal year system, or year-numbering scheme (e.g. Chinese nianhao, Japanese nengō).", "type": "object", "required": ["id", "names", "jd_mappable"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, "names": { "type": "object", "additionalProperties": { "type": "string" }, "minProperties": 1 }, "type": { "type": "array", "items": { "type": "string", "enum": [ "regnal", "dynastic", "religious", "political", "cyclical", "olympiad", "consular", "era", "other" ] } }, "jd_mappable": { "type": "string", "enum": ["true", "false", "partial"] }, "parent": { "type": "string", "description": "Parent dynasty or higher-level era id" }, "start": { "$ref": "temporal-expression.schema.json" }, "end": { "$ref": "temporal-expression.schema.json" }, "year_counting": { "type": "string", "enum": ["ascending", "descending", "regnal", "fixed", "other"], "description": "How years are numbered within the era" }, "calendar_ref": { "type": "string", "description": "The underlying calendar this era is expressed in" }, "successors": { "type": "array", "items": { "type": "string" } }, "predecessors": { "type": "array", "items": { "type": "string" } }, "sources": { "type": "array", "items": { "type": "string", "pattern": "^src:" }, "minItems": 1 }, "limitations": { "type": "array", "items": { "type": "string" } }, "tags": { "type": "array", "items": { "type": "string" } }, "notes": { "type": "string" } }}
5. transition.schema.json(历法切换点)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/transition.schema.json", "title": "Calendar Transition", "description": "A point or period when a region or polity changed calendar systems.", "type": "object", "required": ["id", "from_calendar", "to_calendar", "when", "region"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, "from_calendar": { "type": "string" }, "to_calendar": { "type": "string" }, "when": { "$ref": "temporal-expression.schema.json" }, "region": { "type": "object", "properties": { "names": { "type": "object", "additionalProperties": { "type": "string" } }, "modern_codes": { "type": "array", "items": { "type": "string" }, "description": "ISO 3166 or historical place identifiers" } } }, "days_skipped": { "type": "integer", "description": "Number of days skipped or inserted (can be negative)" }, "sources": { "type": "array", "items": { "type": "string", "pattern": "^src:" }, "minItems": 1 }, "notes": { "type": "string" } }}
6. chronology.schema.json(完整时间线 / 对照表)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/chronology.schema.json", "title": "Chronology", "description": "A structured timeline or conversion table linking multiple systems.", "type": "object", "required": ["id", "names", "entries"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, "names": { "type": "object", "additionalProperties": { "type": "string" }, "minProperties": 1 }, "description": { "type": "string" }, "range": { "type": "object", "properties": { "from": { "$ref": "temporal-expression.schema.json" }, "to": { "$ref": "temporal-expression.schema.json" } } }, "entries": { "type": "array", "items": { "type": "object", "required": ["temporal"], "properties": { "temporal": { "$ref": "temporal-expression.schema.json" }, "labels": { "type": "object", "additionalProperties": { "type": "string" } }, "notes": { "type": "string" } } }, "minItems": 1 }, "sources": { "type": "array", "items": { "type": "string", "pattern": "^src:" }, "minItems": 1 }, "tags": { "type": "array", "items": { "type": "string" } } }}
7. conversion-rule.schema.json(声明式规则,可选)
json
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://omnichronos.org/schemas/conversion-rule.schema.json", "title": "Conversion Rule", "description": "Declarative rules for simple arithmetic calendars to reduce code dependency.", "type": "object", "required": ["id", "calendar_ref", "rules"], "additionalProperties": false, "properties": { "id": { "type": "string", "pattern": "^[a-z0-9][a-z0-9_-]*$" }, "calendar_ref": { "type": "string" }, "rules": { "type": "object", "description": "Key-value rules, e.g. leap_year_cycle, month_lengths, epoch_offset" }, "notes": { "type": "string" } }}
使用说明
- 所有数据文件必须通过对应 Schema 验证(CI 强制)。
$ref使用相对或绝对 URI,实际项目中可用本地文件引用。names强制多语言支持(至少一种语言)。sources强制至少一条文献来源。jd_mappable是强制字段,明确处理非 JD 情况。temporal-expression是整个系统的灵活性核心。
附:OpenChronology 插件接口定义(Plugin Interface Specification)
以下是正式的插件接口草案(v0.1)。设计目标是:
- 语言无关(可用任何语言实现,推荐提供 WebAssembly 版本)
- 统一以 TemporalID 作为中间表示
- 同时支持可完全映射到 JD 的历法和不能完全映射的历法
- 清晰、最小化、易测试
1. 核心概念
TemporalID
统一的中间时间标识,优先使用儒略日,但允许更灵活的形式。
ts
type TemporalID = { // 优先使用 jd?: number; // Julian Day Number(可带小数表示时刻) rd?: number; // Rata Die(可选)
// 非 JD 或补充信息 local_id?: string; // 本地时间线标识 expression?: object; // 完整的 temporal-expression confidence?: number; // 0–1 notes?: string;}
CalendarDate
某个具体历法下的日期表示(结构由该历法自己定义,通常是对象)。
ts
type CalendarDate = { [key: string]: number | string | boolean | null; // 例如: // { year: 2026, month: 10, day: 8 } // { cycle: 78, year: 3, month: 5, leap: false, day: 12 }}
2. 插件必须实现的接口
每个插件必须实现以下方法(名称可因语言惯例略有调整,但语义必须一致):
2.1 元信息
ts
getInfo(): PluginInfo
返回:
ts
interface PluginInfo { id: string; // 插件唯一 ID,例如 "gregorian" name: string; // 人类可读名称 version: string; // 语义化版本 calendars: string[]; // 此插件支持的 calendar id 列表 jd_mappable: "true" | "false" | "partial"; description?: string; author?: string; license?: string;}
2.2 核心转换方法
ts
toTemporal(date: CalendarDate, calendarId: string): TemporalID
把指定历法的日期转换为 TemporalID。
ts
fromTemporal(temporal: TemporalID, calendarId: string): CalendarDate
把 TemporalID 转换为目标历法的日期。
2.3 验证
ts
validate(date: CalendarDate, calendarId: string): ValidationResult
ts
interface ValidationResult { valid: boolean; errors?: string[]; // 人类可读错误信息}
2.4 组件与元数据(推荐实现)
ts
getComponents(calendarId: string): string[]// 返回该历法使用的字段列表,例如 ["year", "month", "day", "leap"]
getMonthLengths?(year: number, calendarId: string): number[]isLeap?(year: number, calendarId: string): boolean
3. 错误处理约定
- 转换失败或输入非法时,应抛出明确的错误(或返回 Result 类型)。
- 推荐错误类型:
InvalidDateErrorUnsupportedCalendarErrorNonMappableError(当要求精确 JD 但无法提供时)OutOfRangeError
4. 插件清单文件(manifest.json)
每个插件目录下必须包含 manifest.json:
json
{ "id": "gregorian", "name": "Gregorian Calendar Plugin", "version": "1.0.0", "calendars": ["gregorian", "proleptic-gregorian"], "jd_mappable": "true", "languages": ["python", "wasm", "typescript"], "entry_points": { "python": "gregorian.py:GregorianPlugin", "wasm": "gregorian.wasm", "typescript": "dist/index.js" }, "dependencies": [], "description": "Standard proleptic Gregorian calendar implementation"}
5. 推荐实现优先级
- Python 参考实现(易读、方便测试)
- WebAssembly 版本(实现真正的语言无关)
- TypeScript / JavaScript
- 其他语言绑定(Rust、Go、C 等)
6. 接口使用示例(伪代码)
python
plugin = load_plugin("gregorian")
# 公历 → TemporalIDtemporal = plugin.to_temporal( {"year": 2026, "month": 10, "day": 8}, "gregorian")print(temporal.jd) # 2460960.5 之类
# TemporalID → 目标历法hebrew_date = plugin.from_temporal(temporal, "hebrew")
7. 扩展点(可选但鼓励)
插件可以额外实现:
add_duration(date, duration, calendarId)diff(date1, date2, calendarId)holidays(year, calendarId)format(date, locale, calendarId)
这些不属于核心接口,但会提升实用性。
8. 版本与兼容性
- 接口本身使用语义化版本(当前为
0.1.0)。 - 破坏性变更会提升主版本号。
- 插件应声明自己兼容的接口版本。
附:X.包容争议、兼容冲突:项目的核心价值与最低目标
X.1 核心立场
OpenChronology 不追求建立唯一正确的全球时间线,也不试图裁决历史争议。
本项目的最大价值,在于系统性地包容争议、兼容冲突。
同一事件、同一历法、同一纪年在不同文献、不同语言、不同学术传统中常常存在互相矛盾的记载。我们选择把这些矛盾本身作为一等公民进行结构化保存,而不是强行消解它们。
项目明确拒绝“唯一权威时间”的幻想,转而提供一个可计算、可比较、可溯源的多视角时间知识层。
X.2 最低可执行目标
在追求长远愿景的同时,项目设定清晰的最低目标:
至少把维基百科(多语言版本)和 Anna’s Archive 等大型资料库中出现的时间相关信息,进行结构化标注与关联。
具体包括但不限于:
- 人物生卒年
- 在位/执政时间
- 事件发生日期
- 历法改革与切换点
- 年号起止
- 文献自身使用的纪年方式
- 不同来源对同一时间点的冲突记载
这一目标将“穷尽全世界文献”的宏大愿景,落实为可验证、可分阶段推进的工程任务。
X.3 设计原则(针对争议与冲突)
- 多假说并存
任何时间表达都允许存在多个互相竞争的 claims,每个 claim 必须绑定来源与置信度。 - 冲突显式化
数据模型必须能明确标记“这些说法存在冲突”,而不是静默覆盖或取平均值。 - 来源至上
所有时间信息都必须可追溯至具体来源(维基页面、书籍、论文、铭文等)。没有来源的数据不予收录。 - 降级而非拒绝
当无法可靠映射到儒略日时,系统支持相对、区间、文学性、循环性表达,而不是强制放弃。 - 中立记录
项目本身不站队。用户可根据自己的需求选择采信哪些来源或哪些假说。
X.4 对数据模型的直接影响
temporal-expression升级为支持claims数组与conflicts标志。- 所有日历、纪年、事件条目均预留多来源字段。
- 新增“来源冲突报告”机制,方便后续研究与可视化。
- 非 JD 体系与争议时间线享有与精确 JD 时间线同等的一等公民地位。
X.5 实施优先级(基于本立场)
- 完善支持多 claims 与冲突标记的 Schema。
- 建立维基百科时间信息抽取与人工校验流水线。
- 探索 Anna’s Archive 等大型书库中时间元数据的合法、可行提取方式。
- 在此基础上再扩展其他文献来源与计算插件。
X.6 成功标准(阶段性)
- 能系统记录并展示同一时间点的多种冲突说法。
- 维基百科主要命名空间中的时间信息得到较高覆盖的结构化标注。
- 用户可以清晰看到“这个日期在不同来源中是如何被记载的”,而不是只得到一个被清洗过的单一结果。
本章总结
OpenChronology 的独特价值不在于提供“正确答案”,而在于诚实、结构化地保存人类记录时间时产生的所有矛盾与多样性。把维基百科与 Anna’s Archive 等大型资料库中的时间信息优先标注出来,是实现这一价值的最务实起点。
备注:初定名OmniChronos调整为OpenChronology,代码中的域暂未更新。