fix(dasha): judge antardasha sandhi from the unclipped start
Upstream 3c2dad95, rewritten for this tree. A birth-clipped antardasha start was reported as a transition. The first mahadasha start stays, because BUG-1268 already stores the real pre-birth boundary there. BUG-1382. Co-Authored-By: Grok (agent loop) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Grok (agent loop)
Cursor
parent
d11ee6f0dd
commit
5be864a8e4
@@ -36518,3 +36518,18 @@
|
||||
- 相关记录:BUG-1268、BUG-1380。
|
||||
- 复发自:无。
|
||||
- 修复版本:分支 `codex/upstream-sync8-20261017`。上游提交 `3c2dad95`、`8643bc9a`、`9e04f0db`。
|
||||
|
||||
## BUG-1382 | 出生日被当成小运交接
|
||||
|
||||
- 状态:resolved
|
||||
- 首次发现 / 最近更新:2026-10-17 / 2026-10-18
|
||||
- 来源:issue #80,任务书 T3。上游 `3c2dad95` 的 Sandhi 部分,按我方数据改写。检索「dasha_sandhi」「unclipped_start」,没有更早的同类记录。
|
||||
- 现象:出生后 30 天内的盘,Sandhi 表把出生日写成一次小运交接。那一天只是第一段小运被裁到出生日,不是两段小运的交界。
|
||||
- 触发条件:`_calc_dasha_sandhi` 用裁剪后的 `start` 判断小运交接。默认参考时刻还带着当前的时分秒。
|
||||
- 根因:第一段小运的可见起点被改成了出生日。BUG-1268 之后,第一大运自己的 `start` 已经是出生前的真实交接,不能连大运起点一起跳过。
|
||||
- 修复:小运起点改用 `unclipped_start_datetime`。第一大运起点仍参与判断。没给参考日期时,参考时刻归零到当天 0 点。
|
||||
- 验证:`tests/test_dasha_sandhi_birth_clip.py`。虚构盘在出生后 30 天不再把出生日算成小运交接;出生前的大运起点仍在容限内出现。
|
||||
- 防复发:上述测试。
|
||||
- 相关记录:BUG-1268、BUG-1380。
|
||||
- 复发自:无。
|
||||
- 修复版本:分支 `codex/upstream-sync8-20261017`。上游提交 `3c2dad95`。
|
||||
|
||||
@@ -464,7 +464,7 @@ def _calc_sensitive_points(planets):
|
||||
|
||||
|
||||
def _calc_dasha_sandhi(dasha_result, reference_date=None, orb_days=90):
|
||||
ref = datetime.strptime(reference_date, "%Y-%m-%d") if reference_date else datetime.now()
|
||||
ref = datetime.strptime(reference_date, "%Y-%m-%d") if reference_date else datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
sandhi = []
|
||||
timeline = dasha_result.get('timeline', []) if isinstance(dasha_result, dict) else []
|
||||
for md in timeline:
|
||||
@@ -486,7 +486,11 @@ def _calc_dasha_sandhi(dasha_result, reference_date=None, orb_days=90):
|
||||
for boundary_key in ['start', 'end']:
|
||||
if boundary_key not in ad:
|
||||
continue
|
||||
bdt = datetime.strptime(ad[boundary_key], "%Y-%m-%d")
|
||||
# 被出生裁掉的小运起点不是交接。用完整起点判断,第一大运自己的 start 仍是出生前的真实交接,不跳过。
|
||||
boundary_date = ad[boundary_key]
|
||||
if boundary_key == 'start' and ad.get('unclipped_start_datetime'):
|
||||
boundary_date = datetime.fromisoformat(ad['unclipped_start_datetime']).strftime('%Y-%m-%d')
|
||||
bdt = datetime.strptime(boundary_date, "%Y-%m-%d")
|
||||
delta = (bdt - ref).days
|
||||
if abs(delta) <= orb_days:
|
||||
sandhi.append({
|
||||
@@ -494,7 +498,7 @@ def _calc_dasha_sandhi(dasha_result, reference_date=None, orb_days=90):
|
||||
'mahadasha_lord': md.get('lord'),
|
||||
'lord': ad.get('lord'),
|
||||
'boundary': boundary_key,
|
||||
'date': ad.get(boundary_key),
|
||||
'date': boundary_date,
|
||||
'days_from_reference': delta,
|
||||
'within_orb': True,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
"""A clipped birth balance is not an actual Dasha transition.
|
||||
|
||||
Upstream ``tests/test_dasha_sandhi_birth_clip.py`` (3c2dad95) skips the first
|
||||
mahadasha start whenever ``is_balance`` is set. This tree does not: BUG-1268
|
||||
already stores the real pre-birth mahadasha boundary in ``start``.
|
||||
|
||||
| 处 | 原值 | 新值 | 原因 |
|
||||
| --- | --- | --- | --- |
|
||||
| 第一大运 ``start`` | ``2000-01-01``,并跳过 ``is_balance`` 起点 | ``1998-01-01``,不跳过 | 我方第一大运起点是出生前的真实交接 |
|
||||
| 断言 | 跳过起点后窗口为空 | 起点超出容限,窗口仍为空 | 单独证明被裁剪的小运起点不算交接 |
|
||||
"""
|
||||
from types import SimpleNamespace
|
||||
|
||||
from scripts.jyotish_engine import _calc_dasha_sandhi, cmd_dasha
|
||||
|
||||
|
||||
def test_birth_clip_does_not_create_a_transition():
|
||||
data = {'timeline': [{'lord': 'Saturn', 'is_balance': True,
|
||||
'start': '1998-01-01', 'end': '2010-01-01',
|
||||
'antardasha_timeline': [{'lord': 'Mercury', 'start': '2000-01-01', 'end': '2002-01-01',
|
||||
'unclipped_start_datetime': '1999-01-01T12:30:00'}]}]}
|
||||
assert _calc_dasha_sandhi(data, '2000-01-01')['sandhi_windows'] == []
|
||||
|
||||
|
||||
def test_actual_unclipped_start_is_still_found():
|
||||
data = {'timeline': [{'lord': 'Saturn', 'is_balance': True,
|
||||
'start': '1998-01-01', 'end': '2010-01-01',
|
||||
'antardasha_timeline': [{'lord': 'Mercury', 'start': '2000-01-01', 'end': '2002-01-01',
|
||||
'unclipped_start_datetime': '1999-12-20T12:30:00'}]}]}
|
||||
windows = _calc_dasha_sandhi(data, '2000-01-01', 30)['sandhi_windows']
|
||||
assert len(windows) == 1
|
||||
assert windows[0]['date'] == '1999-12-20'
|
||||
assert windows[0]['days_from_reference'] == -12
|
||||
|
||||
|
||||
def test_real_boundaries_are_inclusive_at_orb_limit():
|
||||
data = {'timeline': [{'lord': 'Sun', 'start': '2000-01-01', 'end': '2000-02-01'}]}
|
||||
windows = _calc_dasha_sandhi(data, '2000-01-02', 1)['sandhi_windows']
|
||||
assert len(windows) == 1 and windows[0]['date'] == '2000-01-01'
|
||||
|
||||
|
||||
def test_prebirth_mahadasha_start_is_not_discarded():
|
||||
data = {'timeline': [{'lord': 'Saturn', 'is_balance': True,
|
||||
'start': '1999-12-01', 'end': '2010-01-01',
|
||||
'antardasha_timeline': []}]}
|
||||
windows = _calc_dasha_sandhi(data, '2000-01-01', 90)['sandhi_windows']
|
||||
assert [row['date'] for row in windows] == ['1999-12-01']
|
||||
|
||||
|
||||
def test_thirty_day_chart_does_not_list_the_birth_day_as_an_antardasha_join():
|
||||
packet = cmd_dasha(SimpleNamespace(
|
||||
moon_lon=20 / 3, nakshatra=None, pada=None,
|
||||
birthdate='2000-01-01', year=2000, month=1, day=1, hour=12, minute=0, second=0,
|
||||
lat=None, lon=None, tz=0, today='2000-01-31', dasha_year_days=365.25))
|
||||
windows = _calc_dasha_sandhi(packet, '2000-01-31', 30)['sandhi_windows']
|
||||
clipped = [
|
||||
row for row in windows
|
||||
if row['level'] == 'antardasha' and row['boundary'] == 'start' and row['date'] == '2000-01-01'
|
||||
]
|
||||
assert clipped == []
|
||||
Reference in New Issue
Block a user