@gracefullight/saju 1.2.0 → 1.3.1
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.
- package/README.ko.md +8 -4
- package/README.md +8 -4
- package/dist/__tests__/date-fns-adapter.test.js +11 -0
- package/dist/__tests__/relations.test.js +1 -0
- package/dist/__tests__/saju.test.js +22 -0
- package/dist/__tests__/yongshen.test.js +9 -5
- package/dist/adapters/date-fns.d.ts +2 -2
- package/dist/adapters/date-fns.d.ts.map +1 -1
- package/dist/adapters/date-fns.js +39 -38
- package/dist/core/four-pillars.d.ts.map +1 -1
- package/dist/core/four-pillars.js +47 -4
- package/dist/core/luck.d.ts +6 -0
- package/dist/core/luck.d.ts.map +1 -1
- package/dist/core/luck.js +24 -2
- package/dist/core/nayin.d.ts +16 -0
- package/dist/core/nayin.d.ts.map +1 -0
- package/dist/core/nayin.js +83 -0
- package/dist/core/relations.d.ts +21 -3
- package/dist/core/relations.d.ts.map +1 -1
- package/dist/core/relations.js +74 -10
- package/dist/core/sinsals.d.ts +1 -1
- package/dist/core/sinsals.d.ts.map +1 -1
- package/dist/core/sinsals.js +100 -0
- package/dist/core/solar-terms.d.ts.map +1 -1
- package/dist/core/solar-terms.js +28 -1
- package/dist/core/strength.d.ts.map +1 -1
- package/dist/core/strength.js +24 -1
- package/dist/core/yongshen.d.ts.map +1 -1
- package/dist/core/yongshen.js +57 -22
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/utils/constants.js +1 -1
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -151,16 +151,20 @@ import { getFourPillars, STANDARD_PRESET } from "@gracefullight/saju";
|
|
|
151
151
|
|
|
152
152
|
const adapter = await createDateFnsAdapter();
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
timeZone: "Asia/Seoul",
|
|
157
|
-
};
|
|
154
|
+
// 일반 Date를 바로 사용할 수 있습니다
|
|
155
|
+
const dt = new Date(1985, 4, 15, 14, 30); // 주의: 월은 0부터 시작
|
|
158
156
|
|
|
159
157
|
const result = getFourPillars(dt, {
|
|
160
158
|
adapter,
|
|
161
159
|
longitudeDeg: 126.9778,
|
|
162
160
|
preset: STANDARD_PRESET,
|
|
163
161
|
});
|
|
162
|
+
|
|
163
|
+
// 명시적인 타임존 메타데이터가 필요하면 래퍼 객체도 계속 사용할 수 있습니다
|
|
164
|
+
const zonedDt = {
|
|
165
|
+
date: new Date(1985, 4, 15, 14, 30),
|
|
166
|
+
timeZone: "Asia/Seoul",
|
|
167
|
+
};
|
|
164
168
|
```
|
|
165
169
|
|
|
166
170
|
### 커스텀 날짜 어댑터
|
package/README.md
CHANGED
|
@@ -151,16 +151,20 @@ import { getFourPillars, STANDARD_PRESET } from "@gracefullight/saju";
|
|
|
151
151
|
|
|
152
152
|
const adapter = await createDateFnsAdapter();
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
timeZone: "Asia/Seoul",
|
|
157
|
-
};
|
|
154
|
+
// Plain Date works directly
|
|
155
|
+
const dt = new Date(1985, 4, 15, 14, 30); // Note: month is 0-indexed
|
|
158
156
|
|
|
159
157
|
const result = getFourPillars(dt, {
|
|
160
158
|
adapter,
|
|
161
159
|
longitudeDeg: 126.9778,
|
|
162
160
|
preset: STANDARD_PRESET,
|
|
163
161
|
});
|
|
162
|
+
|
|
163
|
+
// If you need explicit timezone metadata, you can still pass a wrapper object
|
|
164
|
+
const zonedDt = {
|
|
165
|
+
date: new Date(1985, 4, 15, 14, 30),
|
|
166
|
+
timeZone: "Asia/Seoul",
|
|
167
|
+
};
|
|
164
168
|
```
|
|
165
169
|
|
|
166
170
|
### Custom Date Adapter
|
|
@@ -6,6 +6,13 @@ describe("date-fns Adapter", () => {
|
|
|
6
6
|
adapter = await createDateFnsAdapter();
|
|
7
7
|
});
|
|
8
8
|
describe("Basic date getters", () => {
|
|
9
|
+
it("should accept plain Date values", () => {
|
|
10
|
+
const dt = new Date(2000, 0, 1, 18, 0);
|
|
11
|
+
expect(adapter.getYear(dt)).toBe(2000);
|
|
12
|
+
expect(adapter.getMonth(dt)).toBe(1);
|
|
13
|
+
expect(adapter.getDay(dt)).toBe(1);
|
|
14
|
+
expect(adapter.getHour(dt)).toBe(18);
|
|
15
|
+
});
|
|
9
16
|
it("should get year correctly", () => {
|
|
10
17
|
const dt = { date: new Date(2000, 0, 1), timeZone: "Asia/Seoul" };
|
|
11
18
|
expect(adapter.getYear(dt)).toBe(2000);
|
|
@@ -34,6 +41,10 @@ describe("date-fns Adapter", () => {
|
|
|
34
41
|
const dt = { date: new Date(2000, 0, 1), timeZone: "Asia/Seoul" };
|
|
35
42
|
expect(adapter.getZoneName(dt)).toBe("Asia/Seoul");
|
|
36
43
|
});
|
|
44
|
+
it("should fall back to system timezone for plain Date values", () => {
|
|
45
|
+
const dt = new Date(2000, 0, 1);
|
|
46
|
+
expect(adapter.getZoneName(dt)).toBe(Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
47
|
+
});
|
|
37
48
|
});
|
|
38
49
|
describe("Date arithmetic", () => {
|
|
39
50
|
it("should add minutes correctly", () => {
|
|
@@ -81,6 +81,7 @@ describe("relations", () => {
|
|
|
81
81
|
it("aggregates all relations", () => {
|
|
82
82
|
const result = analyzeRelations("甲子", "庚午", "丙寅", "壬申");
|
|
83
83
|
expect(result.all.length).toBe(result.combinations.length +
|
|
84
|
+
result.stemClashes.length +
|
|
84
85
|
result.clashes.length +
|
|
85
86
|
result.harms.length +
|
|
86
87
|
result.punishments.length +
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { createDateFnsAdapter } from "../adapters/date-fns";
|
|
3
4
|
import { createLuxonAdapter } from "../adapters/luxon";
|
|
4
5
|
import { getSaju, STANDARD_PRESET } from "../index";
|
|
5
6
|
describe("getSaju integration", () => {
|
|
@@ -140,4 +141,25 @@ describe("getSaju integration", () => {
|
|
|
140
141
|
expect(result.solarTerms.prevJieDate).toBeDefined();
|
|
141
142
|
expect(result.solarTerms.nextJieDate).toBeDefined();
|
|
142
143
|
});
|
|
144
|
+
it("accepts plain Date with the date-fns adapter (Issue #64 regression)", async () => {
|
|
145
|
+
const adapter = await createDateFnsAdapter();
|
|
146
|
+
const dt = new Date(1990, 1, 1, 12, 10);
|
|
147
|
+
expect(() => getSaju(dt, {
|
|
148
|
+
adapter,
|
|
149
|
+
longitudeDeg: 126.9778,
|
|
150
|
+
gender: "male",
|
|
151
|
+
preset: STANDARD_PRESET,
|
|
152
|
+
})).not.toThrow();
|
|
153
|
+
const result = getSaju(dt, {
|
|
154
|
+
adapter,
|
|
155
|
+
longitudeDeg: 126.9778,
|
|
156
|
+
gender: "male",
|
|
157
|
+
preset: STANDARD_PRESET,
|
|
158
|
+
});
|
|
159
|
+
expect(result.pillars.year).toBeDefined();
|
|
160
|
+
expect(result.pillars.month).toBeDefined();
|
|
161
|
+
expect(result.pillars.day).toBeDefined();
|
|
162
|
+
expect(result.pillars.hour).toBeDefined();
|
|
163
|
+
expect(result.lunar.lunarYear).toBeGreaterThan(0);
|
|
164
|
+
});
|
|
143
165
|
});
|
|
@@ -14,17 +14,21 @@ describe("yongshen", () => {
|
|
|
14
14
|
expect(result.allElements[result.primary.key].isYongShen).toBe(true);
|
|
15
15
|
});
|
|
16
16
|
it("identifies kishen elements correctly", () => {
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
17
|
+
// Use a balanced chart where 억부 method is used (not formation)
|
|
18
|
+
const result = analyzeYongShen("甲子", "丙寅", "庚申", "丁亥");
|
|
19
|
+
if (result.method.key !== "formation") {
|
|
20
|
+
const hasKiShen = Object.values(result.allElements).some((e) => e.isKiShen);
|
|
21
|
+
expect(hasKiShen).toBe(true);
|
|
22
|
+
}
|
|
20
23
|
});
|
|
21
24
|
it("uses 억부 method for 중화 strength (조후 is adjustment, not primary)", () => {
|
|
22
25
|
const result = analyzeYongShen("甲子", "丙寅", "庚申", "丁亥");
|
|
23
26
|
expect(["balance", "formation"]).toContain(result.method.key);
|
|
24
27
|
});
|
|
25
|
-
it("uses
|
|
28
|
+
it("uses formation method for extreme strength with 종강격", () => {
|
|
29
|
+
// All wood: extremely strong with no controller (metal) → 종강격
|
|
26
30
|
const result = analyzeYongShen("甲寅", "甲寅", "甲寅", "甲寅");
|
|
27
|
-
expect(result.method.key).toBe("
|
|
31
|
+
expect(result.method.key).toBe("formation");
|
|
28
32
|
});
|
|
29
33
|
it("includes johuAdjustment field in result", () => {
|
|
30
34
|
const result = analyzeYongShen("甲子", "丙寅", "甲辰", "乙亥");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { DateAdapter } from "../adapters/date-adapter";
|
|
2
|
-
interface
|
|
2
|
+
export interface ZonedDateFnsDate {
|
|
3
3
|
date: Date;
|
|
4
4
|
timeZone: string;
|
|
5
5
|
}
|
|
6
|
+
export type DateFnsDate = Date | ZonedDateFnsDate;
|
|
6
7
|
export declare function createDateFnsAdapter(): Promise<DateAdapter<DateFnsDate>>;
|
|
7
|
-
export {};
|
|
8
8
|
//# sourceMappingURL=date-fns.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-fns.d.ts","sourceRoot":"","sources":["../../src/adapters/date-fns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,
|
|
1
|
+
{"version":3,"file":"date-fns.d.ts","sourceRoot":"","sources":["../../src/adapters/date-fns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,gBAAgB,CAAC;AAgClD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CA4D9E"}
|
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
function isZonedDate(date) {
|
|
2
|
+
return (typeof date === "object" &&
|
|
3
|
+
date !== null &&
|
|
4
|
+
"date" in date &&
|
|
5
|
+
date.date instanceof Date &&
|
|
6
|
+
typeof date.timeZone === "string");
|
|
7
|
+
}
|
|
8
|
+
function getNativeDate(date) {
|
|
9
|
+
return isZonedDate(date) ? date.date : date;
|
|
10
|
+
}
|
|
11
|
+
function getSystemTimeZone() {
|
|
12
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
13
|
+
}
|
|
14
|
+
function getTimeZone(date) {
|
|
15
|
+
return isZonedDate(date) ? date.timeZone : getSystemTimeZone();
|
|
16
|
+
}
|
|
17
|
+
function cloneWithTimeZone(date, timeZone) {
|
|
18
|
+
return { date, timeZone };
|
|
19
|
+
}
|
|
20
|
+
function preserveInputShape(input, date) {
|
|
21
|
+
return isZonedDate(input) ? cloneWithTimeZone(date, input.timeZone) : date;
|
|
22
|
+
}
|
|
1
23
|
export async function createDateFnsAdapter() {
|
|
2
24
|
let addMinutes;
|
|
3
25
|
let addDays;
|
|
@@ -31,43 +53,22 @@ export async function createDateFnsAdapter() {
|
|
|
31
53
|
throw new Error("date-fns or date-fns-tz is not installed. Install with: npm install date-fns date-fns-tz");
|
|
32
54
|
}
|
|
33
55
|
return {
|
|
34
|
-
getYear: (dateFns) => getYear(dateFns
|
|
35
|
-
getMonth: (dateFns) => getMonth(dateFns
|
|
36
|
-
getDay: (dateFns) => getDate(dateFns
|
|
37
|
-
getHour: (dateFns) => getHours(dateFns
|
|
38
|
-
getMinute: (dateFns) => getMinutes(dateFns
|
|
39
|
-
getSecond: (dateFns) => getSeconds(dateFns
|
|
40
|
-
getZoneName: (dateFns) => dateFns
|
|
41
|
-
plusMinutes: (dateFns, minutes) => (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
timeZone: dateFns.timeZone,
|
|
52
|
-
}),
|
|
53
|
-
toUTC: (dateFns) => ({
|
|
54
|
-
date: fromZonedTime(dateFns.date, dateFns.timeZone),
|
|
55
|
-
timeZone: "UTC",
|
|
56
|
-
}),
|
|
57
|
-
toISO: (dateFns) => formatISO(dateFns.date),
|
|
58
|
-
toMillis: (dateFns) => dateFns.date.getTime(),
|
|
59
|
-
fromMillis: (millis, zone) => ({
|
|
60
|
-
date: new Date(millis),
|
|
61
|
-
timeZone: zone,
|
|
62
|
-
}),
|
|
63
|
-
createUTC: (year, month, day, hour, minute, second) => ({
|
|
64
|
-
date: new Date(Date.UTC(year, month - 1, day, hour, minute, second)),
|
|
65
|
-
timeZone: "UTC",
|
|
66
|
-
}),
|
|
67
|
-
setZone: (dateFns, zoneName) => ({
|
|
68
|
-
date: toZonedTime(dateFns.date, zoneName),
|
|
69
|
-
timeZone: zoneName,
|
|
70
|
-
}),
|
|
71
|
-
isGreaterThanOrEqual: (date1, date2) => date1.date >= date2.date,
|
|
56
|
+
getYear: (dateFns) => getYear(getNativeDate(dateFns)),
|
|
57
|
+
getMonth: (dateFns) => getMonth(getNativeDate(dateFns)) + 1,
|
|
58
|
+
getDay: (dateFns) => getDate(getNativeDate(dateFns)),
|
|
59
|
+
getHour: (dateFns) => getHours(getNativeDate(dateFns)),
|
|
60
|
+
getMinute: (dateFns) => getMinutes(getNativeDate(dateFns)),
|
|
61
|
+
getSecond: (dateFns) => getSeconds(getNativeDate(dateFns)),
|
|
62
|
+
getZoneName: (dateFns) => getTimeZone(dateFns),
|
|
63
|
+
plusMinutes: (dateFns, minutes) => preserveInputShape(dateFns, addMinutes(getNativeDate(dateFns), minutes)),
|
|
64
|
+
plusDays: (dateFns, days) => preserveInputShape(dateFns, addDays(getNativeDate(dateFns), days)),
|
|
65
|
+
minusDays: (dateFns, days) => preserveInputShape(dateFns, subDays(getNativeDate(dateFns), days)),
|
|
66
|
+
toUTC: (dateFns) => cloneWithTimeZone(fromZonedTime(getNativeDate(dateFns), getTimeZone(dateFns)), "UTC"),
|
|
67
|
+
toISO: (dateFns) => formatISO(getNativeDate(dateFns)),
|
|
68
|
+
toMillis: (dateFns) => getNativeDate(dateFns).getTime(),
|
|
69
|
+
fromMillis: (millis, zone) => cloneWithTimeZone(new Date(millis), zone),
|
|
70
|
+
createUTC: (year, month, day, hour, minute, second) => cloneWithTimeZone(new Date(Date.UTC(year, month - 1, day, hour, minute, second)), "UTC"),
|
|
71
|
+
setZone: (dateFns, zoneName) => cloneWithTimeZone(toZonedTime(getNativeDate(dateFns), zoneName), zoneName),
|
|
72
|
+
isGreaterThanOrEqual: (date1, date2) => getNativeDate(date1) >= getNativeDate(date2),
|
|
72
73
|
};
|
|
73
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"four-pillars.d.ts","sourceRoot":"","sources":["../../src/core/four-pillars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAgC,KAAK,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAE3B,eAAO,MAAM,eAAe;;;;CAI3B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAEF,eAAO,MAAM,OAAO;;;;CAAkB,CAAC;AACvC,eAAO,MAAM,OAAO;;;;CAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"four-pillars.d.ts","sourceRoot":"","sources":["../../src/core/four-pillars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAgB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAgC,KAAK,EAAE,MAAM,SAAS,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;AAE3B,eAAO,MAAM,eAAe;;;;CAI3B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAEF,eAAO,MAAM,OAAO;;;;CAAkB,CAAC;AACvC,eAAO,MAAM,OAAO;;;;CAAqB,CAAC;AAsD1C,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,KAAK,EACL,GAAG,GACJ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,GAAG;IACF,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAIA;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,CAAC,EACV,YAAY,EAAE,MAAM,EACpB,aAAa,SAAI,GAChB,CAAC,CAGH;AAoFD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,CAAC,EACV,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;CAAE,GACvC;IACD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAOA;AAsBD,wBAAgB,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,CAAC,EACV,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAA;CAAE,GACvC;IACD,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAWA;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,OAAO,EAAE,CAAC,EACV,EACE,OAAO,EACP,WAAwB,EACxB,YAAY,EACZ,aAAiB,EACjB,2BAAmC,GACpC,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACxB,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC,GACA;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAgB9C;AAWD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,CAAC,EACV,EACE,OAAO,EACP,YAAY,EACZ,aAAiB,EACjB,uBAA+B,EAC/B,WAAwB,EACxB,2BAAmC,GACpC,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,WAAW,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC,GACA;IACD,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,CAAC;IACd,aAAa,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D,CAuBA;AAED,wBAAgB,cAAc,CAAC,CAAC,EAC9B,OAAO,EAAE,CAAC,EACV,EACE,OAAO,EACP,YAAY,EACZ,aAAiB,EACjB,MAAgB,GACjB,EAAE;IACD,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,OAAO,GAAG,OAAO,OAAO,CAAC;CAC1C,GACA;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE;QACJ,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/D,iBAAiB,EAAE,MAAM,CAAC;QAC1B,MAAM,EAAE,OAAO,MAAM,CAAC;KACvB,CAAC;CACH,CA8CA"}
|
|
@@ -13,6 +13,45 @@ export const TRADITIONAL_PRESET = {
|
|
|
13
13
|
};
|
|
14
14
|
export const presetA = STANDARD_PRESET;
|
|
15
15
|
export const presetB = TRADITIONAL_PRESET;
|
|
16
|
+
/**
|
|
17
|
+
* Korea DST period: 1987-05-10 02:00 ~ 1988-10-08 03:00 (UTC+10)
|
|
18
|
+
* Returns the effective timezone offset in hours for a Korean datetime.
|
|
19
|
+
*/
|
|
20
|
+
function getEffectiveKSTOffset(adapter, dtLocal) {
|
|
21
|
+
const y = adapter.getYear(dtLocal);
|
|
22
|
+
const m = adapter.getMonth(dtLocal);
|
|
23
|
+
const d = adapter.getDay(dtLocal);
|
|
24
|
+
const h = adapter.getHour(dtLocal);
|
|
25
|
+
// KDT start: 1987-05-10 02:00 KST (becomes 03:00 KDT)
|
|
26
|
+
// KDT end: 1988-10-08 03:00 KDT (becomes 02:00 KST)
|
|
27
|
+
const afterStart = y > 1987 || (y === 1987 && (m > 5 || (m === 5 && (d > 10 || (d === 10 && h >= 2)))));
|
|
28
|
+
const beforeEnd = y < 1988 || (y === 1988 && (m < 10 || (m === 10 && (d < 8 || (d === 8 && h < 3)))));
|
|
29
|
+
return afterStart && beforeEnd ? 10 : 9;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Approximate ΔT (TT - UT) in seconds.
|
|
33
|
+
* Based on polynomial expressions from Meeus / USNO.
|
|
34
|
+
*/
|
|
35
|
+
function deltaT(year) {
|
|
36
|
+
if (year >= 2005 && year < 2050) {
|
|
37
|
+
const t = year - 2000;
|
|
38
|
+
return 62.92 + 0.32217 * t + 0.005589 * t * t;
|
|
39
|
+
}
|
|
40
|
+
if (year >= 1986 && year < 2005) {
|
|
41
|
+
const t = year - 2000;
|
|
42
|
+
return (63.86 +
|
|
43
|
+
0.3345 * t -
|
|
44
|
+
0.060374 * t * t +
|
|
45
|
+
0.0017275 * t * t * t +
|
|
46
|
+
0.000651814 * t * t * t * t +
|
|
47
|
+
0.00002373599 * t * t * t * t * t);
|
|
48
|
+
}
|
|
49
|
+
if (year >= 1900 && year < 1986) {
|
|
50
|
+
const t = year - 1900;
|
|
51
|
+
return -0.02 + 0.000297 * t * t;
|
|
52
|
+
}
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
16
55
|
function normDeg(x) {
|
|
17
56
|
x %= 360;
|
|
18
57
|
return x < 0 ? x + 360 : x;
|
|
@@ -38,7 +77,10 @@ function sunApparentLongitude(adapter, dtUtc) {
|
|
|
38
77
|
const A = Math.floor(y / 100);
|
|
39
78
|
const B = 2 - A + Math.floor(A / 4);
|
|
40
79
|
const JD = Math.floor(365.25 * (y + 4716)) + Math.floor(30.6001 * (m + 1)) + d + B - 1524.5;
|
|
41
|
-
|
|
80
|
+
// Apply ΔT correction for TT
|
|
81
|
+
const dtSeconds = deltaT(y);
|
|
82
|
+
const JD_TT = JD + dtSeconds / 86400.0;
|
|
83
|
+
const T = (JD_TT - 2451545.0) / 36525.0;
|
|
42
84
|
const L0 = normDeg(280.46646 + 36000.76983 * T + 0.0003032 * T * T);
|
|
43
85
|
const M = normDeg(357.52911 + 35999.05029 * T - 0.0001537 * T * T);
|
|
44
86
|
const deg2rad = (deg) => (deg * Math.PI) / 180;
|
|
@@ -171,7 +213,8 @@ export function hourPillar(dtLocal, { adapter, longitudeDeg, tzOffsetHours = 9,
|
|
|
171
213
|
return { pillar: STEMS[hs] + BRANCHES[hb], adjustedDt: dtUsed, effectiveDate: effDate };
|
|
172
214
|
}
|
|
173
215
|
export function getFourPillars(dtLocal, { adapter, longitudeDeg, tzOffsetHours = 9, preset = presetA, }) {
|
|
174
|
-
const
|
|
216
|
+
const effectiveTzOffset = tzOffsetHours === 9 ? getEffectiveKSTOffset(adapter, dtLocal) : tzOffsetHours;
|
|
217
|
+
const effectiveLongitude = longitudeDeg ?? effectiveTzOffset * 15;
|
|
175
218
|
const dayBoundary = preset.dayBoundary ?? "midnight";
|
|
176
219
|
const useMeanSolarTimeForHour = preset.useMeanSolarTimeForHour ?? false;
|
|
177
220
|
const useMeanSolarTimeForBoundary = preset.useMeanSolarTimeForBoundary ?? false;
|
|
@@ -181,14 +224,14 @@ export function getFourPillars(dtLocal, { adapter, longitudeDeg, tzOffsetHours =
|
|
|
181
224
|
adapter,
|
|
182
225
|
dayBoundary,
|
|
183
226
|
longitudeDeg: effectiveLongitude,
|
|
184
|
-
tzOffsetHours,
|
|
227
|
+
tzOffsetHours: effectiveTzOffset,
|
|
185
228
|
useMeanSolarTimeForBoundary,
|
|
186
229
|
});
|
|
187
230
|
const d = dayPillarFromDate(effDate);
|
|
188
231
|
const h = hourPillar(dtLocal, {
|
|
189
232
|
adapter,
|
|
190
233
|
longitudeDeg: effectiveLongitude,
|
|
191
|
-
tzOffsetHours,
|
|
234
|
+
tzOffsetHours: effectiveTzOffset,
|
|
192
235
|
useMeanSolarTimeForHour,
|
|
193
236
|
dayBoundary,
|
|
194
237
|
useMeanSolarTimeForBoundary,
|
package/dist/core/luck.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DateAdapter } from "../adapters/date-adapter";
|
|
2
|
+
import { type SolarTermKey } from "../core/solar-terms";
|
|
2
3
|
import type { Gender, Polarity } from "../types";
|
|
3
4
|
export type { Gender };
|
|
4
5
|
export interface LuckPillar {
|
|
@@ -45,6 +46,11 @@ export interface MonthlyLuckResult {
|
|
|
45
46
|
stem: string;
|
|
46
47
|
branch: string;
|
|
47
48
|
pillar: string;
|
|
49
|
+
solarTerm: {
|
|
50
|
+
key: SolarTermKey;
|
|
51
|
+
korean: string;
|
|
52
|
+
hanja: string;
|
|
53
|
+
};
|
|
48
54
|
}
|
|
49
55
|
export declare function calculateMonthlyLuck(year: number, fromMonth: number, toMonth: number): MonthlyLuckResult[];
|
|
50
56
|
export interface DailyLuckResult {
|
package/dist/core/luck.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"luck.d.ts","sourceRoot":"","sources":["../../src/core/luck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"luck.d.ts","sourceRoot":"","sources":["../../src/core/luck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGhD,YAAY,EAAE,MAAM,EAAE,CAAC;AAEvB,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,QAAQ,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,aAAa,EAAE,CAAC,EAChB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE;IACP,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,eAAe,CA4DjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,gBAAgB,EAAE,CAkBpB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAO9F;AAiBD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE;QACT,GAAG,EAAE,YAAY,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,iBAAiB,EAAE,CAoCrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,eAAe,EAAE,CAqBnB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAI7E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAWlE"}
|
package/dist/core/luck.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getSolarTermLabel } from "../core/solar-terms";
|
|
1
2
|
import { getStemPolarity } from "../core/ten-gods";
|
|
2
3
|
import { BRANCHES, getPillarIndex, jdnFromDate, pillarFromIndex, STEMS } from "../utils";
|
|
3
4
|
export function calculateMajorLuck(birthDateTime, gender, yearPillar, monthPillar, options) {
|
|
@@ -79,6 +80,20 @@ export function getCurrentMajorLuck(majorLuck, age) {
|
|
|
79
80
|
}
|
|
80
81
|
return null;
|
|
81
82
|
}
|
|
83
|
+
const MONTH_JIE_KEYS = [
|
|
84
|
+
"springBegins",
|
|
85
|
+
"awakeningInsects",
|
|
86
|
+
"pureBrightness",
|
|
87
|
+
"summerBegins",
|
|
88
|
+
"grainInEar",
|
|
89
|
+
"minorHeat",
|
|
90
|
+
"autumnBegins",
|
|
91
|
+
"whiteDew",
|
|
92
|
+
"coldDew",
|
|
93
|
+
"winterBegins",
|
|
94
|
+
"majorSnow",
|
|
95
|
+
"minorCold",
|
|
96
|
+
];
|
|
82
97
|
export function calculateMonthlyLuck(year, fromMonth, toMonth) {
|
|
83
98
|
const results = [];
|
|
84
99
|
const yearIdx60 = (((year - 1984) % 60) + 60) % 60;
|
|
@@ -92,12 +107,19 @@ export function calculateMonthlyLuck(year, fromMonth, toMonth) {
|
|
|
92
107
|
const stem = STEMS[stemIdx];
|
|
93
108
|
const branch = BRANCHES[branchIdx];
|
|
94
109
|
const pillar = stem + branch;
|
|
110
|
+
const jieKey = MONTH_JIE_KEYS[monthOffset % 12];
|
|
111
|
+
const jieLabel = getSolarTermLabel(jieKey);
|
|
95
112
|
results.push({
|
|
96
113
|
year,
|
|
97
114
|
month,
|
|
98
115
|
stem,
|
|
99
116
|
branch,
|
|
100
117
|
pillar,
|
|
118
|
+
solarTerm: {
|
|
119
|
+
key: jieLabel.key,
|
|
120
|
+
korean: jieLabel.korean,
|
|
121
|
+
hanja: jieLabel.hanja,
|
|
122
|
+
},
|
|
101
123
|
});
|
|
102
124
|
}
|
|
103
125
|
return results;
|
|
@@ -106,7 +128,7 @@ export function calculateDailyLuck(year, month, fromDay, toDay) {
|
|
|
106
128
|
const results = [];
|
|
107
129
|
for (let day = fromDay; day <= toDay; day++) {
|
|
108
130
|
const jdn = jdnFromDate(year, month, day);
|
|
109
|
-
const idx60 = (((jdn
|
|
131
|
+
const idx60 = (((jdn - 11) % 60) + 60) % 60;
|
|
110
132
|
const stem = STEMS[idx60 % 10];
|
|
111
133
|
const branch = BRANCHES[idx60 % 12];
|
|
112
134
|
const pillar = stem + branch;
|
|
@@ -123,7 +145,7 @@ export function calculateDailyLuck(year, month, fromDay, toDay) {
|
|
|
123
145
|
}
|
|
124
146
|
export function getDayPillar(year, month, day) {
|
|
125
147
|
const jdn = jdnFromDate(year, month, day);
|
|
126
|
-
const idx60 = (((jdn
|
|
148
|
+
const idx60 = (((jdn - 11) % 60) + 60) % 60;
|
|
127
149
|
return STEMS[idx60 % 10] + BRANCHES[idx60 % 12];
|
|
128
150
|
}
|
|
129
151
|
export function getMonthPillar(year, month) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Element } from "../types";
|
|
2
|
+
export interface NayinResult {
|
|
3
|
+
element: Element;
|
|
4
|
+
korean: string;
|
|
5
|
+
hanja: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function getNayin(pillarIdx60: number): NayinResult;
|
|
8
|
+
export declare function getNayinFromPillar(pillar: string): NayinResult;
|
|
9
|
+
export interface FourPillarsNayin {
|
|
10
|
+
year: NayinResult;
|
|
11
|
+
month: NayinResult;
|
|
12
|
+
day: NayinResult;
|
|
13
|
+
hour: NayinResult;
|
|
14
|
+
}
|
|
15
|
+
export declare function analyzeFourPillarsNayin(yearPillar: string, monthPillar: string, dayPillar: string, hourPillar: string): FourPillarsNayin;
|
|
16
|
+
//# sourceMappingURL=nayin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nayin.d.ts","sourceRoot":"","sources":["../../src/core/nayin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAkEvC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CAMzD;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAG9D;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC;IACnB,GAAG,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,gBAAgB,CAOlB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { getPillarIndex } from "../utils";
|
|
2
|
+
const NAYIN_TABLE = {
|
|
3
|
+
0: { element: "metal", korean: "해중금", hanja: "海中金" },
|
|
4
|
+
1: { element: "metal", korean: "해중금", hanja: "海中金" },
|
|
5
|
+
2: { element: "fire", korean: "노중화", hanja: "爐中火" },
|
|
6
|
+
3: { element: "fire", korean: "노중화", hanja: "爐中火" },
|
|
7
|
+
4: { element: "wood", korean: "대림목", hanja: "大林木" },
|
|
8
|
+
5: { element: "wood", korean: "대림목", hanja: "大林木" },
|
|
9
|
+
6: { element: "earth", korean: "노방토", hanja: "路傍土" },
|
|
10
|
+
7: { element: "earth", korean: "노방토", hanja: "路傍土" },
|
|
11
|
+
8: { element: "metal", korean: "검봉금", hanja: "劍鋒金" },
|
|
12
|
+
9: { element: "metal", korean: "검봉금", hanja: "劍鋒金" },
|
|
13
|
+
10: { element: "fire", korean: "산두화", hanja: "山頭火" },
|
|
14
|
+
11: { element: "fire", korean: "산두화", hanja: "山頭火" },
|
|
15
|
+
12: { element: "water", korean: "간하수", hanja: "澗下水" },
|
|
16
|
+
13: { element: "water", korean: "간하수", hanja: "澗下水" },
|
|
17
|
+
14: { element: "earth", korean: "성두토", hanja: "城頭土" },
|
|
18
|
+
15: { element: "earth", korean: "성두토", hanja: "城頭土" },
|
|
19
|
+
16: { element: "metal", korean: "백랍금", hanja: "白蠟金" },
|
|
20
|
+
17: { element: "metal", korean: "백랍금", hanja: "白蠟金" },
|
|
21
|
+
18: { element: "wood", korean: "양류목", hanja: "楊柳木" },
|
|
22
|
+
19: { element: "wood", korean: "양류목", hanja: "楊柳木" },
|
|
23
|
+
20: { element: "water", korean: "천천수", hanja: "泉中水" },
|
|
24
|
+
21: { element: "water", korean: "천천수", hanja: "泉中水" },
|
|
25
|
+
22: { element: "earth", korean: "옥상토", hanja: "屋上土" },
|
|
26
|
+
23: { element: "earth", korean: "옥상토", hanja: "屋上土" },
|
|
27
|
+
24: { element: "fire", korean: "벽력화", hanja: "霹靂火" },
|
|
28
|
+
25: { element: "fire", korean: "벽력화", hanja: "霹靂火" },
|
|
29
|
+
26: { element: "wood", korean: "송백목", hanja: "松柏木" },
|
|
30
|
+
27: { element: "wood", korean: "송백목", hanja: "松柏木" },
|
|
31
|
+
28: { element: "water", korean: "장류수", hanja: "長流水" },
|
|
32
|
+
29: { element: "water", korean: "장류수", hanja: "長流水" },
|
|
33
|
+
30: { element: "metal", korean: "사중금", hanja: "砂中金" },
|
|
34
|
+
31: { element: "metal", korean: "사중금", hanja: "砂中金" },
|
|
35
|
+
32: { element: "fire", korean: "산하화", hanja: "山下火" },
|
|
36
|
+
33: { element: "fire", korean: "산하화", hanja: "山下火" },
|
|
37
|
+
34: { element: "wood", korean: "평지목", hanja: "平地木" },
|
|
38
|
+
35: { element: "wood", korean: "평지목", hanja: "平地木" },
|
|
39
|
+
36: { element: "earth", korean: "벽상토", hanja: "壁上土" },
|
|
40
|
+
37: { element: "earth", korean: "벽상토", hanja: "壁上土" },
|
|
41
|
+
38: { element: "metal", korean: "금박금", hanja: "金箔金" },
|
|
42
|
+
39: { element: "metal", korean: "금박금", hanja: "金箔金" },
|
|
43
|
+
40: { element: "fire", korean: "복등화", hanja: "覆燈火" },
|
|
44
|
+
41: { element: "fire", korean: "복등화", hanja: "覆燈火" },
|
|
45
|
+
42: { element: "water", korean: "천하수", hanja: "天河水" },
|
|
46
|
+
43: { element: "water", korean: "천하수", hanja: "天河水" },
|
|
47
|
+
44: { element: "earth", korean: "대역토", hanja: "大驛土" },
|
|
48
|
+
45: { element: "earth", korean: "대역토", hanja: "大驛土" },
|
|
49
|
+
46: { element: "metal", korean: "채광금", hanja: "釵釧金" },
|
|
50
|
+
47: { element: "metal", korean: "채광금", hanja: "釵釧金" },
|
|
51
|
+
48: { element: "wood", korean: "상자목", hanja: "桑柘木" },
|
|
52
|
+
49: { element: "wood", korean: "상자목", hanja: "桑柘木" },
|
|
53
|
+
50: { element: "water", korean: "대계수", hanja: "大溪水" },
|
|
54
|
+
51: { element: "water", korean: "대계수", hanja: "大溪水" },
|
|
55
|
+
52: { element: "earth", korean: "사중토", hanja: "砂中土" },
|
|
56
|
+
53: { element: "earth", korean: "사중토", hanja: "砂中土" },
|
|
57
|
+
54: { element: "fire", korean: "천상화", hanja: "天上火" },
|
|
58
|
+
55: { element: "fire", korean: "천상화", hanja: "天上火" },
|
|
59
|
+
56: { element: "wood", korean: "석류목", hanja: "石榴木" },
|
|
60
|
+
57: { element: "wood", korean: "석류목", hanja: "石榴木" },
|
|
61
|
+
58: { element: "water", korean: "대해수", hanja: "大海水" },
|
|
62
|
+
59: { element: "water", korean: "대해수", hanja: "大海水" },
|
|
63
|
+
};
|
|
64
|
+
export function getNayin(pillarIdx60) {
|
|
65
|
+
const normalized = ((pillarIdx60 % 60) + 60) % 60;
|
|
66
|
+
const pairIdx = Math.floor(normalized / 2) * 2;
|
|
67
|
+
const entry = NAYIN_TABLE[pairIdx];
|
|
68
|
+
if (!entry)
|
|
69
|
+
throw new Error(`Invalid pillar index: ${pillarIdx60}`);
|
|
70
|
+
return { element: entry.element, korean: entry.korean, hanja: entry.hanja };
|
|
71
|
+
}
|
|
72
|
+
export function getNayinFromPillar(pillar) {
|
|
73
|
+
const idx = getPillarIndex(pillar);
|
|
74
|
+
return getNayin(idx);
|
|
75
|
+
}
|
|
76
|
+
export function analyzeFourPillarsNayin(yearPillar, monthPillar, dayPillar, hourPillar) {
|
|
77
|
+
return {
|
|
78
|
+
year: getNayin(getPillarIndex(yearPillar)),
|
|
79
|
+
month: getNayin(getPillarIndex(monthPillar)),
|
|
80
|
+
day: getNayin(getPillarIndex(dayPillar)),
|
|
81
|
+
hour: getNayin(getPillarIndex(hourPillar)),
|
|
82
|
+
};
|
|
83
|
+
}
|
package/dist/core/relations.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Element, ElementLabel } from "../core/ten-gods";
|
|
2
2
|
import type { Label } from "../types";
|
|
3
|
-
export declare const RELATION_TYPE_KEYS: readonly ["stemCombination", "sixCombination", "tripleCombination", "directionalCombination", "clash", "harm", "punishment", "destruction"];
|
|
3
|
+
export declare const RELATION_TYPE_KEYS: readonly ["stemCombination", "stemClash", "sixCombination", "halfCombination", "tripleCombination", "directionalCombination", "clash", "harm", "punishment", "destruction"];
|
|
4
4
|
export type RelationTypeKey = (typeof RELATION_TYPE_KEYS)[number];
|
|
5
5
|
export interface RelationTypeLabel extends Label<RelationTypeKey> {
|
|
6
6
|
}
|
|
@@ -20,11 +20,17 @@ export type StemCombinationResult = {
|
|
|
20
20
|
resultElement: Element;
|
|
21
21
|
};
|
|
22
22
|
export declare const STEM_COMBINATIONS: StemCombinationResult[];
|
|
23
|
+
export declare const STEM_CLASHES: [string, string][];
|
|
23
24
|
export type BranchCombinationResult = {
|
|
24
25
|
branches: [string, string];
|
|
25
26
|
resultElement: Element;
|
|
26
27
|
};
|
|
27
28
|
export declare const BRANCH_SIX_COMBINATIONS: BranchCombinationResult[];
|
|
29
|
+
export type HalfCombinationResult = {
|
|
30
|
+
branches: [string, string];
|
|
31
|
+
resultElement: Element;
|
|
32
|
+
};
|
|
33
|
+
export declare const BRANCH_HALF_COMBINATIONS: HalfCombinationResult[];
|
|
28
34
|
export type TripleCombinationResult = {
|
|
29
35
|
branches: [string, string, string];
|
|
30
36
|
resultElement: Element;
|
|
@@ -46,6 +52,11 @@ export interface StemCombination {
|
|
|
46
52
|
transformStatus: TransformationStatusLabel;
|
|
47
53
|
transformReason: string;
|
|
48
54
|
}
|
|
55
|
+
export interface StemClash {
|
|
56
|
+
type: RelationTypeLabel;
|
|
57
|
+
pair: [string, string];
|
|
58
|
+
positions: [string, string];
|
|
59
|
+
}
|
|
49
60
|
export interface BranchSixCombination {
|
|
50
61
|
type: RelationTypeLabel;
|
|
51
62
|
pair: [string, string];
|
|
@@ -54,6 +65,12 @@ export interface BranchSixCombination {
|
|
|
54
65
|
transformStatus: TransformationStatusLabel;
|
|
55
66
|
transformReason: string;
|
|
56
67
|
}
|
|
68
|
+
export interface BranchHalfCombination {
|
|
69
|
+
type: RelationTypeLabel;
|
|
70
|
+
pair: [string, string];
|
|
71
|
+
positions: [string, string];
|
|
72
|
+
resultElement: ElementLabel;
|
|
73
|
+
}
|
|
57
74
|
export interface BranchTripleCombination {
|
|
58
75
|
type: RelationTypeLabel;
|
|
59
76
|
branches: string[];
|
|
@@ -93,9 +110,10 @@ export interface BranchDestruction {
|
|
|
93
110
|
pair: [string, string];
|
|
94
111
|
positions: [string, string];
|
|
95
112
|
}
|
|
96
|
-
export type Relation = StemCombination | BranchSixCombination | BranchTripleCombination | BranchDirectionalCombination | BranchClash | BranchHarm | BranchPunishment | BranchDestruction;
|
|
113
|
+
export type Relation = StemCombination | StemClash | BranchSixCombination | BranchHalfCombination | BranchTripleCombination | BranchDirectionalCombination | BranchClash | BranchHarm | BranchPunishment | BranchDestruction;
|
|
97
114
|
export interface RelationsResult {
|
|
98
|
-
combinations: (StemCombination | BranchSixCombination | BranchTripleCombination | BranchDirectionalCombination)[];
|
|
115
|
+
combinations: (StemCombination | BranchSixCombination | BranchHalfCombination | BranchTripleCombination | BranchDirectionalCombination)[];
|
|
116
|
+
stemClashes: StemClash[];
|
|
99
117
|
clashes: BranchClash[];
|
|
100
118
|
harms: BranchHarm[];
|
|
101
119
|
punishments: BranchPunishment[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/core/relations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,eAAO,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"relations.d.ts","sourceRoot":"","sources":["../../src/core/relations.ts"],"names":[],"mappings":"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"}
|