ziwei-chart 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ziwei_chart/__init__.py +103 -0
- ziwei_chart/calendar.py +160 -0
- ziwei_chart/data/60jiazi.json +62 -0
- ziwei_chart/data/6base_mainstar_location.json +171 -0
- ziwei_chart/data/sihua_config.json +62 -0
- ziwei_chart/data/wuhu_config.json +12 -0
- ziwei_chart/horoscope.py +134 -0
- ziwei_chart/models.py +343 -0
- ziwei_chart/natal.py +276 -0
- ziwei_chart/rules.py +70 -0
- ziwei_chart/schema/ziwei_chart.v1.json +365 -0
- ziwei_chart/solar_time.py +85 -0
- ziwei_chart-0.1.0.dist-info/METADATA +109 -0
- ziwei_chart-0.1.0.dist-info/RECORD +17 -0
- ziwei_chart-0.1.0.dist-info/WHEEL +5 -0
- ziwei_chart-0.1.0.dist-info/licenses/LICENSE +202 -0
- ziwei_chart-0.1.0.dist-info/top_level.txt +1 -0
ziwei_chart/__init__.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""ziwei-chart: deterministic Zi Wei Dou Shu natal chart casting.
|
|
2
|
+
|
|
3
|
+
>>> from datetime import datetime
|
|
4
|
+
>>> from zoneinfo import ZoneInfo
|
|
5
|
+
>>> from ziwei_chart import BirthInput, cast_chart
|
|
6
|
+
>>> chart = cast_chart(BirthInput(
|
|
7
|
+
... datetime=datetime(2004, 4, 25, 9, 20, tzinfo=ZoneInfo("Asia/Shanghai")),
|
|
8
|
+
... gender="女"))
|
|
9
|
+
>>> chart.to_dict()["schema"]
|
|
10
|
+
'ziwei_chart.v1'
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from typing import Literal
|
|
17
|
+
|
|
18
|
+
from .calendar import CalendarRules, resolve_calendar
|
|
19
|
+
from .models import Chart, HoroscopeChart
|
|
20
|
+
from .natal import build_natal_chart
|
|
21
|
+
from .rules import RuleSet
|
|
22
|
+
|
|
23
|
+
Gender = Literal["男", "女"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class BirthInput:
|
|
28
|
+
"""Birth data for casting.
|
|
29
|
+
|
|
30
|
+
- ``datetime``: aware civil birth datetime with an IANA ZoneInfo.
|
|
31
|
+
- ``gender``: "男" or "女".
|
|
32
|
+
- ``longitude``/``latitude``: optional; when both are given the civil
|
|
33
|
+
time is converted to true solar time (requires the ``[solar]`` extra).
|
|
34
|
+
Place names are resolved by the caller.
|
|
35
|
+
- ``bazi``/``lunar_date_str``: optional precomputed calendar. When both
|
|
36
|
+
are provided they are used as-is and ``datetime`` may be None — this is
|
|
37
|
+
the path used by applications that keep their own calendar service.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
datetime: datetime | None = None
|
|
41
|
+
gender: Gender = "男"
|
|
42
|
+
longitude: float | None = None
|
|
43
|
+
latitude: float | None = None
|
|
44
|
+
bazi: str | None = None
|
|
45
|
+
lunar_date_str: str | None = None
|
|
46
|
+
calendar_rules: CalendarRules = field(default_factory=CalendarRules)
|
|
47
|
+
|
|
48
|
+
def __post_init__(self):
|
|
49
|
+
if self.gender not in ("男", "女"):
|
|
50
|
+
raise ValueError("紫微斗数暂不支持非二元性别")
|
|
51
|
+
has_precomputed = self.bazi is not None or self.lunar_date_str is not None
|
|
52
|
+
if has_precomputed and not (self.bazi and self.lunar_date_str):
|
|
53
|
+
raise ValueError("bazi and lunar_date_str must be provided together")
|
|
54
|
+
if not has_precomputed and self.datetime is None:
|
|
55
|
+
raise ValueError("either datetime or a precomputed bazi/lunar_date_str is required")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def cast_chart(birth_input: BirthInput, rules: RuleSet | None = None) -> Chart:
|
|
59
|
+
"""Cast the natal chart (and unlock horoscope views) from a BirthInput."""
|
|
60
|
+
rules = rules or RuleSet.default()
|
|
61
|
+
if birth_input.bazi and birth_input.lunar_date_str:
|
|
62
|
+
chart = cast_chart_from_calendar(
|
|
63
|
+
bazi=birth_input.bazi, lunar_date_str=birth_input.lunar_date_str,
|
|
64
|
+
gender=birth_input.gender, rules=rules,
|
|
65
|
+
)
|
|
66
|
+
if birth_input.datetime is not None:
|
|
67
|
+
chart.input_receipt["datetime"] = birth_input.datetime.isoformat()
|
|
68
|
+
return chart
|
|
69
|
+
|
|
70
|
+
calendar_info = resolve_calendar(
|
|
71
|
+
birth_input.datetime, birth_input.longitude, birth_input.latitude,
|
|
72
|
+
birth_input.calendar_rules,
|
|
73
|
+
)
|
|
74
|
+
chart = cast_chart_from_calendar(
|
|
75
|
+
bazi=calendar_info.bazi, lunar_date_str=calendar_info.lunar_date_str,
|
|
76
|
+
gender=birth_input.gender, rules=rules,
|
|
77
|
+
)
|
|
78
|
+
chart.calendar = calendar_info
|
|
79
|
+
chart.input_receipt.update(calendar_info.as_receipt())
|
|
80
|
+
if birth_input.datetime is not None:
|
|
81
|
+
chart.input_receipt["datetime"] = birth_input.datetime.isoformat()
|
|
82
|
+
if birth_input.longitude is not None and birth_input.latitude is not None:
|
|
83
|
+
chart.input_receipt["coordinates"] = [birth_input.latitude, birth_input.longitude]
|
|
84
|
+
return chart
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def cast_chart_from_calendar(bazi: str, lunar_date_str: str, gender: str,
|
|
88
|
+
rules: RuleSet | None = None) -> Chart:
|
|
89
|
+
"""Cast the natal chart from a precomputed bazi + lunar_date_str pair."""
|
|
90
|
+
return build_natal_chart(bazi=bazi, lunar_date_str=lunar_date_str,
|
|
91
|
+
gender=gender, rules=rules)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
__all__ = [
|
|
95
|
+
"BirthInput",
|
|
96
|
+
"CalendarRules",
|
|
97
|
+
"Chart",
|
|
98
|
+
"HoroscopeChart",
|
|
99
|
+
"RuleSet",
|
|
100
|
+
"cast_chart",
|
|
101
|
+
"cast_chart_from_calendar",
|
|
102
|
+
]
|
|
103
|
+
__version__ = "0.1.0"
|
ziwei_chart/calendar.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Calendar resolution: true solar time, day/time-switch rules, bazi and
|
|
2
|
+
lunar date computation via lunar-python.
|
|
3
|
+
|
|
4
|
+
Default rules match the legacy suanqiu behaviour exactly:
|
|
5
|
+
- ``day_rule="zi-early"``: 23:00 (子初) starts the next day pillar.
|
|
6
|
+
- ``time_rule="next-day"``: the hour pillar for 23:00-24:00 is computed at
|
|
7
|
+
00:30 of the following civil day.
|
|
8
|
+
- the lunar date used by the chart itself follows civil midnight, NOT the
|
|
9
|
+
day-pillar switch.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from datetime import datetime, timedelta
|
|
16
|
+
from typing import Literal, NamedTuple
|
|
17
|
+
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
18
|
+
|
|
19
|
+
DayRule = Literal["midnight", "zi-early", "solar-midnight"]
|
|
20
|
+
TimeRule = Literal["midnight", "prev-day", "next-day"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class LunarDateTime(NamedTuple):
|
|
24
|
+
year: int
|
|
25
|
+
month: int
|
|
26
|
+
day: int
|
|
27
|
+
hour: int
|
|
28
|
+
minute: int
|
|
29
|
+
second: int
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
_LUNAR_DATETIME_RE = re.compile(r"^\s*(\d{1,4})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})\s*$")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def parse_lunar_datetime(text: str) -> LunarDateTime:
|
|
36
|
+
"""解析 lunar_date_str。农历二月有廿九/三十,不能用 datetime.strptime。"""
|
|
37
|
+
match = _LUNAR_DATETIME_RE.match(text or "")
|
|
38
|
+
if not match:
|
|
39
|
+
raise ValueError(f"Invalid lunar date string: {text!r}")
|
|
40
|
+
value = LunarDateTime(*(int(part) for part in match.groups()))
|
|
41
|
+
if not (1 <= value.month <= 12 and 1 <= value.day <= 30
|
|
42
|
+
and value.hour < 24 and value.minute < 60 and value.second < 60):
|
|
43
|
+
raise ValueError(f"Invalid lunar date string: {text!r}")
|
|
44
|
+
return value
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class CalendarRules:
|
|
49
|
+
day_rule: DayRule = "zi-early"
|
|
50
|
+
time_rule: TimeRule = "next-day"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class CalendarInfo:
|
|
55
|
+
bazi: str
|
|
56
|
+
lunar_date_str: str
|
|
57
|
+
true_solar_time: datetime | None # from_calendar 路径时为 None
|
|
58
|
+
timezone: str
|
|
59
|
+
day_rule: DayRule
|
|
60
|
+
time_rule: TimeRule
|
|
61
|
+
civil_datetime: datetime | None = None
|
|
62
|
+
|
|
63
|
+
def as_receipt(self) -> dict:
|
|
64
|
+
return {
|
|
65
|
+
"bazi": self.bazi,
|
|
66
|
+
"lunar_date_str": self.lunar_date_str,
|
|
67
|
+
"true_solar_time": (
|
|
68
|
+
self.true_solar_time.strftime("%Y-%m-%d %H:%M:%S")
|
|
69
|
+
if self.true_solar_time else None
|
|
70
|
+
),
|
|
71
|
+
"timezone": self.timezone,
|
|
72
|
+
"calendar_rules": {"day_rule": self.day_rule, "time_rule": self.time_rule},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def apply_day_switch(dt_ast: datetime, ast_hour_float: float, tz: str,
|
|
77
|
+
day_rule: DayRule = "zi-early") -> datetime:
|
|
78
|
+
"""day_rule: "midnight" 子正换日 | "zi-early" 子初换日 | "solar-midnight" 真太阳午夜."""
|
|
79
|
+
dt_ast = dt_ast.astimezone(ZoneInfo(tz))
|
|
80
|
+
if day_rule == "zi-early":
|
|
81
|
+
if 23.0 <= ast_hour_float < 24.0:
|
|
82
|
+
return dt_ast + timedelta(days=1)
|
|
83
|
+
elif day_rule == "solar-midnight":
|
|
84
|
+
if ast_hour_float < 0.5:
|
|
85
|
+
return dt_ast + timedelta(days=1)
|
|
86
|
+
# "midnight" 不动
|
|
87
|
+
return dt_ast
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def apply_time_switch(dt_for_day: datetime, ast_hour_float: float, tz: str,
|
|
91
|
+
time_rule: TimeRule = "next-day") -> datetime:
|
|
92
|
+
"""time_rule: "midnight" 民用日界 | "next-day" 夜子归次日 | "prev-day" 早子归前日."""
|
|
93
|
+
dt_for_day = dt_for_day.astimezone(ZoneInfo(tz))
|
|
94
|
+
if time_rule == "next-day" and 23.0 <= ast_hour_float < 24.0:
|
|
95
|
+
# 不要简单 +1 小时(会跨到次次日);直接把时间“对齐”到当日 00:30
|
|
96
|
+
return dt_for_day.replace(hour=0, minute=30, second=0, microsecond=0)
|
|
97
|
+
if time_rule == "prev-day" and 0.0 <= ast_hour_float < 1.0:
|
|
98
|
+
prev = dt_for_day - timedelta(days=1)
|
|
99
|
+
return prev.replace(hour=23, minute=30, second=0, microsecond=0)
|
|
100
|
+
return dt_for_day
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _timezone_name(dt: datetime) -> str:
|
|
104
|
+
tz_name = getattr(dt.tzinfo, "key", None)
|
|
105
|
+
if not tz_name:
|
|
106
|
+
raise ValueError("BirthInput.datetime must carry an IANA ZoneInfo timezone")
|
|
107
|
+
return tz_name
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def resolve_calendar(dt: datetime, longitude: float | None, latitude: float | None,
|
|
111
|
+
rules: CalendarRules) -> CalendarInfo:
|
|
112
|
+
"""Compute bazi + chart lunar date from an aware civil datetime.
|
|
113
|
+
|
|
114
|
+
With ``longitude``/``latitude`` the civil time is first converted to true
|
|
115
|
+
solar time (requires the ``[solar]`` extra). Without them the datetime is
|
|
116
|
+
used as-is — no longitude or DST assumptions.
|
|
117
|
+
"""
|
|
118
|
+
if dt.tzinfo is None or dt.utcoffset() is None:
|
|
119
|
+
raise ValueError("BirthInput.datetime must be timezone-aware")
|
|
120
|
+
tz = _timezone_name(dt)
|
|
121
|
+
if longitude is not None and latitude is not None:
|
|
122
|
+
from .solar_time import resolve_true_solar_time
|
|
123
|
+
|
|
124
|
+
dt_ast = resolve_true_solar_time(dt, lat=latitude, lon=longitude, tz=tz)
|
|
125
|
+
else:
|
|
126
|
+
dt_ast = dt.astimezone(ZoneInfo(tz))
|
|
127
|
+
h_ast = dt_ast.hour + dt_ast.minute / 60.0 + dt_ast.second / 3600.0
|
|
128
|
+
|
|
129
|
+
from lunar_python import Solar
|
|
130
|
+
|
|
131
|
+
dt_for_day = apply_day_switch(dt_ast, h_ast, tz, day_rule=rules.day_rule)
|
|
132
|
+
dt_for_bazi = apply_time_switch(dt_for_day, h_ast, tz, time_rule=rules.time_rule)
|
|
133
|
+
solar_obj = Solar.fromYmdHms(
|
|
134
|
+
dt_for_bazi.year, dt_for_bazi.month, dt_for_bazi.day,
|
|
135
|
+
dt_for_bazi.hour, dt_for_bazi.minute, dt_for_bazi.second,
|
|
136
|
+
)
|
|
137
|
+
ec = solar_obj.getLunar().getEightChar()
|
|
138
|
+
|
|
139
|
+
# 紫微使用实际排盘时刻的农历日期,不能继承八字日柱的子初换日。
|
|
140
|
+
chart_lunar = Solar.fromYmdHms(
|
|
141
|
+
dt_ast.year, dt_ast.month, dt_ast.day,
|
|
142
|
+
dt_ast.hour, dt_ast.minute, dt_ast.second,
|
|
143
|
+
).getLunar()
|
|
144
|
+
lunar_year = chart_lunar.getYear()
|
|
145
|
+
lunar_month = abs(chart_lunar.getMonth()) # leap months come back negative
|
|
146
|
+
lunar_day = chart_lunar.getDay()
|
|
147
|
+
# 农历日期不能塞进公历 datetime:二月廿九/三十在公历二月不存在。只拼字符串。
|
|
148
|
+
lunar_date_str = (
|
|
149
|
+
f"{lunar_year:04d}-{lunar_month:02d}-{lunar_day:02d} "
|
|
150
|
+
f"{dt_ast.hour:02d}:{dt_ast.minute:02d}:{dt_ast.second:02d}"
|
|
151
|
+
)
|
|
152
|
+
return CalendarInfo(
|
|
153
|
+
bazi=f"{ec.getYear()}{ec.getMonth()}{ec.getDay()}{ec.getTime()}",
|
|
154
|
+
lunar_date_str=lunar_date_str,
|
|
155
|
+
true_solar_time=dt_ast,
|
|
156
|
+
timezone=tz,
|
|
157
|
+
day_rule=rules.day_rule,
|
|
158
|
+
time_rule=rules.time_rule,
|
|
159
|
+
civil_datetime=dt,
|
|
160
|
+
)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"甲子": "金",
|
|
3
|
+
"乙丑": "金",
|
|
4
|
+
"丙寅": "火",
|
|
5
|
+
"丁卯": "火",
|
|
6
|
+
"戊辰": "木",
|
|
7
|
+
"己巳": "木",
|
|
8
|
+
"庚午": "土",
|
|
9
|
+
"辛未": "土",
|
|
10
|
+
"壬申": "金",
|
|
11
|
+
"癸酉": "金",
|
|
12
|
+
"甲戌": "火",
|
|
13
|
+
"乙亥": "火",
|
|
14
|
+
"丙子": "水",
|
|
15
|
+
"丁丑": "水",
|
|
16
|
+
"戊寅": "土",
|
|
17
|
+
"己卯": "土",
|
|
18
|
+
"庚辰": "金",
|
|
19
|
+
"辛巳": "金",
|
|
20
|
+
"壬午": "木",
|
|
21
|
+
"癸未": "木",
|
|
22
|
+
"甲申": "水",
|
|
23
|
+
"乙酉": "水",
|
|
24
|
+
"丙戌": "土",
|
|
25
|
+
"丁亥": "土",
|
|
26
|
+
"戊子": "火",
|
|
27
|
+
"己丑": "火",
|
|
28
|
+
"庚寅": "木",
|
|
29
|
+
"辛卯": "木",
|
|
30
|
+
"壬辰": "水",
|
|
31
|
+
"癸巳": "水",
|
|
32
|
+
"甲午": "金",
|
|
33
|
+
"乙未": "金",
|
|
34
|
+
"丙申": "火",
|
|
35
|
+
"丁酉": "火",
|
|
36
|
+
"戊戌": "木",
|
|
37
|
+
"己亥": "木",
|
|
38
|
+
"庚子": "土",
|
|
39
|
+
"辛丑": "土",
|
|
40
|
+
"壬寅": "金",
|
|
41
|
+
"癸卯": "金",
|
|
42
|
+
"甲辰": "火",
|
|
43
|
+
"乙巳": "火",
|
|
44
|
+
"丙午": "水",
|
|
45
|
+
"丁未": "水",
|
|
46
|
+
"戊申": "土",
|
|
47
|
+
"己酉": "土",
|
|
48
|
+
"庚戌": "金",
|
|
49
|
+
"辛亥": "金",
|
|
50
|
+
"壬子": "木",
|
|
51
|
+
"癸丑": "木",
|
|
52
|
+
"甲寅": "水",
|
|
53
|
+
"乙卯": "水",
|
|
54
|
+
"丙辰": "土",
|
|
55
|
+
"丁巳": "土",
|
|
56
|
+
"戊午": "火",
|
|
57
|
+
"己未": "火",
|
|
58
|
+
"庚申": "木",
|
|
59
|
+
"辛酉": "木",
|
|
60
|
+
"壬戌": "水",
|
|
61
|
+
"癸亥": "水"
|
|
62
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
{
|
|
2
|
+
"紫微在子": {
|
|
3
|
+
"子": ["紫微"],
|
|
4
|
+
"丑": [],
|
|
5
|
+
"寅": ["破军"],
|
|
6
|
+
"卯": [],
|
|
7
|
+
"辰": ["天府", "廉贞"],
|
|
8
|
+
"巳": ["太阴"],
|
|
9
|
+
"午": ["贪狼"],
|
|
10
|
+
"未": ["天同", "巨门"],
|
|
11
|
+
"申": ["武曲", "天相"],
|
|
12
|
+
"酉": ["天梁", "太阳"],
|
|
13
|
+
"戌": ["七杀"],
|
|
14
|
+
"亥": ["天机"]
|
|
15
|
+
},
|
|
16
|
+
"紫微在丑": {
|
|
17
|
+
"子": ["天机"],
|
|
18
|
+
"丑": ["紫微", "破军"],
|
|
19
|
+
"寅": [],
|
|
20
|
+
"卯": ["天府"],
|
|
21
|
+
"辰": ["太阴"],
|
|
22
|
+
"巳": ["廉贞","贪狼"],
|
|
23
|
+
"午": ["巨门"],
|
|
24
|
+
"未": ["天相"],
|
|
25
|
+
"申": ["天同", "天梁"],
|
|
26
|
+
"酉": ["武曲", "七杀"],
|
|
27
|
+
"戌": ["太阳"],
|
|
28
|
+
"亥": []
|
|
29
|
+
},
|
|
30
|
+
"紫微在寅": {
|
|
31
|
+
"子": ["破军"],
|
|
32
|
+
"丑": ["天机"],
|
|
33
|
+
"寅": ["紫微", "天府"],
|
|
34
|
+
"卯": ["太阴"],
|
|
35
|
+
"辰": ["贪狼"],
|
|
36
|
+
"巳": ["巨门"],
|
|
37
|
+
"午": ["廉贞", "天相"],
|
|
38
|
+
"未": ["天梁"],
|
|
39
|
+
"申": ["七杀"],
|
|
40
|
+
"酉": ["天同"],
|
|
41
|
+
"戌": ["武曲"],
|
|
42
|
+
"亥": ["太阳"]
|
|
43
|
+
},
|
|
44
|
+
"紫微在卯": {
|
|
45
|
+
"子": ["太阳"],
|
|
46
|
+
"丑": ["天府"],
|
|
47
|
+
"寅": ["天机", "太阴"],
|
|
48
|
+
"卯": ["紫微", "贪狼"],
|
|
49
|
+
"辰": ["巨门"],
|
|
50
|
+
"巳": ["天相"],
|
|
51
|
+
"午": ["天梁"],
|
|
52
|
+
"未": ["廉贞", "七杀"],
|
|
53
|
+
"申": [],
|
|
54
|
+
"酉": [],
|
|
55
|
+
"戌": ["天同"],
|
|
56
|
+
"亥": ["武曲", "破军"]
|
|
57
|
+
},
|
|
58
|
+
"紫微在辰": {
|
|
59
|
+
"子": ["武曲", "天府"],
|
|
60
|
+
"丑": ["太阳", "太阴"],
|
|
61
|
+
"寅": ["贪狼"],
|
|
62
|
+
"卯": ["天机", "巨门"],
|
|
63
|
+
"辰": ["紫微", "天相"],
|
|
64
|
+
"巳": ["天梁"],
|
|
65
|
+
"午": ["七杀"],
|
|
66
|
+
"未": [],
|
|
67
|
+
"申": ["廉贞"],
|
|
68
|
+
"酉": [],
|
|
69
|
+
"戌": ["破军"],
|
|
70
|
+
"亥": ["天同"]
|
|
71
|
+
},
|
|
72
|
+
"紫微在巳": {
|
|
73
|
+
"子": ["天同", "太阴"],
|
|
74
|
+
"丑": ["武曲", "贪狼"],
|
|
75
|
+
"寅": ["巨门", "太阳"],
|
|
76
|
+
"卯": ["天相"],
|
|
77
|
+
"辰": ["天机", "天梁"],
|
|
78
|
+
"巳": ["紫微", "七杀"],
|
|
79
|
+
"午": [],
|
|
80
|
+
"未": [],
|
|
81
|
+
"申": [],
|
|
82
|
+
"酉": ["廉贞", "破军"],
|
|
83
|
+
"戌": [],
|
|
84
|
+
"亥": ["天府"]
|
|
85
|
+
},
|
|
86
|
+
"紫微在午": {
|
|
87
|
+
"子": ["贪狼"],
|
|
88
|
+
"丑": ["天同","巨门"],
|
|
89
|
+
"寅": ["武曲","天相"],
|
|
90
|
+
"卯": ["天梁","太阳"],
|
|
91
|
+
"辰": ["七杀"],
|
|
92
|
+
"巳": ["天机"],
|
|
93
|
+
"午": ["紫微"],
|
|
94
|
+
"未": [],
|
|
95
|
+
"申": ["破军"],
|
|
96
|
+
"酉": [],
|
|
97
|
+
"戌": ["天府","廉贞"],
|
|
98
|
+
"亥": ["太阴"]
|
|
99
|
+
},
|
|
100
|
+
"紫微在未": {
|
|
101
|
+
"子": ["巨门"],
|
|
102
|
+
"丑": ["天相"],
|
|
103
|
+
"寅": ["天同", "天梁"],
|
|
104
|
+
"卯": ["武曲", "七杀"],
|
|
105
|
+
"辰": ["太阳"],
|
|
106
|
+
"巳": [],
|
|
107
|
+
"午": ["天机"],
|
|
108
|
+
"未": ["紫微", "破军"],
|
|
109
|
+
"申": [],
|
|
110
|
+
"酉": ["天府"],
|
|
111
|
+
"戌": ["太阴"],
|
|
112
|
+
"亥": ["廉贞", "贪狼"]
|
|
113
|
+
},
|
|
114
|
+
"紫微在申": {
|
|
115
|
+
"子": ["廉贞", "天相"],
|
|
116
|
+
"丑": ["天梁"],
|
|
117
|
+
"寅": ["七杀"],
|
|
118
|
+
"卯": ["天同"],
|
|
119
|
+
"辰": ["武曲"],
|
|
120
|
+
"巳": ["太阳"],
|
|
121
|
+
"午": ["破军"],
|
|
122
|
+
"未": ["天机"],
|
|
123
|
+
"申": ["紫微", "天府"],
|
|
124
|
+
"酉": ["太阴"],
|
|
125
|
+
"戌": ["贪狼"],
|
|
126
|
+
"亥": ["巨门"]
|
|
127
|
+
},
|
|
128
|
+
"紫微在酉": {
|
|
129
|
+
"子": ["天梁"],
|
|
130
|
+
"丑": ["廉贞", "七杀"],
|
|
131
|
+
"寅": [],
|
|
132
|
+
"卯": [],
|
|
133
|
+
"辰": ["天同"],
|
|
134
|
+
"巳": ["武曲", "破军"],
|
|
135
|
+
"午": ["太阳"],
|
|
136
|
+
"未": ["天府"],
|
|
137
|
+
"申": ["天机", "太阴"],
|
|
138
|
+
"酉": ["紫微", "贪狼"],
|
|
139
|
+
"戌": ["巨门"],
|
|
140
|
+
"亥": ["天相"]
|
|
141
|
+
},
|
|
142
|
+
"紫微在戌": {
|
|
143
|
+
"子": ["七杀"],
|
|
144
|
+
"丑": [],
|
|
145
|
+
"寅": ["廉贞"],
|
|
146
|
+
"卯": [],
|
|
147
|
+
"辰": ["破军"],
|
|
148
|
+
"巳": ["天同"],
|
|
149
|
+
"午": ["武曲", "天府"],
|
|
150
|
+
"未": ["太阳", "太阴"],
|
|
151
|
+
"申": ["贪狼"],
|
|
152
|
+
"酉": ["天机", "巨门"],
|
|
153
|
+
"戌": ["紫微", "天相"],
|
|
154
|
+
"亥": ["天梁"]
|
|
155
|
+
},
|
|
156
|
+
"紫微在亥": {
|
|
157
|
+
"子": [],
|
|
158
|
+
"丑": [],
|
|
159
|
+
"寅": [],
|
|
160
|
+
"卯": ["廉贞", "破军"],
|
|
161
|
+
"辰": [],
|
|
162
|
+
"巳": ["天府"],
|
|
163
|
+
"午": ["天同", "太阴"],
|
|
164
|
+
"未": ["武曲", "贪狼"],
|
|
165
|
+
"申": ["巨门", "太阳"],
|
|
166
|
+
"酉": ["天相"],
|
|
167
|
+
"戌": ["天机", "天梁"],
|
|
168
|
+
"亥": ["紫微", "七杀"]
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"甲": {
|
|
3
|
+
"廉贞": "禄",
|
|
4
|
+
"破军": "权",
|
|
5
|
+
"武曲": "科",
|
|
6
|
+
"太阳": "忌"
|
|
7
|
+
},
|
|
8
|
+
"乙": {
|
|
9
|
+
"天机": "禄",
|
|
10
|
+
"天梁": "权",
|
|
11
|
+
"紫微": "科",
|
|
12
|
+
"太阴": "忌"
|
|
13
|
+
},
|
|
14
|
+
"丙": {
|
|
15
|
+
"天同": "禄",
|
|
16
|
+
"天机": "权",
|
|
17
|
+
"文昌": "科",
|
|
18
|
+
"廉贞": "忌"
|
|
19
|
+
},
|
|
20
|
+
"丁": {
|
|
21
|
+
"太阴": "禄",
|
|
22
|
+
"天同": "权",
|
|
23
|
+
"天机": "科",
|
|
24
|
+
"巨门": "忌"
|
|
25
|
+
},
|
|
26
|
+
"戊": {
|
|
27
|
+
"贪狼": "禄",
|
|
28
|
+
"太阴": "权",
|
|
29
|
+
"右弼": "科",
|
|
30
|
+
"天机": "忌"
|
|
31
|
+
},
|
|
32
|
+
"己": {
|
|
33
|
+
"武曲": "禄",
|
|
34
|
+
"贪狼": "权",
|
|
35
|
+
"天梁": "科",
|
|
36
|
+
"文曲": "忌"
|
|
37
|
+
},
|
|
38
|
+
"庚": {
|
|
39
|
+
"太阳": "禄",
|
|
40
|
+
"武曲": "权",
|
|
41
|
+
"太阴": "科",
|
|
42
|
+
"天同": "忌"
|
|
43
|
+
},
|
|
44
|
+
"辛": {
|
|
45
|
+
"巨门": "禄",
|
|
46
|
+
"太阳": "权",
|
|
47
|
+
"文曲": "科",
|
|
48
|
+
"文昌": "忌"
|
|
49
|
+
},
|
|
50
|
+
"壬": {
|
|
51
|
+
"天梁": "禄",
|
|
52
|
+
"紫微": "权",
|
|
53
|
+
"左辅": "科",
|
|
54
|
+
"武曲": "忌"
|
|
55
|
+
},
|
|
56
|
+
"癸": {
|
|
57
|
+
"破军": "禄",
|
|
58
|
+
"巨门": "权",
|
|
59
|
+
"太阴": "科",
|
|
60
|
+
"贪狼": "忌"
|
|
61
|
+
}
|
|
62
|
+
}
|