Spaces:
Running
Running
th commited on
Commit ·
badbcb4
1
Parent(s): a30fb56
fix: 晚子时排盘错误 + async事件循环阻塞 + 输入校验
Browse filesP0 晚子时bug: hour24ToTimeIndex把23点映射成0(早子时),iztro时辰索引
实为0~12(12=晚子时),导致23:00-23:59出生用户日柱错一天、整盘错误
(实测1990-06-15 23:30女: 错盘命宫破军 → 正确太阳)。改为23点返回12,
由iztro自行处理跨日。新增test_late_zi_hour.js回归测试。
P1: 四个排盘端点从async def改为def(FastAPI线程池),消除同步
subprocess.run阻塞uvicorn事件循环导致的全服务卡顿。
小项: 排盘subprocess调用抽成run_ziwei_calculation helper(消除×4重复);
gender用Literal['男','女']校验; target_year默认值改为动态当前年;
CORS allow_credentials关闭(与通配origins组合无效)。
🦊 Generated with Sisi
- app.py +47 -108
- test_late_zi_hour.js +71 -0
- ziwei_service.js +5 -3
app.py
CHANGED
|
@@ -8,7 +8,7 @@ Updated: 2026-02-03 (🌟 v4.0 巴纳姆效果+六亲分析+10步批命流程!
|
|
| 8 |
from fastapi import FastAPI, HTTPException
|
| 9 |
from fastapi.middleware.cors import CORSMiddleware
|
| 10 |
from pydantic import BaseModel, Field
|
| 11 |
-
from typing import Optional, Dict, Any
|
| 12 |
import subprocess
|
| 13 |
import json
|
| 14 |
from datetime import datetime
|
|
@@ -29,7 +29,7 @@ app = FastAPI(
|
|
| 29 |
app.add_middleware(
|
| 30 |
CORSMiddleware,
|
| 31 |
allow_origins=["*"],
|
| 32 |
-
allow_credentials=
|
| 33 |
allow_methods=["*"],
|
| 34 |
allow_headers=["*"],
|
| 35 |
)
|
|
@@ -39,11 +39,43 @@ class ZiweiRequest(BaseModel):
|
|
| 39 |
"""紫微斗数计算请求"""
|
| 40 |
birth_date: str = Field(..., description="出生日期 YYYY-MM-DD", example="2000-01-01")
|
| 41 |
birth_time: str = Field(..., description="出生时间 HH:MM", example="14:30")
|
| 42 |
-
gender:
|
| 43 |
is_leap_month: bool = Field(default=False, description="是否闰月")
|
| 44 |
fix_leap: bool = Field(default=True, description="是否修正闰月")
|
| 45 |
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
class ZiweiResponse(BaseModel):
|
| 48 |
"""紫微斗数计算响应"""
|
| 49 |
status: str
|
|
@@ -155,7 +187,7 @@ def root():
|
|
| 155 |
|
| 156 |
|
| 157 |
@app.post("/calculate-ziwei", response_model=ZiweiResponse)
|
| 158 |
-
|
| 159 |
"""
|
| 160 |
计算紫微斗数命盘
|
| 161 |
|
|
@@ -163,32 +195,7 @@ async def calculate_ziwei(request: ZiweiRequest):
|
|
| 163 |
完整的紫微斗数排盘与AI智能分析
|
| 164 |
"""
|
| 165 |
try:
|
| 166 |
-
|
| 167 |
-
input_data = {
|
| 168 |
-
"birth_date": request.birth_date,
|
| 169 |
-
"birth_time": request.birth_time,
|
| 170 |
-
"gender": request.gender,
|
| 171 |
-
"is_leap_month": request.is_leap_month,
|
| 172 |
-
"fix_leap": request.fix_leap
|
| 173 |
-
}
|
| 174 |
-
|
| 175 |
-
# 调用Node.js脚本
|
| 176 |
-
result = subprocess.run(
|
| 177 |
-
['node', 'ziwei_service.js'],
|
| 178 |
-
input=json.dumps(input_data),
|
| 179 |
-
capture_output=True,
|
| 180 |
-
text=True,
|
| 181 |
-
timeout=10
|
| 182 |
-
)
|
| 183 |
-
|
| 184 |
-
if result.returncode != 0:
|
| 185 |
-
raise HTTPException(
|
| 186 |
-
status_code=500,
|
| 187 |
-
detail=f"Ziwei calculation error: {result.stderr}"
|
| 188 |
-
)
|
| 189 |
-
|
| 190 |
-
# 解析结果
|
| 191 |
-
ziwei_data = json.loads(result.stdout)
|
| 192 |
|
| 193 |
return ZiweiResponse(
|
| 194 |
status="success",
|
|
@@ -204,7 +211,7 @@ async def calculate_ziwei(request: ZiweiRequest):
|
|
| 204 |
|
| 205 |
|
| 206 |
@app.post("/analyze-ziwei-enhanced", response_model=ZiweiResponse)
|
| 207 |
-
|
| 208 |
"""
|
| 209 |
增强版紫微斗数分析 - 包含四化飞星和AI解读
|
| 210 |
|
|
@@ -213,31 +220,7 @@ async def analyze_ziwei_enhanced(request: ZiweiRequest):
|
|
| 213 |
"""
|
| 214 |
try:
|
| 215 |
# 1. 首先调用基础排盘功能
|
| 216 |
-
|
| 217 |
-
"birth_date": request.birth_date,
|
| 218 |
-
"birth_time": request.birth_time,
|
| 219 |
-
"gender": request.gender,
|
| 220 |
-
"is_leap_month": request.is_leap_month,
|
| 221 |
-
"fix_leap": request.fix_leap
|
| 222 |
-
}
|
| 223 |
-
|
| 224 |
-
# 调用Node.js脚本获取基础命盘
|
| 225 |
-
result = subprocess.run(
|
| 226 |
-
['node', 'ziwei_service.js'],
|
| 227 |
-
input=json.dumps(input_data),
|
| 228 |
-
capture_output=True,
|
| 229 |
-
text=True,
|
| 230 |
-
timeout=10
|
| 231 |
-
)
|
| 232 |
-
|
| 233 |
-
if result.returncode != 0:
|
| 234 |
-
raise HTTPException(
|
| 235 |
-
status_code=500,
|
| 236 |
-
detail=f"Ziwei calculation error: {result.stderr}"
|
| 237 |
-
)
|
| 238 |
-
|
| 239 |
-
# 解析基础命盘数据
|
| 240 |
-
ziwei_chart = json.loads(result.stdout)
|
| 241 |
|
| 242 |
# 2. 四化飞星分析
|
| 243 |
sihua_analyzer = SihuaAnalyzer(ziwei_chart)
|
|
@@ -276,7 +259,7 @@ async def analyze_ziwei_enhanced(request: ZiweiRequest):
|
|
| 276 |
|
| 277 |
|
| 278 |
@app.post("/analyze-ziwei-knowledge-enhanced", response_model=ZiweiResponse)
|
| 279 |
-
|
| 280 |
"""
|
| 281 |
知识库增强版紫微斗数分析 v4.0 🔮✨💕
|
| 282 |
|
|
@@ -299,29 +282,7 @@ async def analyze_ziwei_knowledge_enhanced(request: ZiweiRequest):
|
|
| 299 |
"""
|
| 300 |
try:
|
| 301 |
# 1. 基础排盘
|
| 302 |
-
|
| 303 |
-
"birth_date": request.birth_date,
|
| 304 |
-
"birth_time": request.birth_time,
|
| 305 |
-
"gender": request.gender,
|
| 306 |
-
"is_leap_month": request.is_leap_month,
|
| 307 |
-
"fix_leap": request.fix_leap
|
| 308 |
-
}
|
| 309 |
-
|
| 310 |
-
result = subprocess.run(
|
| 311 |
-
['node', 'ziwei_service.js'],
|
| 312 |
-
input=json.dumps(input_data),
|
| 313 |
-
capture_output=True,
|
| 314 |
-
text=True,
|
| 315 |
-
timeout=10
|
| 316 |
-
)
|
| 317 |
-
|
| 318 |
-
if result.returncode != 0:
|
| 319 |
-
raise HTTPException(
|
| 320 |
-
status_code=500,
|
| 321 |
-
detail=f"Ziwei calculation error: {result.stderr}"
|
| 322 |
-
)
|
| 323 |
-
|
| 324 |
-
ziwei_chart = json.loads(result.stdout)
|
| 325 |
|
| 326 |
# 2. 四化飞星分析
|
| 327 |
sihua_analyzer = SihuaAnalyzer(ziwei_chart)
|
|
@@ -400,14 +361,14 @@ async def analyze_ziwei_knowledge_enhanced(request: ZiweiRequest):
|
|
| 400 |
|
| 401 |
|
| 402 |
@app.post("/analyze-ziwei-v4", response_model=ZiweiResponse)
|
| 403 |
-
|
| 404 |
"""
|
| 405 |
v4.0 巴纳姆温暖版 - 别名端点
|
| 406 |
|
| 407 |
等同于 /analyze-ziwei-knowledge-enhanced (已升级到v4.0)
|
| 408 |
保留此端点是为了向后兼容
|
| 409 |
"""
|
| 410 |
-
return
|
| 411 |
|
| 412 |
|
| 413 |
@app.get("/debug/modules")
|
|
@@ -459,14 +420,14 @@ class MonthlyFortuneRequest(BaseModel):
|
|
| 459 |
"""流月运势请求"""
|
| 460 |
birth_date: str = Field(..., description="出生日期 YYYY-MM-DD", example="2000-01-01")
|
| 461 |
birth_time: str = Field(..., description="出生时间 HH:MM", example="14:30")
|
| 462 |
-
gender:
|
| 463 |
is_leap_month: bool = Field(default=False, description="是否闰月")
|
| 464 |
fix_leap: bool = Field(default=True, description="是否修正闰月")
|
| 465 |
-
target_year: int = Field(
|
| 466 |
|
| 467 |
|
| 468 |
@app.post("/analyze-monthly-fortune", response_model=ZiweiResponse)
|
| 469 |
-
|
| 470 |
"""
|
| 471 |
流月运势预测 v1.0 🌟✨ (NEW!)
|
| 472 |
|
|
@@ -482,29 +443,7 @@ async def analyze_monthly_fortune(request: MonthlyFortuneRequest):
|
|
| 482 |
"""
|
| 483 |
try:
|
| 484 |
# 1. 基础排盘
|
| 485 |
-
|
| 486 |
-
"birth_date": request.birth_date,
|
| 487 |
-
"birth_time": request.birth_time,
|
| 488 |
-
"gender": request.gender,
|
| 489 |
-
"is_leap_month": request.is_leap_month,
|
| 490 |
-
"fix_leap": request.fix_leap
|
| 491 |
-
}
|
| 492 |
-
|
| 493 |
-
result = subprocess.run(
|
| 494 |
-
['node', 'ziwei_service.js'],
|
| 495 |
-
input=json.dumps(input_data),
|
| 496 |
-
capture_output=True,
|
| 497 |
-
text=True,
|
| 498 |
-
timeout=10
|
| 499 |
-
)
|
| 500 |
-
|
| 501 |
-
if result.returncode != 0:
|
| 502 |
-
raise HTTPException(
|
| 503 |
-
status_code=500,
|
| 504 |
-
detail=f"Ziwei calculation error: {result.stderr}"
|
| 505 |
-
)
|
| 506 |
-
|
| 507 |
-
ziwei_chart = json.loads(result.stdout)
|
| 508 |
|
| 509 |
# 2. 流月分析
|
| 510 |
liuyue_analyzer = LiuyueAnalyzer(ziwei_chart)
|
|
|
|
| 8 |
from fastapi import FastAPI, HTTPException
|
| 9 |
from fastapi.middleware.cors import CORSMiddleware
|
| 10 |
from pydantic import BaseModel, Field
|
| 11 |
+
from typing import Literal, Optional, Dict, Any
|
| 12 |
import subprocess
|
| 13 |
import json
|
| 14 |
from datetime import datetime
|
|
|
|
| 29 |
app.add_middleware(
|
| 30 |
CORSMiddleware,
|
| 31 |
allow_origins=["*"],
|
| 32 |
+
allow_credentials=False,
|
| 33 |
allow_methods=["*"],
|
| 34 |
allow_headers=["*"],
|
| 35 |
)
|
|
|
|
| 39 |
"""紫微斗数计算请求"""
|
| 40 |
birth_date: str = Field(..., description="出生日期 YYYY-MM-DD", example="2000-01-01")
|
| 41 |
birth_time: str = Field(..., description="出生时间 HH:MM", example="14:30")
|
| 42 |
+
gender: Literal['男', '女'] = Field(..., description="性别: 男/女", example="男")
|
| 43 |
is_leap_month: bool = Field(default=False, description="是否闰月")
|
| 44 |
fix_leap: bool = Field(default=True, description="是否修正闰月")
|
| 45 |
|
| 46 |
|
| 47 |
+
def run_ziwei_calculation(request: BaseModel) -> Dict[str, Any]:
|
| 48 |
+
"""调用Node.js iztro服务进行基础排盘,返回命盘dict
|
| 49 |
+
|
| 50 |
+
接受ZiweiRequest或MonthlyFortuneRequest(共享排盘字段)。
|
| 51 |
+
统一处理subprocess调用、returncode检查和JSON解析,
|
| 52 |
+
失败时直接抛出HTTPException。
|
| 53 |
+
"""
|
| 54 |
+
input_data = {
|
| 55 |
+
"birth_date": request.birth_date,
|
| 56 |
+
"birth_time": request.birth_time,
|
| 57 |
+
"gender": request.gender,
|
| 58 |
+
"is_leap_month": request.is_leap_month,
|
| 59 |
+
"fix_leap": request.fix_leap
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
result = subprocess.run(
|
| 63 |
+
['node', 'ziwei_service.js'],
|
| 64 |
+
input=json.dumps(input_data),
|
| 65 |
+
capture_output=True,
|
| 66 |
+
text=True,
|
| 67 |
+
timeout=10
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
if result.returncode != 0:
|
| 71 |
+
raise HTTPException(
|
| 72 |
+
status_code=500,
|
| 73 |
+
detail=f"Ziwei calculation error: {result.stderr}"
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
return json.loads(result.stdout)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
class ZiweiResponse(BaseModel):
|
| 80 |
"""紫微斗数计算响应"""
|
| 81 |
status: str
|
|
|
|
| 187 |
|
| 188 |
|
| 189 |
@app.post("/calculate-ziwei", response_model=ZiweiResponse)
|
| 190 |
+
def calculate_ziwei(request: ZiweiRequest):
|
| 191 |
"""
|
| 192 |
计算紫微斗数命盘
|
| 193 |
|
|
|
|
| 195 |
完整的紫微斗数排盘与AI智能分析
|
| 196 |
"""
|
| 197 |
try:
|
| 198 |
+
ziwei_data = run_ziwei_calculation(request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
|
| 200 |
return ZiweiResponse(
|
| 201 |
status="success",
|
|
|
|
| 211 |
|
| 212 |
|
| 213 |
@app.post("/analyze-ziwei-enhanced", response_model=ZiweiResponse)
|
| 214 |
+
def analyze_ziwei_enhanced(request: ZiweiRequest):
|
| 215 |
"""
|
| 216 |
增强版紫微斗数分析 - 包含四化飞星和AI解读
|
| 217 |
|
|
|
|
| 220 |
"""
|
| 221 |
try:
|
| 222 |
# 1. 首先调用基础排盘功能
|
| 223 |
+
ziwei_chart = run_ziwei_calculation(request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
|
| 225 |
# 2. 四化飞星分析
|
| 226 |
sihua_analyzer = SihuaAnalyzer(ziwei_chart)
|
|
|
|
| 259 |
|
| 260 |
|
| 261 |
@app.post("/analyze-ziwei-knowledge-enhanced", response_model=ZiweiResponse)
|
| 262 |
+
def analyze_ziwei_knowledge_enhanced(request: ZiweiRequest):
|
| 263 |
"""
|
| 264 |
知识库增强版紫微斗数分析 v4.0 🔮✨💕
|
| 265 |
|
|
|
|
| 282 |
"""
|
| 283 |
try:
|
| 284 |
# 1. 基础排盘
|
| 285 |
+
ziwei_chart = run_ziwei_calculation(request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
|
| 287 |
# 2. 四化飞星分析
|
| 288 |
sihua_analyzer = SihuaAnalyzer(ziwei_chart)
|
|
|
|
| 361 |
|
| 362 |
|
| 363 |
@app.post("/analyze-ziwei-v4", response_model=ZiweiResponse)
|
| 364 |
+
def analyze_ziwei_v4(request: ZiweiRequest):
|
| 365 |
"""
|
| 366 |
v4.0 巴纳姆温暖版 - 别名端点
|
| 367 |
|
| 368 |
等同于 /analyze-ziwei-knowledge-enhanced (已升级到v4.0)
|
| 369 |
保留此端点是为了向后兼容
|
| 370 |
"""
|
| 371 |
+
return analyze_ziwei_knowledge_enhanced(request)
|
| 372 |
|
| 373 |
|
| 374 |
@app.get("/debug/modules")
|
|
|
|
| 420 |
"""流月运势请求"""
|
| 421 |
birth_date: str = Field(..., description="出生日期 YYYY-MM-DD", example="2000-01-01")
|
| 422 |
birth_time: str = Field(..., description="出生时间 HH:MM", example="14:30")
|
| 423 |
+
gender: Literal['男', '女'] = Field(..., description="性别: 男/女", example="男")
|
| 424 |
is_leap_month: bool = Field(default=False, description="是否闰月")
|
| 425 |
fix_leap: bool = Field(default=True, description="是否修正闰月")
|
| 426 |
+
target_year: int = Field(default_factory=lambda: datetime.now().year, description="目标年份(默认当前年)", example=2026)
|
| 427 |
|
| 428 |
|
| 429 |
@app.post("/analyze-monthly-fortune", response_model=ZiweiResponse)
|
| 430 |
+
def analyze_monthly_fortune(request: MonthlyFortuneRequest):
|
| 431 |
"""
|
| 432 |
流月运势预测 v1.0 🌟✨ (NEW!)
|
| 433 |
|
|
|
|
| 443 |
"""
|
| 444 |
try:
|
| 445 |
# 1. 基础排盘
|
| 446 |
+
ziwei_chart = run_ziwei_calculation(request)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 447 |
|
| 448 |
# 2. 流月分析
|
| 449 |
liuyue_analyzer = LiuyueAnalyzer(ziwei_chart)
|
test_late_zi_hour.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* 晚子时(23:00-23:59)排盘回归测试
|
| 3 |
+
*
|
| 4 |
+
* iztro 时辰索引为 0~12,其中 12 = 晚子时(23:00-00:00)。
|
| 5 |
+
* bug: hour24ToTimeIndex 曾把 23 点映射成 0(早子时),
|
| 6 |
+
* 导致 23:00-23:59 出生的用户日柱/命盘全部错误。
|
| 7 |
+
*
|
| 8 |
+
* 用例(1990-06-15 女):
|
| 9 |
+
* 23:30 出生 → 晚子时 index 12 → 日柱 壬子,命宫主星 太阳
|
| 10 |
+
* 00:30 出生 → 早子时 index 0 → 日柱 辛亥,命宫主星 破军
|
| 11 |
+
*
|
| 12 |
+
* 运行: node test_late_zi_hour.js
|
| 13 |
+
*/
|
| 14 |
+
|
| 15 |
+
const { spawnSync } = require('child_process');
|
| 16 |
+
|
| 17 |
+
function runService(birthTime) {
|
| 18 |
+
const input = JSON.stringify({
|
| 19 |
+
birth_date: '1990-06-15',
|
| 20 |
+
birth_time: birthTime,
|
| 21 |
+
gender: '女',
|
| 22 |
+
is_leap_month: false,
|
| 23 |
+
fix_leap: true,
|
| 24 |
+
});
|
| 25 |
+
const result = spawnSync('node', ['ziwei_service.js'], {
|
| 26 |
+
input,
|
| 27 |
+
encoding: 'utf-8',
|
| 28 |
+
cwd: __dirname,
|
| 29 |
+
timeout: 15000,
|
| 30 |
+
});
|
| 31 |
+
if (result.status !== 0) {
|
| 32 |
+
throw new Error(`ziwei_service.js failed: ${result.stderr}`);
|
| 33 |
+
}
|
| 34 |
+
return JSON.parse(result.stdout);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
function pick(data) {
|
| 38 |
+
const mingGong = data.palaces.find((p) => p.name === '命宫');
|
| 39 |
+
return {
|
| 40 |
+
day_pillar: data.chart.chinese_date.split(' ')[2],
|
| 41 |
+
ming_gong_stars: mingGong.major_stars.map((s) => s.name),
|
| 42 |
+
};
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
let failures = 0;
|
| 46 |
+
|
| 47 |
+
function check(label, actual, expected) {
|
| 48 |
+
const ok = JSON.stringify(actual) === JSON.stringify(expected);
|
| 49 |
+
console.log(`${ok ? '✅ PASS' : '❌ FAIL'} ${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
|
| 50 |
+
if (!ok) failures++;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
// 用例1: 23:30 出生 → 晚子时(index 12),日柱应为次日壬子,命宫主星太阳
|
| 54 |
+
const lateZi = pick(runService('23:30'));
|
| 55 |
+
check('23:30 日柱(晚子时)', lateZi.day_pillar, '壬子');
|
| 56 |
+
check('23:30 命宫主星', lateZi.ming_gong_stars, ['太阳']);
|
| 57 |
+
|
| 58 |
+
// 用例2: 00:30 出生 → 早子时(index 0),日柱辛亥,命宫主星破军(保持不变)
|
| 59 |
+
const earlyZi = pick(runService('00:30'));
|
| 60 |
+
check('00:30 日柱(早子时)', earlyZi.day_pillar, '辛亥');
|
| 61 |
+
check('00:30 命宫主星', earlyZi.ming_gong_stars, ['破军']);
|
| 62 |
+
|
| 63 |
+
// 用例3: 非子时时辰不受影响 — 14:30 未时
|
| 64 |
+
const weiShi = runService('14:30');
|
| 65 |
+
check('14:30 时辰索引(未时)', weiShi.chart.earthly_branch_index, 7);
|
| 66 |
+
|
| 67 |
+
if (failures > 0) {
|
| 68 |
+
console.error(`\n${failures} test(s) failed`);
|
| 69 |
+
process.exit(1);
|
| 70 |
+
}
|
| 71 |
+
console.log('\nAll tests passed 🦊');
|
ziwei_service.js
CHANGED
|
@@ -7,13 +7,15 @@ const iztro = require('iztro');
|
|
| 7 |
const astro = iztro.astro;
|
| 8 |
|
| 9 |
/**
|
| 10 |
-
* 将24小时制转换为
|
| 11 |
-
* 子(0):
|
| 12 |
* 辰(4): 07-09, 巳(5): 09-11, 午(6): 11-13, 未(7): 13-15
|
| 13 |
* 申(8): 15-17, 酉(9): 17-19, 戌(10): 19-21, 亥(11): 21-23
|
|
|
|
| 14 |
*/
|
| 15 |
function hour24ToTimeIndex(hour24) {
|
| 16 |
-
if (hour24 >= 23
|
|
|
|
| 17 |
if (hour24 >= 1 && hour24 < 3) return 1; // 丑时
|
| 18 |
if (hour24 >= 3 && hour24 < 5) return 2; // 寅时
|
| 19 |
if (hour24 >= 5 && hour24 < 7) return 3; // 卯时
|
|
|
|
| 7 |
const astro = iztro.astro;
|
| 8 |
|
| 9 |
/**
|
| 10 |
+
* 将24小时制转换为iztro时辰索引 (0-12)
|
| 11 |
+
* 早子(0): 00-01, 丑(1): 01-03, 寅(2): 03-05, 卯(3): 05-07
|
| 12 |
* 辰(4): 07-09, 巳(5): 09-11, 午(6): 11-13, 未(7): 13-15
|
| 13 |
* 申(8): 15-17, 酉(9): 17-19, 戌(10): 19-21, 亥(11): 21-23
|
| 14 |
+
* 晚子(12): 23-00 — iztro用12区分晚子时并自行处理跨日日柱
|
| 15 |
*/
|
| 16 |
function hour24ToTimeIndex(hour24) {
|
| 17 |
+
if (hour24 >= 23) return 12; // 晚子时
|
| 18 |
+
if (hour24 < 1) return 0; // 早子时
|
| 19 |
if (hour24 >= 1 && hour24 < 3) return 1; // 丑时
|
| 20 |
if (hour24 >= 3 && hour24 < 5) return 2; // 寅时
|
| 21 |
if (hour24 >= 5 && hour24 < 7) return 3; // 卯时
|