@orrery/core 0.2.1 → 0.3.0

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.
@@ -1,3 +1,6 @@
1
+ import {
2
+ adjustKdtToKst
3
+ } from "./chunk-TW4ADZCX.js";
1
4
  import {
2
5
  BRIGHTNESS_TABLE,
3
6
  DI_ZHI,
@@ -11894,6 +11897,12 @@ function getBrightness(star, zhi) {
11894
11897
  return BRIGHTNESS_TABLE[star]?.[zhi] ?? "";
11895
11898
  }
11896
11899
  function createChart(year, month, day, hour, minute, isMale) {
11900
+ const kst = adjustKdtToKst(year, month, day, hour, minute);
11901
+ year = kst.year;
11902
+ month = kst.month;
11903
+ day = kst.day;
11904
+ hour = kst.hour;
11905
+ minute = kst.minute;
11897
11906
  const { lunarYear, lunarMonth, lunarDay, isLeap } = solarToLunar(year, month, day);
11898
11907
  const [yearGan, yearZhi] = getYearGanZhi(lunarYear);
11899
11908
  const mingGongZhi = calculateMingGong(lunarMonth, hour);
@@ -1,3 +1,6 @@
1
+ import {
2
+ adjustKdtToKst
3
+ } from "./chunk-TW4ADZCX.js";
1
4
  import {
2
5
  analyzeAllRelations,
3
6
  getDaewoon,
@@ -16,7 +19,9 @@ function getSipsin(dayStem, targetStem) {
16
19
  return rel ? rel.hanja : "?";
17
20
  }
18
21
  function calculateSaju(input) {
19
- const { year, month, day, hour, minute, gender } = input;
22
+ const kst = adjustKdtToKst(input.year, input.month, input.day, input.hour, input.minute);
23
+ const { year, month, day, hour, minute } = kst;
24
+ const { gender } = input;
20
25
  const isMale = gender === "M";
21
26
  const [yp, mp, dp, hp] = getFourPillars(year, month, day, hour, minute);
22
27
  const dayStem = dp[0];
@@ -0,0 +1,33 @@
1
+ // src/kdt.ts
2
+ function isKoreanDaylightTime(year, month, day) {
3
+ if (year === 1987) {
4
+ if (month > 5 && month < 10) return true;
5
+ if (month === 5 && day >= 10) return true;
6
+ if (month === 10 && day <= 11) return true;
7
+ }
8
+ if (year === 1988) {
9
+ if (month > 5 && month < 10) return true;
10
+ if (month === 5 && day >= 8) return true;
11
+ if (month === 10 && day <= 9) return true;
12
+ }
13
+ return false;
14
+ }
15
+ function adjustKdtToKst(year, month, day, hour, minute) {
16
+ if (!isKoreanDaylightTime(year, month, day)) {
17
+ return { year, month, day, hour, minute };
18
+ }
19
+ hour -= 1;
20
+ if (hour < 0) {
21
+ hour += 24;
22
+ const d = new Date(year, month - 1, day - 1);
23
+ year = d.getFullYear();
24
+ month = d.getMonth() + 1;
25
+ day = d.getDate();
26
+ }
27
+ return { year, month, day, hour, minute };
28
+ }
29
+
30
+ export {
31
+ isKoreanDaylightTime,
32
+ adjustKdtToKst
33
+ };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  export { calculateSaju } from './saju.js';
2
2
  export { calculateLiunian, createChart, getDaxianList } from './ziwei.js';
3
- export { ASPECT_SYMBOLS, HOUSE_SYSTEMS, PLANET_KO, PLANET_SYMBOLS, ROMAN, ZODIAC_KO, ZODIAC_SIGNS, ZODIAC_SYMBOLS, calculateNatal, formatDegree, getSwissEph, lonToSign, normalizeDeg } from './natal.js';
3
+ export { ASPECT_SYMBOLS, HOUSE_SYSTEMS, PLANET_KO, PLANET_SYMBOLS, ROMAN, ZODIAC_KO, ZODIAC_SIGNS, ZODIAC_SYMBOLS, calculateNatal, formatDegree, isKoreanDaylightTime, lonToSign, normalizeDeg } from './natal.js';
4
4
  export { analyzeAllRelations, analyzePillarRelations, calcPillarIndices, calcSolarTerms, checkDirectionalCompose, checkTripleCompose, findTransits, getBranchRelation, getDaewoon, getFourPillars, getHiddenStems, getJeonggi, getRelation, getSpecialSals, getStemRelation, getTwelveMeteor, getTwelveSpirit, toHangul } from './pillars.js';
5
5
  export { BRANCH_ELEMENT, DI_ZHI, EARTH, EARTH_KR, ELEMENT_HANJA, HGANJI, JIJANGGAN, LUCKY_STAR_NAMES, MAIN_STAR_NAMES, METEORS_12, METEOR_LOOKUP, PALACE_NAMES, PILLAR_NAMES, RELATIONS, SHA_STAR_NAMES, SKY, SKY_KR, SPIRITS_12, STEM_INFO, TIAN_GAN, YANGGAN } from './constants.js';
6
6
  export { City, KOREAN_CITIES, SEOUL, WORLD_CITIES, filterCities, formatCityName } from './cities.js';
7
7
  export { AllRelations, AspectType, BirthInput, DaewoonItem, Element, Gender, LiuNianInfo, LiuYueInfo, Meteor, NatalAngles, NatalAspect, NatalChart, NatalHouse, PairRelation, Pillar, PillarDetail, PlanetId, PlanetPosition, Relation, RelationResult, SajuResult, SpecialSals, Spirit, StemInfo, TransitItem, WuXingJu, YinYang, ZiweiChart, ZiweiPalace, ZiweiStar, ZodiacSign } from './types.js';
8
- import 'swisseph-wasm';
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  calculateSaju
3
- } from "./chunk-TRSIZZ73.js";
3
+ } from "./chunk-ETDERV6C.js";
4
4
  import {
5
5
  calculateLiunian,
6
6
  createChart,
7
7
  getDaxianList
8
- } from "./chunk-KD6TCTRW.js";
8
+ } from "./chunk-CISACDIA.js";
9
9
  import {
10
10
  ASPECT_SYMBOLS,
11
11
  HOUSE_SYSTEMS,
@@ -17,10 +17,12 @@ import {
17
17
  ZODIAC_SYMBOLS,
18
18
  calculateNatal,
19
19
  formatDegree,
20
- getSwissEph,
21
20
  lonToSign,
22
21
  normalizeDeg
23
- } from "./chunk-6PJQHSY6.js";
22
+ } from "./chunk-6BKZDAMP.js";
23
+ import {
24
+ isKoreanDaylightTime
25
+ } from "./chunk-TW4ADZCX.js";
24
26
  import {
25
27
  analyzeAllRelations,
26
28
  analyzePillarRelations,
@@ -128,9 +130,9 @@ export {
128
130
  getRelation,
129
131
  getSpecialSals,
130
132
  getStemRelation,
131
- getSwissEph,
132
133
  getTwelveMeteor,
133
134
  getTwelveSpirit,
135
+ isKoreanDaylightTime,
134
136
  lonToSign,
135
137
  normalizeDeg,
136
138
  toHangul
package/dist/natal.d.ts CHANGED
@@ -1,11 +1,19 @@
1
- import SwissEph from 'swisseph-wasm';
2
1
  import { AspectType, PlanetId, ZodiacSign, BirthInput, NatalChart } from './types.js';
3
2
 
3
+ /**
4
+ * 한국 하계표준시(KDT) 유틸리티
5
+ *
6
+ * 1987~1988년 88올림픽 준비를 위해 시행된 하계표준시(UTC+10) 보정.
7
+ * SwissEph 등 무거운 의존성 없이 saju/ziwei/natal 모두에서 사용 가능.
8
+ */
9
+ /** 한국 하계표준시(KDT) 기간인지 판정 (1987~1988 88올림픽) */
10
+ declare function isKoreanDaylightTime(year: number, month: number, day: number): boolean;
11
+
4
12
  /**
5
13
  * 서양 점성술 Natal Chart 계산 엔진
6
14
  *
7
- * flatlib/pyswisseph 기반을 TypeScript 포팅.
8
- * 브라우저에서 Swiss Ephemeris를 사용하기 위해 swisseph-wasm을 활용한다.
15
+ * Pure TypeScript ephemeris (Moshier 이론 기반).
16
+ * 외부 데이터 파일이나 WASM 없이 브라우저에서 동기 실행 가능.
9
17
  */
10
18
 
11
19
  declare const ZODIAC_SIGNS: ZodiacSign[];
@@ -17,7 +25,6 @@ declare const ASPECT_SYMBOLS: Record<AspectType, string>;
17
25
  declare const ROMAN: string[];
18
26
  /** 하우스 시스템: [swisseph char, 표시 이름] */
19
27
  declare const HOUSE_SYSTEMS: [string, string][];
20
- declare function getSwissEph(): Promise<SwissEph>;
21
28
  /** longitude → ZodiacSign */
22
29
  declare function lonToSign(lon: number): ZodiacSign;
23
30
  /** 0~360 정규화 (음수 모듈로 처리) */
@@ -26,4 +33,4 @@ declare function normalizeDeg(deg: number): number;
26
33
  declare function formatDegree(lon: number): string;
27
34
  declare function calculateNatal(input: BirthInput, houseSystem?: string): Promise<NatalChart>;
28
35
 
29
- export { ASPECT_SYMBOLS, HOUSE_SYSTEMS, PLANET_KO, PLANET_SYMBOLS, ROMAN, ZODIAC_KO, ZODIAC_SIGNS, ZODIAC_SYMBOLS, calculateNatal, formatDegree, getSwissEph, lonToSign, normalizeDeg };
36
+ export { ASPECT_SYMBOLS, HOUSE_SYSTEMS, PLANET_KO, PLANET_SYMBOLS, ROMAN, ZODIAC_KO, ZODIAC_SIGNS, ZODIAC_SYMBOLS, calculateNatal, formatDegree, isKoreanDaylightTime, lonToSign, normalizeDeg };
package/dist/natal.js CHANGED
@@ -9,10 +9,12 @@ import {
9
9
  ZODIAC_SYMBOLS,
10
10
  calculateNatal,
11
11
  formatDegree,
12
- getSwissEph,
13
12
  lonToSign,
14
13
  normalizeDeg
15
- } from "./chunk-6PJQHSY6.js";
14
+ } from "./chunk-6BKZDAMP.js";
15
+ import {
16
+ isKoreanDaylightTime
17
+ } from "./chunk-TW4ADZCX.js";
16
18
  import "./chunk-JSBRDJBE.js";
17
19
  export {
18
20
  ASPECT_SYMBOLS,
@@ -25,7 +27,7 @@ export {
25
27
  ZODIAC_SYMBOLS,
26
28
  calculateNatal,
27
29
  formatDegree,
28
- getSwissEph,
30
+ isKoreanDaylightTime,
29
31
  lonToSign,
30
32
  normalizeDeg
31
33
  };
package/dist/saju.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  calculateSaju
3
- } from "./chunk-TRSIZZ73.js";
3
+ } from "./chunk-ETDERV6C.js";
4
+ import "./chunk-TW4ADZCX.js";
4
5
  import "./chunk-DGSIRAXF.js";
5
6
  import "./chunk-VJDUZB5T.js";
6
7
  import "./chunk-JSBRDJBE.js";
package/dist/ziwei.js CHANGED
@@ -2,7 +2,8 @@ import {
2
2
  calculateLiunian,
3
3
  createChart,
4
4
  getDaxianList
5
- } from "./chunk-KD6TCTRW.js";
5
+ } from "./chunk-CISACDIA.js";
6
+ import "./chunk-TW4ADZCX.js";
6
7
  import "./chunk-VJDUZB5T.js";
