saju8z 1.1.0 → 1.2.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.
- package/README.md +156 -13
- package/bin/saju8z.js +79 -10
- package/dist/core.cjs +34 -5
- package/dist/core.js +34 -5
- package/dist/format.cjs +15 -3
- package/dist/format.js +15 -3
- package/dist/index.cjs +64 -8
- package/dist/index.js +64 -8
- package/dist/types/application/calculateSajuChart.d.ts +7 -1
- package/dist/types/application/normalizeDateTime.d.ts +4 -0
- package/dist/types/calendar/dateMath.d.ts +1 -0
- package/dist/types/calendar/solarTerms.d.ts +1 -0
- package/dist/types/config/saju8z.d.ts +1 -1
- package/dist/types/contracts/sajuChart.d.ts +20 -2
- package/dist/types/format.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/input/parseSajuChartInput.d.ts +2 -2
- package/dist/types/output/chartPresentation.d.ts +3 -3
- package/dist/types/saju/calculateDayPillar.d.ts +1 -0
- package/dist/types/saju/calculateMonthPillar.d.ts +1 -0
- package/dist/types/saju/calculateTenGods.d.ts +1 -0
- package/dist/types/saju/calculateThreePillars.d.ts +3 -0
- package/dist/types-cjs/application/calculateSajuChart.d.ts +7 -1
- package/dist/types-cjs/application/normalizeDateTime.d.ts +4 -0
- package/dist/types-cjs/calendar/dateMath.d.ts +1 -0
- package/dist/types-cjs/calendar/solarTerms.d.ts +1 -0
- package/dist/types-cjs/config/saju8z.d.ts +1 -1
- package/dist/types-cjs/contracts/sajuChart.d.ts +20 -2
- package/dist/types-cjs/format.d.ts +1 -1
- package/dist/types-cjs/index.d.ts +1 -1
- package/dist/types-cjs/input/parseSajuChartInput.d.ts +2 -2
- package/dist/types-cjs/output/chartPresentation.d.ts +3 -3
- package/dist/types-cjs/saju/calculateDayPillar.d.ts +1 -0
- package/dist/types-cjs/saju/calculateMonthPillar.d.ts +1 -0
- package/dist/types-cjs/saju/calculateTenGods.d.ts +1 -0
- package/dist/types-cjs/saju/calculateThreePillars.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# saju8z
|
|
2
2
|
|
|
3
|
-
생년월일시로 사주팔자와 십성을
|
|
3
|
+
생년월일시로 사주팔자와 십성을 계산하고, 시간을 모르면 삼주(년·월·일)를 제공하는 만세력 CLI 라이브러리입니다.
|
|
4
4
|
|
|
5
5
|
양력/음력/윤달을 지원하고, 결과를 텍스트/JSON/AI 전달용 프롬프트로 출력합니다.
|
|
6
6
|
|
|
7
|
-
**Node.js 22 이상과 npm**이 필요합니다. 터미널에서 바로 사용하려면 `--date
|
|
7
|
+
**Node.js 22 이상과 npm**이 필요합니다. 터미널에서 바로 사용하려면 `--date`·`--time` 또는 `--dt`를 본인의 생년월일시로 바꾸세요.
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
|
|
@@ -27,6 +27,132 @@ saju8z --date 2000-02-25 --time 04:10
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
### 인자 없이 실행하고 날짜·시각 입력하기
|
|
31
|
+
|
|
32
|
+
옵션 없이 `saju8z`를 실행하면 생년월일과 출생 시각을 차례로 질문합니다. 아래처럼 값을 입력한 뒤 각각 Enter를 누르세요.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
saju8z
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
입력 예시:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
생년월일과 출생 시각을 입력하세요. 양력·현재 GMT 시차로 계산합니다.
|
|
42
|
+
생년월일 (YYYY-MM-DD, 예: 1998-03-05): 1998-03-05
|
|
43
|
+
출생 시각 (HH:mm, 예: 11:00 / 시간을 모르면 비워두고 Enter): 11:00
|
|
44
|
+
|
|
45
|
+
[만세력]
|
|
46
|
+
...
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- 날짜는 `1998-03-05`처럼 연도 4자리·월 2자리·일 2자리를 하이픈으로 구분합니다.
|
|
50
|
+
- 시각은 `11:00`처럼 24시간제의 시·분을 콜론으로 구분합니다. 오후 11시는 `23:00`, 자정은 `00:00`입니다.
|
|
51
|
+
- 시간을 모르면 시각 질문에서 아무것도 적지 않고 Enter를 누르세요. 삼주만 출력합니다.
|
|
52
|
+
- 시간을 입력하면 **양력·실행 환경의 현재 GMT 시차·기본 텍스트 형식**으로 사주를 출력합니다. 시간을 생략하면 양력 날짜 기준으로 계산하며 GMT 환산과 -30분 보정은 생략합니다.
|
|
53
|
+
- 잘못된 날짜·시각이나 빈 날짜는 오류로 종료합니다. 빈 시각은 시간 미상으로 처리합니다. 다시 실행해 입력하세요. 음력·윤달·고정 시차·다른 출력 형식은 아래 CLI 옵션을 사용하세요.
|
|
54
|
+
|
|
55
|
+
대화형 입력은 **인자가 전혀 없을 때만** 시작합니다. 옵션을 전달하면 `--date` 또는 `--dt`가 필요하며, `--time`은 선택입니다. 입력 안내는 표준 오류(stderr), 계산 결과는 표준 출력(stdout)에 기록합니다.
|
|
56
|
+
|
|
57
|
+
### 날짜와 시각을 한 번에 입력하기
|
|
58
|
+
|
|
59
|
+
`--dt`는 날짜만 적는 **`YYYYMMDD` 8자리**와 시각까지 적는 **`YYYYMMDDHHmm` 12자리**를 지원합니다. `19980305`는 `--date 1998-03-05`와 같으며 삼주를 출력합니다. `199803051100`은 `--date 1998-03-05 --time 11:00`과 같은 사주를 출력합니다.
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
saju8z --dt 19980305
|
|
63
|
+
saju8z --dt 199803051100
|
|
64
|
+
saju8z --dt 199803051100 --gmt +09:00 --format json
|
|
65
|
+
saju8z --dt=199803051100 --gmt +09:00 --format prompt
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**옵션으로 실행할 때는 `--date` 또는 `--dt`를 입력해야 합니다. `--time`은 선택입니다.** `--dt`와 `--date`·`--time`을 혼용하면 오류가 발생합니다. 월·일·시·분은 각각 두 자리로 입력하며, 날짜와 시각의 유효성 검사는 기존 입력 방식과 같습니다. 시간이 있으면 `--gmt` 생략 시 현재 시차를 사용합니다. 시간이 없으면 시차 환산을 생략합니다. `--calendar lunar`·`--leap`는 두 방식 모두 사용할 수 있습니다.
|
|
69
|
+
|
|
70
|
+
### 시간을 모를 때 삼주 출력
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
saju8z --date 1998-03-05
|
|
74
|
+
saju8z --dt 19980305
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
위 두 명령은 동일한 삼주 결과를 반환합니다.
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
|
|
81
|
+
[만세력]
|
|
82
|
+
양력 날짜: 1998-03-05
|
|
83
|
+
출생 시각: 미상 (삼주만 제공하며 시주는 추정하거나 해석하지 않습니다.)
|
|
84
|
+
시간 미상으로 GMT 환산과 -30분 보정은 적용하지 않았습니다.
|
|
85
|
+
일간: 신금(辛金)
|
|
86
|
+
|
|
87
|
+
년주: 무인(戊寅)
|
|
88
|
+
- 천간: 무(戊), 토(土), 정인
|
|
89
|
+
- 지지: 인(寅), 목(木), 정재
|
|
90
|
+
|
|
91
|
+
월주: 갑인(甲寅)
|
|
92
|
+
- 천간: 갑(甲), 목(木), 정재
|
|
93
|
+
- 지지: 인(寅), 목(木), 정재
|
|
94
|
+
|
|
95
|
+
일주: 신해(辛亥)
|
|
96
|
+
- 천간: 신(辛), 금(金), 본원
|
|
97
|
+
- 지지: 해(亥), 수(水), 상관
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
시각이 없으면 입력 날짜를 그대로 사용합니다. 음력 입력은 양력으로 변환한 날짜를 사용하며, GMT 환산과 -30분 보정은 적용하지 않습니다. 입춘·절입 당일부터 새 년주·월주를 적용합니다. 이 기준은 출생 시각을 추정한 결과가 아닙니다.
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
saju8z --dt 19980305 --format json
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
<details>
|
|
107
|
+
<summary>시간 미상 JSON 결과 펼치기</summary>
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"normalizedDateTime": {
|
|
112
|
+
"year": 1998,
|
|
113
|
+
"month": 3,
|
|
114
|
+
"day": 5,
|
|
115
|
+
"hour": null,
|
|
116
|
+
"minute": null
|
|
117
|
+
},
|
|
118
|
+
"calculationDateTime": {
|
|
119
|
+
"year": 1998,
|
|
120
|
+
"month": 3,
|
|
121
|
+
"day": 5,
|
|
122
|
+
"hour": null,
|
|
123
|
+
"minute": null
|
|
124
|
+
},
|
|
125
|
+
"fourPillars": {
|
|
126
|
+
"year": {
|
|
127
|
+
"stem": "무",
|
|
128
|
+
"branch": "인"
|
|
129
|
+
},
|
|
130
|
+
"month": {
|
|
131
|
+
"stem": "갑",
|
|
132
|
+
"branch": "인"
|
|
133
|
+
},
|
|
134
|
+
"day": {
|
|
135
|
+
"stem": "신",
|
|
136
|
+
"branch": "해"
|
|
137
|
+
},
|
|
138
|
+
"hour": null
|
|
139
|
+
},
|
|
140
|
+
"tenGods": {
|
|
141
|
+
"yearStem": "정인",
|
|
142
|
+
"yearBranch": "정재",
|
|
143
|
+
"monthStem": "정재",
|
|
144
|
+
"monthBranch": "정재",
|
|
145
|
+
"dayBranch": "상관",
|
|
146
|
+
"hourStem": null,
|
|
147
|
+
"hourBranch": null
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
시간 미상 결과는 `fourPillars.hour`, `tenGods.hourStem`, `tenGods.hourBranch`가 `null`이며, `normalizedDateTime`·`calculationDateTime`의 `hour`·`minute`도 `null`입니다. 두 날짜 객체는 같은 양력 날짜를 담습니다. 텍스트·프롬프트에는 년주·월주·일주만 표시하고, 프롬프트에는 시주를 추정하거나 해석하지 않도록 안내합니다.
|
|
155
|
+
|
|
30
156
|
### 출력 형식 선택
|
|
31
157
|
|
|
32
158
|
|
|
@@ -50,6 +176,7 @@ saju8z --date 2000-02-25 --time 04:10
|
|
|
50
176
|
|
|
51
177
|
|
|
52
178
|
```text
|
|
179
|
+
|
|
53
180
|
[만세력]
|
|
54
181
|
양력 환산 시각: 2000-02-25 04:10 (GMT+09:00)
|
|
55
182
|
-30분 보정 후 계산 시각: 2000-02-25 03:40
|
|
@@ -212,8 +339,9 @@ npx --yes saju8z --date 2017-05-01 --time 12:00 --gmt +09:00 --calendar lunar --
|
|
|
212
339
|
|
|
213
340
|
| 옵션 | 필수 | 기본값·설명 |
|
|
214
341
|
| -------------- | --- | ----------------------------------------------------- |
|
|
215
|
-
| `--
|
|
216
|
-
| `--
|
|
342
|
+
| `--dt` | 선택 | 날짜 `YYYYMMDD` 8자리 또는 날짜·시각 `YYYYMMDDHHmm` 12자리 |
|
|
343
|
+
| `--date` | 조건부 | 생년월일 `YYYY-MM-DD`. 옵션 실행 시 `--dt`가 없으면 필수 |
|
|
344
|
+
| `--time` | 아니요 | 출생 시각 `HH:mm`, `00:00`\~`23:59`. 생략하면 삼주 출력 |
|
|
217
345
|
| `--gmt` | 아니요 | 고정 시차 `±HH:mm`, `-12:00`\~`+14:00` 기본값은 실행 환경의 현재 GMT |
|
|
218
346
|
| `--calendar` | 아니요 | `solar`(기본, 양력) 또는 `lunar`(한국 음력) |
|
|
219
347
|
| `--leap` | 아니요 | 음력 윤달일 때 지정. `--calendar lunar`와 함께 사용 |
|
|
@@ -223,7 +351,7 @@ npx --yes saju8z --date 2017-05-01 --time 12:00 --gmt +09:00 --calendar lunar --
|
|
|
223
351
|
|
|
224
352
|
시차는 `--gmt -05:00` 또는 `--gmt=-05:00`처럼 전달합니다.
|
|
225
353
|
|
|
226
|
-
`--gmt`를 생략하면 출생일 당시가 아닌 **실행 시점의 GMT 시차**를 사용합니다. 한국 표준시 환경에서는 `+09:00`이며, 서머타임을 사용하는 환경에서는 현재 서머타임도 반영됩니다. 출생 당시 위치의 시차로 계산하려면 해당 시차를 직접 지정하세요.
|
|
354
|
+
`--gmt`를 생략하면 출생일 당시가 아닌 **실행 시점의 GMT 시차**를 사용합니다. 한국 표준시 환경에서는 `+09:00`이며, 서머타임을 사용하는 환경에서는 현재 서머타임도 반영됩니다. 출생 당시 위치의 시차로 계산하려면 해당 시차를 직접 지정하세요. 시간 미상일 때는 `--gmt` 값에 관계없이 날짜 기준 삼주를 계산합니다. 전달한 GMT 값의 형식과 범위는 계속 검증합니다.
|
|
227
355
|
|
|
228
356
|
|
|
229
357
|
|
|
@@ -247,6 +375,17 @@ console.log(formatSajuChart(result, "prompt")); // AI 전달용 프롬프트 문
|
|
|
247
375
|
|
|
248
376
|
|
|
249
377
|
|
|
378
|
+
시간을 모르면 라이브러리에서도 `time`을 생략하거나 `undefined`로 전달합니다.
|
|
379
|
+
|
|
380
|
+
```ts
|
|
381
|
+
const unknown = calculateSajuChart({ date: "1998-03-05", gmt: "+09:00" });
|
|
382
|
+
console.log(unknown.fourPillars.hour); // null
|
|
383
|
+
console.log(unknown.normalizedDateTime.hour); // null
|
|
384
|
+
console.log(formatSajuChart(unknown)); // 년·월·일 삼주
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
시간을 명시한 호출은 `SajuChartResultWithTime`, 생략한 호출은 `SajuChartResultWithoutTime`으로 추론됩니다. `SajuChartResult`는 두 결과의 유니온입니다. `time`이 선택적인 `SajuChartInput` 변수를 전달하면 결과도 유니온이므로 시주를 사용하기 전에 `null`을 확인하세요. 두 결과 타입은 `saju8z`와 `saju8z/format`에서 가져올 수 있습니다. 저수준 `saju8z/core`의 기존 사주 타입과 함수는 그대로 사용합니다.
|
|
388
|
+
|
|
250
389
|
## 입력
|
|
251
390
|
|
|
252
391
|
`calculateSajuChart(input)`은 다음 객체를 받습니다.
|
|
@@ -255,13 +394,13 @@ console.log(formatSajuChart(result, "prompt")); // AI 전달용 프롬프트 문
|
|
|
255
394
|
| 필드 | 타입 | 필수 | 설명 |
|
|
256
395
|
| ----------- | -------------------- | --- | ------------------------------------------ |
|
|
257
396
|
| `date` | `string` | 예 | `YYYY-MM-DD`. 선택한 달력 기준의 날짜 |
|
|
258
|
-
| `time` | `string` |
|
|
397
|
+
| `time` | `string` | 아니요 | `HH:mm`, `00:00`\~`23:59`. 생략 또는 `undefined`이면 시간 미상 |
|
|
259
398
|
| `gmt` | `string` | 예 | 부호를 포함한 고정 시차 `±HH:mm`, `-12:00`\~`+14:00` |
|
|
260
399
|
| `calendar` | `"solar"`, `"lunar"` | 아니요 | 양력 또는 한국 음력. 기본값 `"solar"` |
|
|
261
400
|
| `leapMonth` | `boolean` | 아니요 | 음력 윤달 여부. 기본값 `false`, 음력에서만 `true` 허용 |
|
|
262
401
|
|
|
263
402
|
|
|
264
|
-
라이브러리 API의 `gmt`는 출생 당시 날짜·시간의 시차를 직접 지정합니다. 예를 들어 한국 표준시는 `+09:00`, UTC는 `+00:00`입니다. 실행 환경의 시간대나 지역 이름으로 자동 추정하지 않습니다.
|
|
403
|
+
라이브러리 API의 `gmt`는 출생 당시 날짜·시간의 시차를 직접 지정합니다. 예를 들어 한국 표준시는 `+09:00`, UTC는 `+00:00`입니다. 실행 환경의 시간대나 지역 이름으로 자동 추정하지 않습니다. `gmt`는 시간 미상 입력에서도 필수이며 형식을 검증하지만, 날짜 기준 계산에는 사용하지 않습니다. `time: ""`·`time: null`은 허용하지 않습니다. CLI에서도 `--time` 값을 비우는 대신 옵션을 생략하고, 대화형 질문에서만 빈 시각을 허용합니다.
|
|
265
404
|
|
|
266
405
|
음력 윤달은 다음과 같이 입력합니다.
|
|
267
406
|
|
|
@@ -285,10 +424,10 @@ const result = calculateSajuChart({
|
|
|
285
424
|
|
|
286
425
|
| 필드 | 내용 |
|
|
287
426
|
| --------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
288
|
-
| `normalizedDateTime` |
|
|
289
|
-
| `calculationDateTime` |
|
|
290
|
-
| `fourPillars` | `year`, `month`, `day`, `hour`의 사주팔자.
|
|
291
|
-
| `tenGods` | 일간 기준 십성. `yearStem`, `yearBranch`, `monthStem`, `monthBranch`, `dayBranch`, `hourStem`, `hourBranch` |
|
|
427
|
+
| `normalizedDateTime` | 시간이 있으면 GMT+09:00으로 환산한 양력 시각. 시간이 없으면 양력 날짜와 `hour: null`, `minute: null` |
|
|
428
|
+
| `calculationDateTime` | 시간이 있으면 -30분 보정한 시각. 시간이 없으면 `normalizedDateTime`과 동일한 날짜·null 시각 |
|
|
429
|
+
| `fourPillars` | `year`, `month`, `day`, `hour`의 사주팔자. 시간이 없으면 `hour: null` |
|
|
430
|
+
| `tenGods` | 일간 기준 십성. `yearStem`, `yearBranch`, `monthStem`, `monthBranch`, `dayBranch`, `hourStem`, `hourBranch`. 시간 미상이면 마지막 두 필드는 `null` |
|
|
292
431
|
|
|
293
432
|
|
|
294
433
|
천간·지지·십성은 `"병"`, `"진"`, `"식신"`과 같은 한국어 문자열입니다. 일간 자체의 십성 필드는 없으며, 만세력 텍스트에서는 `본원`으로 표시합니다.
|
|
@@ -312,13 +451,17 @@ const result = calculateSajuChart({
|
|
|
312
451
|
|
|
313
452
|
## 계산 기준과 지원 범위
|
|
314
453
|
|
|
454
|
+
시간을 입력한 경우 기존 계산 기준을 적용합니다.
|
|
455
|
+
|
|
315
456
|
1. 음력이면 양력으로 변환합니다.
|
|
316
457
|
2. 입력 GMT에서 GMT+09:00으로 환산합니다.
|
|
317
458
|
3. -30분을 보정한 시각으로 사주팔자를 계산합니다.
|
|
318
459
|
|
|
319
|
-
|
|
460
|
+
시간을 생략한 경우 음력 변환만 수행하고, 시차 환산과 -30분 보정 없이 해당 양력 날짜로 삼주를 계산합니다. 입춘·절입 당일부터 새 년주·월주를 적용하고 일주는 입력 날짜 기준입니다. 임의의 자정·정오를 출생 시각으로 대입하지 않습니다.
|
|
461
|
+
|
|
462
|
+
시간을 입력한 경우 년주는 입춘, 월주는 프로젝트의 고정 절입 시각 표, 일주는 자정을 기준으로 합니다. 고정 절입 표는 실제 연도별 천문 절기 시각과 차이가 있을 수 있습니다. 서머타임·역사적 시차·출생지 경도 보정은 자동 적용하지 않습니다.
|
|
320
463
|
|
|
321
|
-
양력 입력과 GMT+09:00 환산 날짜는 1900~2100년을 지원합니다. 음력은 1900년부터 음력 2050년 11월 18일까지의 유효 날짜를 지원합니다. -30분 보정으로 1900년 첫날이 전년 말로 이동할 수 있습니다.
|
|
464
|
+
양력 입력과 GMT+09:00 환산 날짜는 1900~2100년을 지원합니다. 음력은 1900년부터 음력 2050년 11월 18일까지의 유효 날짜를 지원합니다. 시간을 입력하면 -30분 보정으로 1900년 첫날이 전년 말로 이동할 수 있습니다. 시간이 없으면 해당 날짜를 보존합니다.
|
|
322
465
|
|
|
323
466
|
성별 입력은 필요하지 않습니다. 대운·세운·운세·성격 해석 기능은 제공하지 않습니다.
|
|
324
467
|
|
package/bin/saju8z.js
CHANGED
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import process from "node:process";
|
|
3
|
+
import { createInterface } from "node:readline";
|
|
3
4
|
import { calculateSajuChart, formatSajuChart, UserInputError } from "../dist/index.js";
|
|
4
5
|
|
|
5
|
-
const HELP_TEXT = `사용법: saju8z
|
|
6
|
+
const HELP_TEXT = `사용법: saju8z
|
|
7
|
+
saju8z --date YYYY-MM-DD [--time HH:mm] [--gmt ±HH:mm] [옵션]
|
|
8
|
+
saju8z --dt YYYYMMDD[HHmm] [--gmt ±HH:mm] [옵션]
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
인자 없이 실행하면 날짜와 시각을 차례로 입력받습니다.
|
|
11
|
+
날짜 예: 1998-03-05 / 시각 예: 11:00 (24시간제, 모르면 비워두고 Enter)
|
|
12
|
+
대화형 입력은 양력·현재 GMT 시차·text 출력을 사용합니다.
|
|
13
|
+
|
|
14
|
+
옵션으로 실행할 때 필수 입력 (둘 중 하나):
|
|
15
|
+
--dt 생년월일 8자리 (YYYYMMDD) 또는 생년월일시 12자리 (YYYYMMDDHHmm)
|
|
8
16
|
--date 생년월일 (YYYY-MM-DD)
|
|
9
|
-
--time 출생 시각 (HH:mm, 00:00~23:59)
|
|
17
|
+
--time 출생 시각 (선택, HH:mm, 00:00~23:59). 생략하면 삼주만 계산
|
|
18
|
+
--date 또는 --dt는 필수이며, --dt와 --date·--time은 혼용할 수 없습니다.
|
|
19
|
+
시간이 없으면 입력 날짜 기준으로 삼주를 계산하고 GMT 환산·-30분 보정은 생략합니다.
|
|
10
20
|
|
|
11
21
|
옵션:
|
|
12
22
|
--gmt 고정 GMT 시차 (기본: 실행 환경의 현재 시차, -12:00~+14:00)
|
|
@@ -16,6 +26,9 @@ const HELP_TEXT = `사용법: saju8z --date YYYY-MM-DD --time HH:mm [--gmt ±HH:
|
|
|
16
26
|
--help, -h 도움말
|
|
17
27
|
|
|
18
28
|
예제:
|
|
29
|
+
saju8z
|
|
30
|
+
saju8z --dt 19980305
|
|
31
|
+
saju8z --dt 199803051100
|
|
19
32
|
saju8z --date 2000-02-29 --time 00:10
|
|
20
33
|
saju8z --date 2000-02-29 --time 00:10 --gmt +09:00
|
|
21
34
|
saju8z --date 2000-02-29 --time 00:10 --gmt=-05:00 --format json
|
|
@@ -32,7 +45,35 @@ function getCurrentGmtOffset() {
|
|
|
32
45
|
return `${sign}${hours}:${remainder}`;
|
|
33
46
|
}
|
|
34
47
|
|
|
35
|
-
|
|
48
|
+
async function readInteractiveArguments() {
|
|
49
|
+
const reader = createInterface({
|
|
50
|
+
input: process.stdin,
|
|
51
|
+
output: process.stderr,
|
|
52
|
+
terminal: Boolean(process.stdin.isTTY && process.stderr.isTTY),
|
|
53
|
+
crlfDelay: Infinity
|
|
54
|
+
});
|
|
55
|
+
const answers = reader[Symbol.asyncIterator]();
|
|
56
|
+
/** @param {string} prompt */
|
|
57
|
+
async function ask(prompt) {
|
|
58
|
+
process.stderr.write(prompt);
|
|
59
|
+
const answer = await answers.next();
|
|
60
|
+
if (answer.done) {
|
|
61
|
+
throw new UserInputError("입력이 종료되었습니다. --date 또는 --dt를 사용하세요.");
|
|
62
|
+
}
|
|
63
|
+
return answer.value.trim();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
process.stderr.write("생년월일과 출생 시각을 입력하세요. 양력·현재 GMT 시차로 계산합니다.\n");
|
|
68
|
+
const date = await ask("생년월일 (YYYY-MM-DD, 예: 1998-03-05): ");
|
|
69
|
+
const time = await ask("출생 시각 (HH:mm, 예: 11:00 / 시간을 모르면 비워두고 Enter): ");
|
|
70
|
+
return time ? ["--date", date, "--time", time] : ["--date", date];
|
|
71
|
+
} finally {
|
|
72
|
+
reader.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const VALUE_OPTIONS = new Set(["--dt", "--date", "--time", "--gmt", "--calendar", "--format"]);
|
|
36
77
|
|
|
37
78
|
/** @param {string[]} args */
|
|
38
79
|
function parseOptions(args) {
|
|
@@ -57,12 +98,35 @@ function parseOptions(args) {
|
|
|
57
98
|
return { values, leapMonth };
|
|
58
99
|
}
|
|
59
100
|
|
|
101
|
+
/** @param {Map<string, string>} values */
|
|
102
|
+
function resolveDateTime(values) {
|
|
103
|
+
const dt = values.get("--dt");
|
|
104
|
+
if (dt !== undefined) {
|
|
105
|
+
if (values.has("--date") || values.has("--time")) {
|
|
106
|
+
throw new UserInputError("--dt는 --date 또는 --time과 함께 사용할 수 없습니다.");
|
|
107
|
+
}
|
|
108
|
+
if (![8, 12].includes(dt.length) || !/^\d+$/.test(dt)) {
|
|
109
|
+
throw new UserInputError(
|
|
110
|
+
"--dt는 YYYYMMDD 형식의 8자리 또는 YYYYMMDDHHmm 형식의 12자리 숫자여야 합니다."
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
date: `${dt.slice(0, 4)}-${dt.slice(4, 6)}-${dt.slice(6, 8)}`,
|
|
115
|
+
...(dt.length === 12 ? { time: `${dt.slice(8, 10)}:${dt.slice(10, 12)}` } : {})
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const date = values.get("--date");
|
|
119
|
+
const time = values.get("--time");
|
|
120
|
+
if (!date) {
|
|
121
|
+
throw new UserInputError("--date 또는 --dt를 입력하세요.");
|
|
122
|
+
}
|
|
123
|
+
return { date, ...(time === undefined ? {} : { time }) };
|
|
124
|
+
}
|
|
125
|
+
|
|
60
126
|
/** @param {string[]} args */
|
|
61
127
|
function parseArguments(args) {
|
|
62
128
|
const { values, leapMonth } = parseOptions(args);
|
|
63
|
-
const date = values
|
|
64
|
-
const time = values.get("--time");
|
|
65
|
-
if (!date || !time) throw new UserInputError("--date, --time은 필수입니다.");
|
|
129
|
+
const { date, time } = resolveDateTime(values);
|
|
66
130
|
const gmt = values.get("--gmt") ?? getCurrentGmtOffset();
|
|
67
131
|
const calendar = values.get("--calendar") ?? "solar";
|
|
68
132
|
if (calendar !== "solar" && calendar !== "lunar")
|
|
@@ -70,7 +134,10 @@ function parseArguments(args) {
|
|
|
70
134
|
const format = values.get("--format") ?? "text";
|
|
71
135
|
if (format !== "text" && format !== "json" && format !== "prompt")
|
|
72
136
|
throw new UserInputError("출력 형식은 text, json 또는 prompt이어야 합니다.");
|
|
73
|
-
return {
|
|
137
|
+
return {
|
|
138
|
+
input: { date, ...(time === undefined ? {} : { time }), gmt, calendar, leapMonth },
|
|
139
|
+
format
|
|
140
|
+
};
|
|
74
141
|
}
|
|
75
142
|
|
|
76
143
|
try {
|
|
@@ -79,9 +146,11 @@ try {
|
|
|
79
146
|
if (showHelp) {
|
|
80
147
|
process.stdout.write(HELP_TEXT);
|
|
81
148
|
} else {
|
|
82
|
-
const
|
|
149
|
+
const inputArgs = args.length === 0 ? await readInteractiveArguments() : args;
|
|
150
|
+
const { input, format } = parseArguments(inputArgs);
|
|
83
151
|
const result = calculateSajuChart(input);
|
|
84
|
-
|
|
152
|
+
const leadingNewline = format === "text" ? "\n" : "";
|
|
153
|
+
process.stdout.write(`${leadingNewline}${formatSajuChart(result, format)}\n`);
|
|
85
154
|
}
|
|
86
155
|
} catch (error) {
|
|
87
156
|
process.stderr.write(
|
package/dist/core.cjs
CHANGED
|
@@ -37,7 +37,9 @@ __export(core_exports, {
|
|
|
37
37
|
addMinutes: () => addMinutes,
|
|
38
38
|
applySolarTimeCorrection: () => applySolarTimeCorrection,
|
|
39
39
|
branchIndex: () => branchIndex,
|
|
40
|
+
calculateDateTenGods: () => calculateDateTenGods,
|
|
40
41
|
calculateDayPillar: () => calculateDayPillar,
|
|
42
|
+
calculateDayPillarFromDate: () => calculateDayPillarFromDate,
|
|
41
43
|
calculateFourPillars: () => calculateFourPillars,
|
|
42
44
|
calculateHourBranch: () => calculateHourBranch,
|
|
43
45
|
calculateHourPillar: () => calculateHourPillar,
|
|
@@ -45,10 +47,12 @@ __export(core_exports, {
|
|
|
45
47
|
calculateTenGod: () => calculateTenGod,
|
|
46
48
|
calculateTenGods: () => calculateTenGods,
|
|
47
49
|
calculateYearPillar: () => calculateYearPillar,
|
|
50
|
+
compareLocalDate: () => compareLocalDate,
|
|
48
51
|
compareLocalDateTime: () => compareLocalDateTime,
|
|
49
52
|
daysInMonth: () => daysInMonth,
|
|
50
53
|
formatLocalDateTime: () => formatLocalDateTime,
|
|
51
54
|
formatPillar: () => formatPillar,
|
|
55
|
+
getMonthBranchBySolarDate: () => getMonthBranchBySolarDate,
|
|
52
56
|
getMonthBranchBySolarTerm: () => getMonthBranchBySolarTerm,
|
|
53
57
|
getSolarTermDateTime: () => getSolarTermDateTime,
|
|
54
58
|
hasLunarLeapMonth: () => hasLunarLeapMonth,
|
|
@@ -58,6 +62,7 @@ __export(core_exports, {
|
|
|
58
62
|
lunarMonthDays: () => lunarMonthDays,
|
|
59
63
|
lunarToSolar: () => lunarToSolar,
|
|
60
64
|
monthBranchesInOrder: () => monthBranchesInOrder,
|
|
65
|
+
monthPillarFromBranch: () => monthPillarFromBranch,
|
|
61
66
|
pillarFromIndex: () => pillarFromIndex,
|
|
62
67
|
positiveModulo: () => positiveModulo,
|
|
63
68
|
sexagenaryIndexOfPillar: () => sexagenaryIndexOfPillar,
|
|
@@ -74,7 +79,7 @@ var SUPPORTED_START_YEAR = 1900;
|
|
|
74
79
|
var SUPPORTED_END_YEAR = 2100;
|
|
75
80
|
|
|
76
81
|
// src/config/saju8z.ts
|
|
77
|
-
var SAJU8Z_VERSION = "1.
|
|
82
|
+
var SAJU8Z_VERSION = "1.2.0";
|
|
78
83
|
var SAJU8Z_CALCULATION_PROFILE = "saju8z-fixed-gmt-kst-minus30-v1";
|
|
79
84
|
var SAJU8Z_CORRECTION_MINUTES = -30;
|
|
80
85
|
|
|
@@ -312,6 +317,9 @@ function daysInMonth(year, month) {
|
|
|
312
317
|
function isValidDate(year, month, day) {
|
|
313
318
|
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth(year, month);
|
|
314
319
|
}
|
|
320
|
+
function compareLocalDate(left, right) {
|
|
321
|
+
return left.year - right.year || left.month - right.month || left.day - right.day;
|
|
322
|
+
}
|
|
315
323
|
function compareLocalDateTime(left, right) {
|
|
316
324
|
const keys = ["year", "month", "day", "hour", "minute"];
|
|
317
325
|
for (const key of keys) {
|
|
@@ -1823,11 +1831,23 @@ function getMonthBranchBySolarTerm(dateTime) {
|
|
|
1823
1831
|
}
|
|
1824
1832
|
return selected;
|
|
1825
1833
|
}
|
|
1834
|
+
function getMonthBranchBySolarDate(date) {
|
|
1835
|
+
const rules = [...SOLAR_TERM_RULES].sort((left, right) => left.month - right.month);
|
|
1836
|
+
let selected = "\uCD95";
|
|
1837
|
+
for (const rule of rules) {
|
|
1838
|
+
if (compareLocalDate(date, solarTermDateTime(date.year, rule)) >= 0)
|
|
1839
|
+
selected = rule.monthBranch;
|
|
1840
|
+
}
|
|
1841
|
+
return selected;
|
|
1842
|
+
}
|
|
1826
1843
|
|
|
1827
1844
|
// src/saju/calculateDayPillar.ts
|
|
1828
1845
|
var JDN_TO_SEXAGENARY_OFFSET = 49;
|
|
1829
1846
|
function calculateDayPillar(dateTime) {
|
|
1830
|
-
|
|
1847
|
+
return calculateDayPillarFromDate(dateTime);
|
|
1848
|
+
}
|
|
1849
|
+
function calculateDayPillarFromDate(date) {
|
|
1850
|
+
const jdn = julianDayNumber(date.year, date.month, date.day);
|
|
1831
1851
|
return pillarFromIndex(positiveModulo(jdn + JDN_TO_SEXAGENARY_OFFSET, 60));
|
|
1832
1852
|
}
|
|
1833
1853
|
|
|
@@ -1880,6 +1900,9 @@ var IN_MONTH_START_STEM_BY_YEAR_STEM = {
|
|
|
1880
1900
|
};
|
|
1881
1901
|
function calculateMonthPillar(dateTime, yearStem) {
|
|
1882
1902
|
const branch = getMonthBranchBySolarTerm(dateTime);
|
|
1903
|
+
return monthPillarFromBranch(branch, yearStem);
|
|
1904
|
+
}
|
|
1905
|
+
function monthPillarFromBranch(branch, yearStem) {
|
|
1883
1906
|
const offsetFromIn = positiveModulo(branchIndex(branch) - branchIndex("\uC778"), 12);
|
|
1884
1907
|
const stem = stemAt(IN_MONTH_START_STEM_BY_YEAR_STEM[yearStem] + offsetFromIn);
|
|
1885
1908
|
return { stem, branch };
|
|
@@ -1933,14 +1956,20 @@ function calculateTenGod(dayStem, targetStem) {
|
|
|
1933
1956
|
|
|
1934
1957
|
// src/saju/calculateTenGods.ts
|
|
1935
1958
|
function calculateTenGods(fourPillars) {
|
|
1959
|
+
const dayStem = fourPillars.day.stem;
|
|
1960
|
+
return {
|
|
1961
|
+
...calculateDateTenGods(fourPillars),
|
|
1962
|
+
hourStem: calculateTenGod(dayStem, fourPillars.hour.stem),
|
|
1963
|
+
hourBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.hour.branch].mainHiddenStem)
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
function calculateDateTenGods(fourPillars) {
|
|
1936
1967
|
const dayStem = fourPillars.day.stem;
|
|
1937
1968
|
return {
|
|
1938
1969
|
yearStem: calculateTenGod(dayStem, fourPillars.year.stem),
|
|
1939
1970
|
yearBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.year.branch].mainHiddenStem),
|
|
1940
1971
|
monthStem: calculateTenGod(dayStem, fourPillars.month.stem),
|
|
1941
1972
|
monthBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.month.branch].mainHiddenStem),
|
|
1942
|
-
dayBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.day.branch].mainHiddenStem)
|
|
1943
|
-
hourStem: calculateTenGod(dayStem, fourPillars.hour.stem),
|
|
1944
|
-
hourBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.hour.branch].mainHiddenStem)
|
|
1973
|
+
dayBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.day.branch].mainHiddenStem)
|
|
1945
1974
|
};
|
|
1946
1975
|
}
|
package/dist/core.js
CHANGED
|
@@ -5,7 +5,7 @@ var SUPPORTED_START_YEAR = 1900;
|
|
|
5
5
|
var SUPPORTED_END_YEAR = 2100;
|
|
6
6
|
|
|
7
7
|
// src/config/saju8z.ts
|
|
8
|
-
var SAJU8Z_VERSION = "1.
|
|
8
|
+
var SAJU8Z_VERSION = "1.2.0";
|
|
9
9
|
var SAJU8Z_CALCULATION_PROFILE = "saju8z-fixed-gmt-kst-minus30-v1";
|
|
10
10
|
var SAJU8Z_CORRECTION_MINUTES = -30;
|
|
11
11
|
|
|
@@ -243,6 +243,9 @@ function daysInMonth(year, month) {
|
|
|
243
243
|
function isValidDate(year, month, day) {
|
|
244
244
|
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth(year, month);
|
|
245
245
|
}
|
|
246
|
+
function compareLocalDate(left, right) {
|
|
247
|
+
return left.year - right.year || left.month - right.month || left.day - right.day;
|
|
248
|
+
}
|
|
246
249
|
function compareLocalDateTime(left, right) {
|
|
247
250
|
const keys = ["year", "month", "day", "hour", "minute"];
|
|
248
251
|
for (const key of keys) {
|
|
@@ -1754,11 +1757,23 @@ function getMonthBranchBySolarTerm(dateTime) {
|
|
|
1754
1757
|
}
|
|
1755
1758
|
return selected;
|
|
1756
1759
|
}
|
|
1760
|
+
function getMonthBranchBySolarDate(date) {
|
|
1761
|
+
const rules = [...SOLAR_TERM_RULES].sort((left, right) => left.month - right.month);
|
|
1762
|
+
let selected = "\uCD95";
|
|
1763
|
+
for (const rule of rules) {
|
|
1764
|
+
if (compareLocalDate(date, solarTermDateTime(date.year, rule)) >= 0)
|
|
1765
|
+
selected = rule.monthBranch;
|
|
1766
|
+
}
|
|
1767
|
+
return selected;
|
|
1768
|
+
}
|
|
1757
1769
|
|
|
1758
1770
|
// src/saju/calculateDayPillar.ts
|
|
1759
1771
|
var JDN_TO_SEXAGENARY_OFFSET = 49;
|
|
1760
1772
|
function calculateDayPillar(dateTime) {
|
|
1761
|
-
|
|
1773
|
+
return calculateDayPillarFromDate(dateTime);
|
|
1774
|
+
}
|
|
1775
|
+
function calculateDayPillarFromDate(date) {
|
|
1776
|
+
const jdn = julianDayNumber(date.year, date.month, date.day);
|
|
1762
1777
|
return pillarFromIndex(positiveModulo(jdn + JDN_TO_SEXAGENARY_OFFSET, 60));
|
|
1763
1778
|
}
|
|
1764
1779
|
|
|
@@ -1811,6 +1826,9 @@ var IN_MONTH_START_STEM_BY_YEAR_STEM = {
|
|
|
1811
1826
|
};
|
|
1812
1827
|
function calculateMonthPillar(dateTime, yearStem) {
|
|
1813
1828
|
const branch = getMonthBranchBySolarTerm(dateTime);
|
|
1829
|
+
return monthPillarFromBranch(branch, yearStem);
|
|
1830
|
+
}
|
|
1831
|
+
function monthPillarFromBranch(branch, yearStem) {
|
|
1814
1832
|
const offsetFromIn = positiveModulo(branchIndex(branch) - branchIndex("\uC778"), 12);
|
|
1815
1833
|
const stem = stemAt(IN_MONTH_START_STEM_BY_YEAR_STEM[yearStem] + offsetFromIn);
|
|
1816
1834
|
return { stem, branch };
|
|
@@ -1864,15 +1882,21 @@ function calculateTenGod(dayStem, targetStem) {
|
|
|
1864
1882
|
|
|
1865
1883
|
// src/saju/calculateTenGods.ts
|
|
1866
1884
|
function calculateTenGods(fourPillars) {
|
|
1885
|
+
const dayStem = fourPillars.day.stem;
|
|
1886
|
+
return {
|
|
1887
|
+
...calculateDateTenGods(fourPillars),
|
|
1888
|
+
hourStem: calculateTenGod(dayStem, fourPillars.hour.stem),
|
|
1889
|
+
hourBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.hour.branch].mainHiddenStem)
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
function calculateDateTenGods(fourPillars) {
|
|
1867
1893
|
const dayStem = fourPillars.day.stem;
|
|
1868
1894
|
return {
|
|
1869
1895
|
yearStem: calculateTenGod(dayStem, fourPillars.year.stem),
|
|
1870
1896
|
yearBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.year.branch].mainHiddenStem),
|
|
1871
1897
|
monthStem: calculateTenGod(dayStem, fourPillars.month.stem),
|
|
1872
1898
|
monthBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.month.branch].mainHiddenStem),
|
|
1873
|
-
dayBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.day.branch].mainHiddenStem)
|
|
1874
|
-
hourStem: calculateTenGod(dayStem, fourPillars.hour.stem),
|
|
1875
|
-
hourBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.hour.branch].mainHiddenStem)
|
|
1899
|
+
dayBranch: calculateTenGod(dayStem, BRANCH_INFO[fourPillars.day.branch].mainHiddenStem)
|
|
1876
1900
|
};
|
|
1877
1901
|
}
|
|
1878
1902
|
export {
|
|
@@ -1894,7 +1918,9 @@ export {
|
|
|
1894
1918
|
addMinutes,
|
|
1895
1919
|
applySolarTimeCorrection,
|
|
1896
1920
|
branchIndex,
|
|
1921
|
+
calculateDateTenGods,
|
|
1897
1922
|
calculateDayPillar,
|
|
1923
|
+
calculateDayPillarFromDate,
|
|
1898
1924
|
calculateFourPillars,
|
|
1899
1925
|
calculateHourBranch,
|
|
1900
1926
|
calculateHourPillar,
|
|
@@ -1902,10 +1928,12 @@ export {
|
|
|
1902
1928
|
calculateTenGod,
|
|
1903
1929
|
calculateTenGods,
|
|
1904
1930
|
calculateYearPillar,
|
|
1931
|
+
compareLocalDate,
|
|
1905
1932
|
compareLocalDateTime,
|
|
1906
1933
|
daysInMonth,
|
|
1907
1934
|
formatLocalDateTime,
|
|
1908
1935
|
formatPillar,
|
|
1936
|
+
getMonthBranchBySolarDate,
|
|
1909
1937
|
getMonthBranchBySolarTerm,
|
|
1910
1938
|
getSolarTermDateTime,
|
|
1911
1939
|
hasLunarLeapMonth,
|
|
@@ -1915,6 +1943,7 @@ export {
|
|
|
1915
1943
|
lunarMonthDays,
|
|
1916
1944
|
lunarToSolar,
|
|
1917
1945
|
monthBranchesInOrder,
|
|
1946
|
+
monthPillarFromBranch,
|
|
1918
1947
|
pillarFromIndex,
|
|
1919
1948
|
positiveModulo,
|
|
1920
1949
|
sexagenaryIndexOfPillar,
|
package/dist/format.cjs
CHANGED
|
@@ -242,7 +242,9 @@ function formatDayStem(stem) {
|
|
|
242
242
|
return `${stem}${ELEMENT_NAMES[element]}(${STEM_HANJA[stem].hanja}${element})`;
|
|
243
243
|
}
|
|
244
244
|
function describePillar(result, position) {
|
|
245
|
-
const
|
|
245
|
+
const value = result.fourPillars[position];
|
|
246
|
+
if (value === null) return null;
|
|
247
|
+
const { stem, branch } = value;
|
|
246
248
|
const stemHanja = STEM_HANJA[stem].hanja;
|
|
247
249
|
const branchHanja = BRANCH_HANJA[branch].hanja;
|
|
248
250
|
return {
|
|
@@ -259,17 +261,27 @@ function describePillar(result, position) {
|
|
|
259
261
|
|
|
260
262
|
// src/output/formatSajuText.ts
|
|
261
263
|
function formatDateTime(value) {
|
|
264
|
+
if (value.hour === null) {
|
|
265
|
+
return `${String(value.year).padStart(4, "0")}-${String(value.month).padStart(2, "0")}-${String(value.day).padStart(2, "0")}`;
|
|
266
|
+
}
|
|
262
267
|
return formatLocalDateTime(value).replace("T", " ");
|
|
263
268
|
}
|
|
264
269
|
function formatSajuText(result) {
|
|
265
270
|
const lines = [
|
|
266
271
|
"[\uB9CC\uC138\uB825]",
|
|
267
|
-
|
|
268
|
-
|
|
272
|
+
...result.normalizedDateTime.hour === null ? [
|
|
273
|
+
`\uC591\uB825 \uB0A0\uC9DC: ${formatDateTime(result.normalizedDateTime)}`,
|
|
274
|
+
"\uCD9C\uC0DD \uC2DC\uAC01: \uBBF8\uC0C1 (\uC0BC\uC8FC\uB9CC \uC81C\uACF5\uD558\uBA70 \uC2DC\uC8FC\uB294 \uCD94\uC815\uD558\uAC70\uB098 \uD574\uC11D\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.)",
|
|
275
|
+
"\uC2DC\uAC04 \uBBF8\uC0C1\uC73C\uB85C GMT \uD658\uC0B0\uACFC -30\uBD84 \uBCF4\uC815\uC740 \uC801\uC6A9\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."
|
|
276
|
+
] : [
|
|
277
|
+
`\uC591\uB825 \uD658\uC0B0 \uC2DC\uAC01: ${formatDateTime(result.normalizedDateTime)} (GMT+09:00)`,
|
|
278
|
+
`${SAJU8Z_CORRECTION_MINUTES}\uBD84 \uBCF4\uC815 \uD6C4 \uACC4\uC0B0 \uC2DC\uAC01: ${formatDateTime(result.calculationDateTime)}`
|
|
279
|
+
],
|
|
269
280
|
`\uC77C\uAC04: ${formatDayStem(result.fourPillars.day.stem)}`
|
|
270
281
|
];
|
|
271
282
|
for (const position of ["year", "month", "day", "hour"]) {
|
|
272
283
|
const pillar = describePillar(result, position);
|
|
284
|
+
if (pillar === null) continue;
|
|
273
285
|
lines.push(
|
|
274
286
|
"",
|
|
275
287
|
`${pillar.label}: ${pillar.name}`,
|