Upstream replaced the redacted-year sample (April 17, 14:45, about 36.5N 114.2E) with a public birth (1935-06-21 11:00, Cajarc, France) in the reading workflow and in the narayana-dasha / solar-return usage text. Our copies still carried the private date, time and place. The PDF guide's example coordinates now name the San Francisco values it already labels. Doc and docstring text only; no calculation changes. The same sample is still a quality-gate fixture in scripts/run_quality_gate.py and appears in older docs/research notes; neither is changed here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
cmd_solar_return: Solar Return (Varshaphala) CLI 子命令
|
|
Jyotish Vedic Astrology Skill — v6.0.18
|
|
|
|
用法:
|
|
python3 jyotish_engine.py solar-return --year 1935 --month 6 --day 21 \
|
|
--hour 11 --minute 0 --lat 44.486 --lon 1.842 --tz 1 --target-year 2026
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
from typing import Dict, Any
|
|
|
|
|
|
def cmd_solar_return(args: Any) -> Dict[str, Any]:
|
|
"""
|
|
solar-return 子命令:计算太阳返照盘 + 完整 Varshaphala 分析。
|
|
|
|
参数 (来自 args):
|
|
year, month, day, hour, minute: 出生时间
|
|
lat, lon, tz: 出生地点/时区
|
|
target_year: 目标年份(计算该年太阳返照)
|
|
|
|
返回:
|
|
dict: solar_return_full_report() 的结果
|
|
"""
|
|
try:
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from ayanamsa_utils import DEFAULT_AYANAMSA_NAME
|
|
from solar_return import solar_return_full_report
|
|
except ImportError as e:
|
|
return {"error": f"solar_return 模块导入失败: {e}"}
|
|
|
|
if not hasattr(args, 'target_year') or args.target_year is None:
|
|
return {"error": "solar-return 需要 --target-year 参数",
|
|
"hint": "指定目标年份,如 --target-year 2026"}
|
|
|
|
return solar_return_full_report(
|
|
args.year, args.month, args.day,
|
|
args.hour, args.minute,
|
|
args.lat, args.lon, args.tz,
|
|
args.target_year,
|
|
ayanamsa_name=getattr(args, 'ayanamsa', None) or DEFAULT_AYANAMSA_NAME,
|
|
birth_second=int(getattr(args, 'second', 0) or 0),
|
|
node_mode=getattr(args, 'node_mode', None) or 'mean', # BUG-1501
|
|
**solar_return_location_kwargs(args),
|
|
)
|
|
|
|
|
|
def solar_return_location_kwargs(args: Any) -> Dict[str, Any]:
|
|
"""Return-location kwargs for ``solar_return_full_report``.
|
|
|
|
Two arg shapes are accepted: the annual-pack namespace (``return_lat`` /
|
|
``return_lon`` / ``return_tz`` / ``return_timezone_id``, built by
|
|
``annual_tajika_pack._args_from_payload``) and the CLI namespace
|
|
(``--solar-return-location-mode`` / ``--current-*`` / ``--timezone-id``).
|
|
Upstream yinduzhanxing 41d1c740.
|
|
"""
|
|
if getattr(args, 'return_lat', None) is not None or getattr(args, 'return_timezone_id', None):
|
|
return {
|
|
'local_timezone_id': getattr(args, 'return_timezone_id', None),
|
|
'return_lat': getattr(args, 'return_lat', None),
|
|
'return_lon': getattr(args, 'return_lon', None),
|
|
'return_tz': getattr(args, 'return_tz', None),
|
|
}
|
|
mode = getattr(args, 'solar_return_location_mode', None) or 'birth_place'
|
|
if mode == 'current_location':
|
|
if any(getattr(args, key, None) is None for key in ('current_lat', 'current_lon', 'current_tz')):
|
|
raise ValueError('current_location requires current_lat, current_lon and current_tz')
|
|
return {
|
|
'local_timezone_id': getattr(args, 'current_timezone_id', None),
|
|
'return_lat': float(args.current_lat),
|
|
'return_lon': float(args.current_lon),
|
|
'return_tz': float(args.current_tz),
|
|
}
|
|
# CLI passes ``--timezone-id``; API payloads reach here as ``timezone`` /
|
|
# ``timezone_name`` (calculation_profile_contract keys). Only IANA ids count.
|
|
for key in ('timezone_id', 'timezone', 'timezone_name'):
|
|
value = getattr(args, key, None)
|
|
if isinstance(value, str) and '/' in value:
|
|
return {'local_timezone_id': value.strip()}
|
|
return {'local_timezone_id': None}
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# 独立测试入口
|
|
import argparse
|
|
from datetime import datetime
|
|
|
|
parser = argparse.ArgumentParser(description='Solar Return 测试')
|
|
parser.add_argument('--year', type=int, required=True)
|
|
parser.add_argument('--month', type=int, required=True)
|
|
parser.add_argument('--day', type=int, required=True)
|
|
parser.add_argument('--hour', type=int, default=12)
|
|
parser.add_argument('--minute', type=int, default=0)
|
|
parser.add_argument('--lat', type=float, required=True)
|
|
parser.add_argument('--lon', type=float, required=True)
|
|
parser.add_argument('--tz', type=float, default=0.0)
|
|
parser.add_argument('--target-year', type=int, required=True)
|
|
a = parser.parse_args()
|
|
|
|
result = cmd_solar_return(a)
|
|
import json
|
|
print(json.dumps(result, ensure_ascii=False, indent=2, default=str))
|