定位中...
V24.FullInfo
局数: --
月将: --
值符: --
值使: --
黄经: --
斗柄: --
真太阳时差: --
VSOP87
--
packages = ["./lunar_python-1.4.8-py3-none-any.whl"]
import datetime
import math
import js
import json
from lunar_python import Lunar, Solar
# --- 1. 基础数据 ---
GAN = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"]
ZHI = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"]
STARS = ['', '天蓬', '天芮', '天冲', '天辅', '天禽', '天心', '天柱', '天任', '天英']
DOORS = ['', '休门', '死门', '伤门', '杜门', '', '开门', '惊门', '生门', '景门']
GODS = ['值符', '螣蛇', '太阴', '六合', '白虎', '玄武', '九地', '九天']
TERM_NAMES = ['冬至','小寒','大寒','立春','雨水','惊蛰','春分','清明','谷雨','立夏','小满','芒种','夏至','小暑','大暑','立秋','处暑','白露','秋分','寒露','霜降','立冬','小雪','大雪']
JU_MAP = {
'冬至':[1,7,4], '小寒':[2,8,5], '大寒':[3,9,6], '立春':[8,5,2], '雨水':[9,6,3], '惊蛰':[1,7,4],
'春分':[3,9,6], '清明':[4,1,7], '谷雨':[5,2,8], '立夏':[4,1,7], '小满':[5,2,8], '芒种':[6,3,9],
'夏至':[9,3,6], '小暑':[8,2,5], '大暑':[7,1,4], '立秋':[2,5,8], '处暑':[1,4,7], '白露':[9,3,6],
'秋分':[7,1,4], '寒露':[6,9,3], '霜降':[5,8,2], '立冬':[6,9,3], '小雪':[5,8,2], '大雪':[4,7,1]
}
# --- 2. 天文算法 (VSOP87) ---
class PreciseAstronomy:
@staticmethod
def get_lon(dt):
y, m, d = dt.year, dt.month, dt.day
h = dt.hour + dt.minute/60.0 + dt.second/3600.0
if m <= 2: y -= 1; m += 12
jd = int(365.25 * (y + 4716)) + int(30.6001 * (m + 1)) + d + h/24.0 + 2 - int(y/100) + int(int(y/100)/4) - 1524.5
tau = (jd - 2451545.0) / 365250.0
L0 = 175347046.0 + 3341656.0 * math.cos(4.6692568 + 6283.07585 * tau)
L = (L0 * 1e-8 + math.radians(280.46646 + 36000.76983 * tau))
return (math.degrees(L) + 0.0) % 360.0
class QimenEngine:
def run(self, year, month, day, hour, minute, lat, lon):
solar = Solar.fromYmdHms(year, month, day, hour, minute, 0)
lunar = solar.getLunar()
gz = lunar.getEightChar()
dt_obj = datetime.datetime(year, month, day, hour, minute)
doy = dt_obj.timetuple().tm_yday
b = (2 * math.pi / 365.24) * (doy - 81)
eot = 9.87 * math.sin(2*b) - 7.53 * math.cos(b) - 1.5 * math.sin(b)
tst = dt_obj + datetime.timedelta(minutes=eot + (lon-120)*4)
slon = PreciseAstronomy.get_lon(tst)
dubhe = (slon + 90.0) % 360.0
jiang_idx = (11 - int((slon + 30)/30)) % 12
yue_jiang = ZHI[jiang_idx]
current_jieqi = lunar.getPrevJieQi(True)
term_name = current_jieqi.getName()
day_gan_idx = GAN.index(gz.getDayGan())
day_idx = -1
for i in range(60):
if GAN[i%10] == gz.getDayGan() and ZHI[i%12] == gz.getDayZhi():
day_idx = i
break
diff = day_gan_idx % 5
futou_idx = (day_idx - diff) % 60
futou_zhi = ZHI[futou_idx % 12]
yuan = 2
if futou_zhi in ['子', '午', '卯', '酉']: yuan = 0
elif futou_zhi in ['寅', '申', '巳', '亥']: yuan = 1
ju = JU_MAP.get(term_name, [1,1,1])[yuan]
yang_terms = ['冬至','小寒','大寒','立春','雨水','惊蛰','春分','清明','谷雨','立夏','小满','芒种']
is_yang = term_name in yang_terms
real_yang = is_yang if lat >= 0 else not is_yang
# 地盘
stems = ['戊', '己', '庚', '辛', '壬', '癸', '丁', '丙', '乙']
dp = {}
for i, s in enumerate(stems):
pos = ((ju - 1 + i)%9)+1 if real_yang else ((ju - 1 - i)%9)+1
if pos == 0: pos = 9
dp[pos] = s
h_gan = gz.getTimeGan()
h_zhi = gz.getTimeZhi()
h_zhi_idx = ZHI.index(h_zhi)
g_i = GAN.index(h_gan)
head_zhi_idx = (h_zhi_idx - g_i) % 12
xun_map = {0:'戊', 10:'己', 8:'庚', 6:'辛', 4:'壬', 2:'癸'}
xun_gan = xun_map.get(head_zhi_idx, '戊')
pos_xun = 1
for p, s in dp.items():
if s == xun_gan: pos_xun = p; break
zhifu_star = STARS[pos_xun]
zhishi_door = DOORS[pos_xun] if pos_xun != 5 else "死门"
if pos_xun == 5: pos_xun = 2
target_stem = h_gan
if h_gan == '甲': target_stem = xun_gan
pos_sky_dest = 1
for p, s in dp.items():
if s == target_stem: pos_sky_dest = p; break
path = [1,8,3,4,9,2,7,6]
full_grid = {}
for i in range(1, 10):
full_grid[i] = {"stem_d": dp.get(i, ""), "stem_t": "", "star": "", "door": "", "god": ""}
# 八神
try: start_idx = path.index(pos_sky_dest)
except: start_idx = 0
for i in range(8):
g_idx = i
if real_yang: p_idx = (start_idx + i) % 8
else: p_idx = (start_idx - i) % 8
full_grid[path[p_idx]]["god"] = GODS[g_idx]
# 星 & 干
target_star_name = zhifu_star
if target_star_name == "天禽": target_star_name = "天芮"
base_stars = ["天蓬","天任","天冲","天辅","天英","天芮","天柱","天心"]
try: s_idx = base_stars.index(target_star_name)
except: s_idx = 0
for i in range(8):
curr_star = base_stars[(s_idx + i) % 8]
curr_palace = path[(start_idx + i) % 8]
full_grid[curr_palace]["star"] = curr_star
if curr_star == "天芮": full_grid[curr_palace]["star"] = "天芮(禽)"
orig_p = { "天蓬":1, "天任":8, "天冲":3, "天辅":4, "天英":9, "天芮":2, "天柱":7, "天心":6 }.get(curr_star, 1)
full_grid[curr_palace]["stem_t"] = dp.get(orig_p, "")
# 门
step = (h_zhi_idx - head_zhi_idx) % 12
try:
door_start_palace = pos_xun
if door_start_palace == 5: door_start_palace = 2
d_start_idx = path.index(door_start_palace)
except: d_start_idx = 0
fly_step = step if real_yang else -step
dest_idx = (d_start_idx + fly_step) % 8
base_doors = ["休门","生门","伤门","杜门","景门","死门","惊门","开门"]
try: bd_idx = base_doors.index(zhishi_door)
except: bd_idx = 5
for i in range(8):
curr_door = base_doors[(bd_idx + i) % 8]
curr_p = path[(dest_idx + i) % 8]
full_grid[curr_p]["door"] = curr_door
return json.dumps({
"lunar": f"{gz.getYear()}年 {lunar.toString()}",
"ganzhi": f"{gz.getYear()} {gz.getMonth()} {gz.getDay()} {gz.getTime()}",
"jieqi": f"{term_name} (拆补法)",
"kongwang": f"日空 {lunar.getDayXunKong()}",
"info": {
"lon": f"{slon:.2f}°",
"dubhe": f"{dubhe:.2f}°",
"eot": f"{eot + (lon-120)*4:.1f}m",
"coords": f"{lat:.1f}, {lon:.1f}"
},
"ju": {
"name": f"{'阳' if real_yang else '阴'}遁{ju}局 {['上','中','下'][yuan]}元",
"zhifu": zhifu_star,
"zhishi": zhishi_door,
"jiang": yue_jiang
},
"grid": full_grid
})
engine = QimenEngine()
def python_entry(y, m, d, h, minute, lat, lon):
try:
res = engine.run(int(y), int(m), int(d), int(h), int(minute), float(lat), float(lon))
js.render_result(res)
except Exception as e:
js.alert("Python Error: " + str(e))
js.window.python_entry = python_entry
js.window.init_complete()