7
8
  import "./chunk-JSBRDJBE.js";
8
9
  export {
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@orrery/core",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
+ "license": "AGPL-3.0-only",
4
5
  "type": "module",
5
6
  "keywords": [
6
7
  "saju",
@@ -60,14 +61,6 @@
60
61
  "dependencies": {
61
62
  "lunar-javascript": "^1.7.7"
62
63
  },
63
- "peerDependencies": {
64
- "swisseph-wasm": "^0.0.4"
65
- },
66
- "peerDependenciesMeta": {
67
- "swisseph-wasm": {
68
- "optional": true
69
- }
70
- },
71
64
  "devDependencies": {
72
65
  "tsup": "^8.5.0",
73
66
  "typescript": "~5.9.3",
@@ -1,292 +0,0 @@
1
- // src/natal.ts
2
- import SwissEph from "swisseph-wasm";
3
- var DEFAULT_LAT = 37.5194;
4
- var DEFAULT_LON = 127.0992;
5
- var ZODIAC_SIGNS = [
6
- "Aries",
7
- "Taurus",
8
- "Gemini",
9
- "Cancer",
10
- "Leo",
11
- "Virgo",
12
- "Libra",
13
- "Scorpio",
14
- "Sagittarius",
15
- "Capricorn",
16
- "Aquarius",
17
- "Pisces"
18
- ];
19
- var ZODIAC_SYMBOLS = {
20
- Aries: "\u2648",
21
- Taurus: "\u2649",
22
- Gemini: "\u264A",
23
- Cancer: "\u264B",
24
- Leo: "\u264C",
25
- Virgo: "\u264D",
26
- Libra: "\u264E",
27
- Scorpio: "\u264F",
28
- Sagittarius: "\u2650",
29
- Capricorn: "\u2651",
30
- Aquarius: "\u2652",
31
- Pisces: "\u2653"
32
- };
33
- var ZODIAC_KO = {
34
- Aries: "\uC591\uC790\uB9AC",
35
- Taurus: "\uD669\uC18C\uC790\uB9AC",
36
- Gemini: "\uC30D\uB465\uC774\uC790\uB9AC",
37
- Cancer: "\uAC8C\uC790\uB9AC",
38
- Leo: "\uC0AC\uC790\uC790\uB9AC",
39
- Virgo: "\uCC98\uB140\uC790\uB9AC",
40
- Libra: "\uCC9C\uCE6D\uC790\uB9AC",
41
- Scorpio: "\uC804\uAC08\uC790\uB9AC",
42
- Sagittarius: "\uAD81\uC218\uC790\uB9AC",
43
- Capricorn: "\uC5FC\uC18C\uC790\uB9AC",
44
- Aquarius: "\uBB3C\uBCD1\uC790\uB9AC",
45
- Pisces: "\uBB3C\uACE0\uAE30\uC790\uB9AC"
46
- };
47
- var PLANET_SYMBOLS = {
48
- Sun: "\u2609",
49
- Moon: "\u263D",
50
- Mercury: "\u263F",
51
- Venus: "\u2640",
52
- Mars: "\u2642",
53
- Jupiter: "\u2643",
54
- Saturn: "\u2644",
55
- Uranus: "\u2645",
56
- Neptune: "\u2646",
57
- Pluto: "\u2647",
58
- Chiron: "\u26B7",
59
- NorthNode: "\u260A",
60
- SouthNode: "\u260B"
61
- };
62
- var PLANET_KO = {
63
- Sun: "\uD0DC\uC591",
64
- Moon: "\uB2EC",
65
- Mercury: "\uC218\uC131",
66
- Venus: "\uAE08\uC131",
67
- Mars: "\uD654\uC131",
68
- Jupiter: "\uBAA9\uC131",
69
- Saturn: "\uD1A0\uC131",
70
- Uranus: "\uCC9C\uC655\uC131",
71
- Neptune: "\uD574\uC655\uC131",
72
- Pluto: "\uBA85\uC655\uC131",
73
- Chiron: "\uD0A4\uB860",
74
- NorthNode: "\uBD81\uAD50\uC810",
75
- SouthNode: "\uB0A8\uAD50\uC810"
76
- };
77
- var PLANET_BODIES = [
78
- ["Sun", 0],
79
- // SE_SUN
80
- ["Moon", 1],
81
- // SE_MOON
82
- ["Mercury", 2],
83
- // SE_MERCURY
84
- ["Venus", 3],
85
- // SE_VENUS
86
- ["Mars", 4],
87
- // SE_MARS
88
- ["Jupiter", 5],
89
- // SE_JUPITER
90
- ["Saturn", 6],
91
- // SE_SATURN
92
- ["Uranus", 7],
93
- // SE_URANUS
94
- ["Neptune", 8],
95
- // SE_NEPTUNE
96
- ["Pluto", 9],
97
- // SE_PLUTO
98
- ["Chiron", 15],
99
- // SE_CHIRON
100
- ["NorthNode", 10]
101
- // SE_MEAN_NODE
102
- ];
103
- var ASPECT_SYMBOLS = {
104
- conjunction: "\u260C",
105
- sextile: "\u26B9",
106
- square: "\u25A1",
107
- trine: "\u25B3",
108
- opposition: "\u260D"
109
- };
110
- var ASPECT_DEFS = [
111
- { type: "conjunction", angle: 0, maxOrb: 8 },
112
- { type: "sextile", angle: 60, maxOrb: 6 },
113
- { type: "square", angle: 90, maxOrb: 8 },
114
- { type: "trine", angle: 120, maxOrb: 8 },
115
- { type: "opposition", angle: 180, maxOrb: 8 }
116
- ];
117
- var ROMAN = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"];
118
- var HOUSE_SYSTEMS = [
119
- ["P", "Placidus"],
120
- ["K", "Koch"],
121
- ["O", "Porphyrius"],
122
- ["R", "Regiomontanus"],
123
- ["C", "Campanus"],
124
- ["E", "Equal"],
125
- ["W", "Whole Sign"],
126
- ["B", "Alcabitus"],
127
- ["M", "Morinus"],
128
- ["T", "Topocentric"]
129
- ];
130
- var sweInstance = null;
131
- var initPromise = null;
132
- async function getSwissEph() {
133
- if (sweInstance) return sweInstance;
134
- if (initPromise) return initPromise;
135
- initPromise = (async () => {
136
- const swe = new SwissEph();
137
- await swe.initSwissEph();
138
- sweInstance = swe;
139
- return swe;
140
- })();
141
- return initPromise;
142
- }
143
- function lonToSign(lon) {
144
- return ZODIAC_SIGNS[Math.trunc(normalizeDeg(lon) / 30)];
145
- }
146
- function normalizeDeg(deg) {
147
- return (deg % 360 + 360) % 360;
148
- }
149
- function degreeInSign(lon) {
150
- return normalizeDeg(lon) % 30;
151
- }
152
- function angularDifference(lon1, lon2) {
153
- let diff = Math.abs(normalizeDeg(lon1) - normalizeDeg(lon2));
154
- if (diff > 180) diff = 360 - diff;
155
- return diff;
156
- }
157
- function formatDegree(lon) {
158
- const d = degreeInSign(lon);
159
- const deg = Math.trunc(d);
160
- const min = Math.trunc((d - deg) * 60);
161
- return `${deg}\xB0${String(min).padStart(2, "0")}'`;
162
- }
163
- function findHouse(planetLon, cusps) {
164
- const lon = normalizeDeg(planetLon);
165
- for (let i = 1; i <= 12; i++) {
166
- const start = normalizeDeg(cusps[i]);
167
- const end = normalizeDeg(cusps[i === 12 ? 1 : i + 1]);
168
- if (start < end) {
169
- if (lon >= start && lon < end) return i;
170
- } else {
171
- if (lon >= start || lon < end) return i;
172
- }
173
- }
174
- return 1;
175
- }
176
- function calculateAspects(planets) {
177
- const aspects = [];
178
- for (let i = 0; i < planets.length; i++) {
179
- for (let j = i + 1; j < planets.length; j++) {
180
- const p1 = planets[i];
181
- const p2 = planets[j];
182
- const diff = angularDifference(p1.longitude, p2.longitude);
183
- for (const def of ASPECT_DEFS) {
184
- const orb = Math.abs(diff - def.angle);
185
- if (orb <= def.maxOrb) {
186
- aspects.push({
187
- planet1: p1.id,
188
- planet2: p2.id,
189
- type: def.type,
190
- angle: def.angle,
191
- orb: Math.round(orb * 10) / 10
192
- });
193
- }
194
- }
195
- }
196
- }
197
- aspects.sort((a, b) => a.orb - b.orb);
198
- return aspects;
199
- }
200
- async function calculateNatal(input, houseSystem = "P") {
201
- const swe = await getSwissEph();
202
- const lat = input.latitude ?? DEFAULT_LAT;
203
- const lon = input.longitude ?? DEFAULT_LON;
204
- const utHourDecimal = input.hour + input.minute / 60 - 9;
205
- let utYear = input.year;
206
- let utMonth = input.month;
207
- let utDay = input.day;
208
- let utHour = utHourDecimal;
209
- if (utHour < 0) {
210
- utHour += 24;
211
- const d = new Date(utYear, utMonth - 1, utDay - 1);
212
- utYear = d.getFullYear();
213
- utMonth = d.getMonth() + 1;
214
- utDay = d.getDate();
215
- } else if (utHour >= 24) {
216
- utHour -= 24;
217
- const d = new Date(utYear, utMonth - 1, utDay + 1);
218
- utYear = d.getFullYear();
219
- utMonth = d.getMonth() + 1;
220
- utDay = d.getDate();
221
- }
222
- const jd = swe.julday(utYear, utMonth, utDay, utHour);
223
- const housesEx = swe.houses_ex.bind(swe);
224
- const { cusps, ascmc } = housesEx(jd, 0, lat, lon, houseSystem);
225
- const calcFlags = swe.SEFLG_SWIEPH | swe.SEFLG_SPEED;
226
- const planets = [];
227
- for (const [id, bodyNum] of PLANET_BODIES) {
228
- const pos = swe.calc_ut(jd, bodyNum, calcFlags);
229
- const longitude = pos[0];
230
- planets.push({
231
- id,
232
- longitude,
233
- latitude: pos[1],
234
- speed: pos[3],
235
- sign: lonToSign(longitude),
236
- degreeInSign: degreeInSign(longitude),
237
- isRetrograde: pos[3] < 0,
238
- house: findHouse(longitude, cusps)
239
- });
240
- }
241
- const northNode = planets.find((p) => p.id === "NorthNode");
242
- const southLon = normalizeDeg(northNode.longitude + 180);
243
- planets.push({
244
- id: "SouthNode",
245
- longitude: southLon,
246
- latitude: -northNode.latitude,
247
- speed: northNode.speed,
248
- sign: lonToSign(southLon),
249
- degreeInSign: degreeInSign(southLon),
250
- isRetrograde: false,
251
- house: findHouse(southLon, cusps)
252
- });
253
- const houses = [];
254
- for (let i = 1; i <= 12; i++) {
255
- const cuspLon = cusps[i];
256
- houses.push({
257
- number: i,
258
- cuspLongitude: cuspLon,
259
- sign: lonToSign(cuspLon),
260
- degreeInSign: degreeInSign(cuspLon)
261
- });
262
- }
263
- const ascLon = ascmc[0];
264
- const mcLon = ascmc[1];
265
- const descLon = normalizeDeg(ascLon + 180);
266
- const icLon = normalizeDeg(mcLon + 180);
267
- const angles = {
268
- asc: { longitude: ascLon, sign: lonToSign(ascLon), degreeInSign: degreeInSign(ascLon) },
269
- mc: { longitude: mcLon, sign: lonToSign(mcLon), degreeInSign: degreeInSign(mcLon) },
270
- desc: { longitude: descLon, sign: lonToSign(descLon), degreeInSign: degreeInSign(descLon) },
271
- ic: { longitude: icLon, sign: lonToSign(icLon), degreeInSign: degreeInSign(icLon) }
272
- };
273
- const aspectPlanets = planets.filter((p) => p.id !== "SouthNode");
274
- const aspects = calculateAspects(aspectPlanets);
275
- return { input, planets, houses, angles, aspects };
276
- }
277
-
278
- export {
279
- ZODIAC_SIGNS,
280
- ZODIAC_SYMBOLS,
281
- ZODIAC_KO,
282
- PLANET_SYMBOLS,
283
- PLANET_KO,
284
- ASPECT_SYMBOLS,
285
- ROMAN,
286
- HOUSE_SYSTEMS,
287
- getSwissEph,
288
- lonToSign,
289
- normalizeDeg,
290
- formatDegree,
291
- calculateNatal
292
- };