standards/ 存放 Epheon 各个领域模块的参考数值与预期结果,简称 fixture。
fixture 用于:
- 包级单元测试验证正确性
conformance/一致性校验- 不同实现(TypeScript、Python、Rust)之间的交叉验证
fixture 不用于:
- 大型天文数据集(进入未来的
@epheon/dataset-*包) - 运行时数据(内核不应读取
standards/)
standards/
├── README.md # 本文件
├── primitives/ # @epheon/primitives 的参考数值
│ ├── angles.json # 角度转换与归一化样例
│ ├── durations.json # 时长转换样例
│ └── vectors.json # 三维向量运算样例
├── reference/ # 坐标与参考系参考数值
│ ├── coordinates.json # 球面坐标与内部笛卡尔转换样例
│ └── frames.json # ReferenceFrame 预设帧样例
├── calendar-chinese/ # 中国历法参考样例
│ └── lunar.json # 农历月表与已知历日样例
├── solar/ # 太阳黄经与二十四节气参考数值
│ ├── longitudes.json # 太阳视黄经样例
│ └── terms.json # 二十四节气时刻样例
└── temporal/ # @epheon/temporal 的参考数值
├── julian-days.json # Julian Day 转换样例
├── time-scales.json # 时间尺度转换样例
└── utc-invalid-inputs.json # 非法 UTC 输入样例
每个 fixture 文件使用该领域最自然的 schema,而非统一的泛型模版。
为避免随着目录增多后出现大量 foo[].bar.baz 形式的长路径,下面统一按三层展示:
根结构:文件顶层字段,先快速说明这个文件装了什么条目字段:数组元素或顶层对象的直接字段内嵌对象字段:只有存在对象嵌套时才展开
| 文件 | 根结构 | 说明 |
|---|---|---|
primitives/angles.json |
conversions[]、normalization[] |
角度单位转换与归一化 |
primitives/durations.json |
conversions[] |
时长单位转换 |
primitives/vectors.json |
vectors[]、operations[] |
向量数值与运算结果 |
reference/coordinates.json |
coordinates[] |
球面坐标与笛卡尔转换 |
reference/frames.json |
frames[] |
预设参考系定义 |
calendar-chinese/lunar.json |
monthTables[]、lunarDates[]、ganzhi[] |
农历月表、历日与干支样例 |
solar/longitudes.json |
solarLongitudes[] |
太阳视黄经参考样例 |
solar/terms.json |
solarTerms[] |
二十四节气时刻样例 |
temporal/julian-days.json |
utcInstants[] |
UTC 与 JD 映射 |
temporal/time-scales.json |
timeScaleConversions[] |
UTC 与各时间尺度转换 |
temporal/utc-invalid-inputs.json |
utcDateTimes[] |
非法 UTC 输入与错误码 |
根结构:{ conversions: AngleConversion[]; normalization: AngleNormalization[] }
conversions[]
| 字段 | 类型 | 说明 |
|---|---|---|
degrees |
number | 度数 |
radians |
number | 弧度 |
turns |
number | 圈数 |
arcminutes |
number | 角分 |
arcseconds |
number | 角秒 |
normalization[]
| 字段 | 类型 | 说明 |
|---|---|---|
degrees |
number | 原始角度 |
normalizedDegrees |
number | [0°, 360°) 归一化结果 |
signedDegrees |
number | [-180°, 180°) 归约结果 |
根结构:{ conversions: DurationConversion[] }
conversions[]
| 字段 | 类型 | 说明 |
|---|---|---|
seconds |
number | 秒(basis unit) |
milliseconds |
number | 毫秒 |
days |
number | 日 |
julianYears |
number | 儒略年(365.25 日) |
julianCenturies |
number | 儒略世纪(36525 日) |
根结构:{ vectors: VectorSample[]; operations: VectorOperation[] }
vectors[]
| 字段 | 类型 | 说明 |
|---|---|---|
x |
number | X 分量 |
y |
number | Y 分量 |
z |
number | Z 分量 |
magnitude |
number | 欧几里得范数 sqrt(x^2 + y^2 + z^2) |
operations[]
| 字段 | 类型 | 说明 |
|---|---|---|
a |
object | 运算的第一个向量 |
b |
object | 运算的第二个向量 |
add |
object | a + b 结果向量 |
subtract |
object | a - b 结果向量 |
dot |
number | a · b 点积 |
cross |
object | a × b 叉积结果向量 |
operations[].a、operations[].b、operations[].add、operations[].subtract、operations[].cross
| 字段 | 类型 | 说明 |
|---|---|---|
x |
number | X 分量 |
y |
number | Y 分量 |
z |
number | Z 分量 |
根结构:{ coordinates: CoordinateSample[] }
coordinates[]
| 字段 | 类型 | 说明 |
|---|---|---|
longitudeDegrees |
number | 球面经度(度) |
latitudeDegrees |
number | 球面纬度(度) |
distanceAu |
number | 对应距离(AU) |
cartesian |
object | 对应的内部笛卡尔向量 |
coordinates[].cartesian
| 字段 | 类型 | 说明 |
|---|---|---|
x |
number | X 分量(AU) |
y |
number | Y 分量(AU) |
z |
number | Z 分量(AU) |
根结构:{ frames: ReferenceFrameSample[] }
frames[]
| 字段 | 类型 | 说明 |
|---|---|---|
name |
string | 预设帧稳定名称 |
coordinateSystem |
string | 对应坐标系统 |
epochJde |
number | null |
固定历元的 JDE;瞬时历元帧为 null |
根结构:{ monthTables: LunarMonthTableSample[]; lunarDates: LunarDateSample[]; ganzhi: GanzhiSample[] }
monthTables[]
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 样例稳定标识 |
start |
string | 查询窗口起点,带显式时区偏移 |
end |
string | 查询窗口终点,带显式时区偏移 |
expectedMonths |
object[] | 该窗口内预期的农历月表结果 |
basis |
string | 样例来源、规则集或边界场景说明 |
monthTables[].expectedMonths[]
| 字段 | 类型 | 说明 |
|---|---|---|
year |
number | 农历年 |
month |
number | 农历月编号 |
isLeapMonth |
boolean | 当前月份是否闰月 |
lunarDates[]
| 字段 | 类型 | 说明 |
|---|---|---|
input |
string | 查询时刻,带显式时区偏移 |
year |
number | 预期农历年 |
month |
number | 预期农历月编号 |
day |
number | 预期农历日编号 |
isLeapMonth |
boolean | 预期当前月份是否闰月 |
basis |
string | 样例来源、规则集或边界场景说明 |
ganzhi[]
| 字段 | 类型 | 说明 |
|---|---|---|
input |
string | 查询时刻,带显式时区偏移 |
year |
object | 预期纪年结果 |
month |
object | 预期纪月结果 |
day |
object | 预期纪日结果 |
hour |
object | 预期纪时结果 |
basis |
string | 样例来源、规则集或边界场景说明 |
ganzhi[].year、ganzhi[].month、ganzhi[].day、ganzhi[].hour
| 字段 | 类型 | 说明 |
|---|---|---|
stem |
string | 天干 |
branch |
string | 地支 |
name |
string | 干支组合名 |
根结构:{ utcInstants: JulianDayFixture[] }
utcInstants[]
| 字段 | 类型 | 说明 |
|---|---|---|
input |
string | UTC 字符串,带时区偏移 |
julianDay |
number | 对应的 Julian Day 数值 |
basis |
string,可选 | 数据来源或计算公式 |
根结构:{ timeScaleConversions: TimeScaleConversion[] }
timeScaleConversions[]
| 字段 | 类型 | 说明 |
|---|---|---|
input |
string | UTC 字符串,带时区偏移 |
julianDay |
number | 对应的 JD |
taiMinusUtcSeconds |
number | TAI - UTC,闰秒累计偏移 |
deltaTSeconds |
number | ΔT = TT - UT1 |
ttMinusUtcSeconds |
number | TT - UTC |
ut1MinusUtcSeconds |
number | UT1 - UTC |
julianEphemerisDay |
number | 对应的 JDE |
basis |
string,可选 | 计算说明或公式参考 |
根结构:{ utcDateTimes: InvalidUtcInput[] }
utcDateTimes[]
| 字段 | 类型 | 说明 |
|---|---|---|
input |
string | 非法 UTC 字符串 |
code |
string | 预期错误码,如 InvalidUTCDateTime |
basis |
string | 该输入被判定为非法原因 |
根结构:{ solarLongitudes: SolarLongitudeSample[] }
solarLongitudes[]
| 字段 | 类型 | 说明 |
|---|---|---|
year |
number | 样例所在公历年份 |
term |
string | 对应节气名 |
input |
string | UTC 字符串,带 Z |
longitudeDegrees |
number | 对应时刻太阳地心视黄经(度) |
basis |
string | 外部参考来源与生成方法说明 |
根结构:{ solarTerms: SolarTermSample[] }
solarTerms[]
| 字段 | 类型 | 说明 |
|---|---|---|
year |
number | 节气所在公历年份 |
name |
string | 节气名 |
targetLongitudeDegrees |
number | 对应节气的目标黄经(度) |
instant |
string | 节气交接时刻,UTC 字符串,带 Z |
basis |
string | 外部参考来源与生成方法说明 |
新增领域包时,同步创建对应的 standards/<domain>/ 目录和 fixture 文件。依照该领域最自然的 schema 组织数据,并在本 README 中补全字段说明。
- 覆盖正常值和边界值
- 包含非法输入(用于验证错误处理)
- 数值转换类 fixture 依赖显式公式或已知参考源(Meeus、IERS、JPL 等),在
basis字段注明 - 大型数据集(> 100 KB)不应进入
standards/,应放入独立的 dataset package
fixture 按领域分为三类,各有不同的数据来源与验证链:
通过已知公式(Meeus 算法、IAU 决议、IAU SOFA conventions)计算得出,在测试中赋 tolerance。
| 领域 | 参考来源 | 验证方式 |
|---|---|---|
primitives/ |
数学恒等式、单位换算公式 | 显式 tolerance |
temporal/julian-days.json |
Meeus、IAU SOFA | 显式 tolerance |
temporal/time-scales.json |
IERS Bulletin C、IAU 决议 | 显式 tolerance |
reference/ |
IAU 决议、SOFA conventions | 显式 tolerance |
二十四节气时刻与太阳视黄经对照 JPL Horizons API 生成。
| 文件 | 参考来源 | 验证方式 |
|---|---|---|
solar/terms.json |
JPL Horizons(quantity 31, ObsEcLon,逐时插值) | 建议 1s 级 tolerance |
solar/longitudes.json |
JPL Horizons(同上) | 建议 0.01° 级 tolerance |
每条样例的 basis 字段记录具体查询参数与方法。
中国历法样例是合成样例:将多个底层组件的计算结果固化为可复核的离散结果。
| 文件 | 底层输入来源 | 验证方式 |
|---|---|---|
calendar-chinese/lunar.json |
VSOP87(太阳视位置)+ ELP2000(月亮视位置)+ 内置 ΔT + IERS 闰秒表,按 modern 规则集生成 | 离散字段精确相等 |
中国历法样例的
basis字段记录该样例对应的规则集切片与边界场景(如"2023 闰二月窗口"、"2024 春节年界")。离散字段(year、month、day、isLeapMonth)使用精确相等校验;底层的天象输入精度由上述天象类 tolerance 约束。
- 非法输入:根据公共 API 校验规则构造
- 外部校准来源:JPL Horizons 等参考数据的具体查询参数和日期记录在各条
basis中
这一节只记录当前已经由 fixture / conformance 支撑的口径,不是完整精度报告。
| 能力链路 | 当前证据范围 | 当前可说明口径 | 当前不能说明的内容 |
|---|---|---|---|
| 时间/转换类 | primitives/、temporal/、reference/ fixture 与包级测试 |
以公式、常量和显式 tolerance 校验当前实现正确性 | 不能替代外部权威时标服务的全量符合性声明 |
| 二十四节气 | solar/terms.json,当前覆盖 2024 / 2025 |
当前节气链路对照 JPL Horizons,conformance 容忍度为 ±15 分钟 | 不能据此宣称完整 VSOP87 或全天文长期精度 |
| 朔望 | lunar/phases.json,当前覆盖 2020-2025 |
当前朔望链路在 bootstrap 样例上稳定,事件时刻 conformance 容忍度为 ±6 小时 | 不能据此宣称独立外部校准后的月相绝对精度 |
| 中国历法 | calendar-chinese/lunar.json,当前覆盖 2020 / 2023 / 2024 / 2025 的闰月、年界、月界与干支边界 |
当前 modern 规则集在这些离散边界样例上可复核,月表/历日/干支按精确相等校验 | 不能据此宣称历史规则全覆盖或完整权威历书等价 |
补充说明:
- “精确相等”只适用于离散结果字段,如农历
year/month/day/isLeapMonth和干支四柱。 - “数值 tolerance”只适用于底层连续量或事件时刻,如节气时刻、朔望时刻。
- 当问题变成“模型绝对精度”而不是“当前实现是否稳定回归”时,应优先看外部校准数据,而不是只看 bootstrap fixture。
包级测试通过相对路径 ../../standards/<domain>/<fixture>.json 读取 fixture。
例如 packages/primitives/tests/angle.test.ts 读取 standards/primitives/angles.json。