@lichta/core 2.1.0 → 2.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 +104 -19
- package/dist/index.d.mts +379 -62
- package/dist/index.d.ts +379 -62
- package/dist/index.js +462 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +433 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/styles/calendar-base.css +14 -0
package/dist/index.js
CHANGED
|
@@ -27,12 +27,41 @@ __export(index_exports, {
|
|
|
27
27
|
getAuspiciousHours: () => getAuspiciousHours,
|
|
28
28
|
getCalendarGrid: () => getCalendarGrid,
|
|
29
29
|
getDayCanChi: () => getDayCanChi,
|
|
30
|
+
getDayElement: () => getDayElement,
|
|
31
|
+
getDayElementIndex: () => getDayElementIndex,
|
|
30
32
|
getDayName: () => getDayName,
|
|
33
|
+
getElementName: () => getElementName,
|
|
34
|
+
getElementRelation: () => getElementRelation,
|
|
35
|
+
getElementRelationIndex: () => getElementRelationIndex,
|
|
36
|
+
getHaiBranchIndex: () => getHaiBranchIndex,
|
|
31
37
|
getHourCanChi: () => getHourCanChi,
|
|
38
|
+
getHourElement: () => getHourElement,
|
|
39
|
+
getHourElementIndex: () => getHourElementIndex,
|
|
40
|
+
getISOWeekNumber: () => getISOWeekNumber,
|
|
41
|
+
getInauspiciousHourIndices: () => getInauspiciousHourIndices,
|
|
42
|
+
getInauspiciousHours: () => getInauspiciousHours,
|
|
32
43
|
getMonthCanChi: () => getMonthCanChi,
|
|
44
|
+
getMonthElement: () => getMonthElement,
|
|
45
|
+
getMonthElementIndex: () => getMonthElementIndex,
|
|
33
46
|
getMonthName: () => getMonthName,
|
|
47
|
+
getSolarTerm: () => getSolarTerm,
|
|
48
|
+
getSolarTermName: () => getSolarTermName,
|
|
49
|
+
getSolarTermsInYear: () => getSolarTermsInYear,
|
|
50
|
+
getTruc: () => getTruc,
|
|
51
|
+
getTrucIndex: () => getTrucIndex,
|
|
52
|
+
getTrucName: () => getTrucName,
|
|
53
|
+
getTrucQuality: () => getTrucQuality,
|
|
54
|
+
getTrucQualityIndex: () => getTrucQualityIndex,
|
|
55
|
+
getTuHanhXungGroupIndex: () => getTuHanhXungGroupIndex,
|
|
56
|
+
getTuHanhXungGroupMembers: () => getTuHanhXungGroupMembers,
|
|
57
|
+
getWeekDayLabels: () => getWeekDayLabels,
|
|
58
|
+
getXungBranchIndex: () => getXungBranchIndex,
|
|
34
59
|
getYearDetails: () => getYearDetails,
|
|
35
60
|
getZodiacAnimal: () => getZodiacAnimal,
|
|
61
|
+
getZodiacConflicts: () => getZodiacConflicts,
|
|
62
|
+
isHai: () => isHai,
|
|
63
|
+
isTuHanhXung: () => isTuHanhXung,
|
|
64
|
+
isXung: () => isXung,
|
|
36
65
|
jdFromDate: () => jdFromDate,
|
|
37
66
|
jdToDate: () => jdToDate,
|
|
38
67
|
t: () => t
|
|
@@ -52,9 +81,6 @@ var HEAVENLY_STEMS = [
|
|
|
52
81
|
"Nh\xE2m",
|
|
53
82
|
"Qu\xFD"
|
|
54
83
|
];
|
|
55
|
-
function getStemWeight(index) {
|
|
56
|
-
return Math.floor(index / 2) + 1;
|
|
57
|
-
}
|
|
58
84
|
|
|
59
85
|
// src/constants/earthly-branches.ts
|
|
60
86
|
var EARTHLY_BRANCHES = [
|
|
@@ -71,12 +97,8 @@ var EARTHLY_BRANCHES = [
|
|
|
71
97
|
"Tu\u1EA5t",
|
|
72
98
|
"H\u1EE3i"
|
|
73
99
|
];
|
|
74
|
-
function getBranchWeight(index) {
|
|
75
|
-
const normalizedIndex = index % 6;
|
|
76
|
-
return Math.floor(normalizedIndex / 2);
|
|
77
|
-
}
|
|
78
100
|
|
|
79
|
-
// src/core/
|
|
101
|
+
// src/core/astronomical.ts
|
|
80
102
|
var PI = Math.PI;
|
|
81
103
|
function INT(d) {
|
|
82
104
|
return Math.floor(d);
|
|
@@ -132,7 +154,7 @@ function NewMoon(k) {
|
|
|
132
154
|
function getNewMoonDay(k, timeZone) {
|
|
133
155
|
return INT(NewMoon(k) + 0.5 + timeZone / 24);
|
|
134
156
|
}
|
|
135
|
-
function
|
|
157
|
+
function sunLongitudeDegrees(jdn, timeZone) {
|
|
136
158
|
const T = (jdn - 24515455e-1 - timeZone / 24) / 36525;
|
|
137
159
|
const T2 = T * T;
|
|
138
160
|
const dr = PI / 180;
|
|
@@ -142,11 +164,22 @@ function getSunLongitude(jdn, timeZone) {
|
|
|
142
164
|
DL = DL + (0.019993 - 101e-6 * T) * Math.sin(dr * 2 * M) + 29e-5 * Math.sin(dr * 3 * M);
|
|
143
165
|
let L = L0 + DL;
|
|
144
166
|
L = L - 360 * INT(L / 360);
|
|
145
|
-
return
|
|
167
|
+
return L;
|
|
168
|
+
}
|
|
169
|
+
function getSunLongitude(jdn, timeZone) {
|
|
170
|
+
return INT(sunLongitudeDegrees(jdn, timeZone) / 30);
|
|
171
|
+
}
|
|
172
|
+
function getSolarTermIndex(jdn, timeZone) {
|
|
173
|
+
return INT(sunLongitudeDegrees(jdn, timeZone) / 15);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/core/calendar-engine.ts
|
|
177
|
+
function INT2(d) {
|
|
178
|
+
return Math.floor(d);
|
|
146
179
|
}
|
|
147
180
|
function getLunarMonth11(yy, timeZone) {
|
|
148
181
|
const off = jdFromDate(31, 12, yy) - 2415021076998695e-9;
|
|
149
|
-
const k =
|
|
182
|
+
const k = INT2(off / 29.530588853);
|
|
150
183
|
let nm = getNewMoonDay(k, timeZone);
|
|
151
184
|
const sunLong = getSunLongitude(nm, timeZone);
|
|
152
185
|
if (sunLong >= 9) {
|
|
@@ -155,7 +188,7 @@ function getLunarMonth11(yy, timeZone) {
|
|
|
155
188
|
return nm;
|
|
156
189
|
}
|
|
157
190
|
function getLeapMonthOffset(a11, timeZone) {
|
|
158
|
-
const k =
|
|
191
|
+
const k = INT2((a11 - 2415021076998695e-9) / 29.530588853 + 0.5);
|
|
159
192
|
let last;
|
|
160
193
|
let i = 1;
|
|
161
194
|
let arc = getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone);
|
|
@@ -219,7 +252,7 @@ var LichTa = class {
|
|
|
219
252
|
throw new RangeError(`Lichta: Day must be between 1 and 31, got ${day}`);
|
|
220
253
|
}
|
|
221
254
|
const dayNumber = jdFromDate(day, month, year);
|
|
222
|
-
const k =
|
|
255
|
+
const k = INT2((dayNumber - 2415021076998695e-9) / 29.530588853);
|
|
223
256
|
let monthStart = getNewMoonDay(k + 1, timeZone);
|
|
224
257
|
if (monthStart > dayNumber) {
|
|
225
258
|
monthStart = getNewMoonDay(k, timeZone);
|
|
@@ -235,7 +268,7 @@ var LichTa = class {
|
|
|
235
268
|
b11 = getLunarMonth11(year + 1, timeZone);
|
|
236
269
|
}
|
|
237
270
|
const lunarDay = dayNumber - monthStart + 1;
|
|
238
|
-
const diff =
|
|
271
|
+
const diff = INT2((monthStart - a11) / 29);
|
|
239
272
|
let lunarLeap = false;
|
|
240
273
|
let lunarMonth = diff + 11;
|
|
241
274
|
if (b11 - a11 > 365) {
|
|
@@ -296,7 +329,7 @@ var LichTa = class {
|
|
|
296
329
|
a11 = getLunarMonth11(lunarYear, timeZone);
|
|
297
330
|
b11 = getLunarMonth11(lunarYear + 1, timeZone);
|
|
298
331
|
}
|
|
299
|
-
const k =
|
|
332
|
+
const k = INT2(0.5 + (a11 - 2415021076998695e-9) / 29.530588853);
|
|
300
333
|
let off = lunarMonth - 11;
|
|
301
334
|
if (off < 0) {
|
|
302
335
|
off += 12;
|
|
@@ -320,9 +353,6 @@ var LichTa = class {
|
|
|
320
353
|
}
|
|
321
354
|
};
|
|
322
355
|
|
|
323
|
-
// src/constants/five-elements.ts
|
|
324
|
-
var FIVE_ELEMENTS = ["Kim", "M\u1ED9c", "Th\u1EE7y", "H\u1ECFa", "Th\u1ED5"];
|
|
325
|
-
|
|
326
356
|
// src/constants/i18n.ts
|
|
327
357
|
var translations = {
|
|
328
358
|
vi: {
|
|
@@ -338,7 +368,40 @@ var translations = {
|
|
|
338
368
|
leapLabel: "Nhu\u1EADn",
|
|
339
369
|
yearLabel: "N\u0103m",
|
|
340
370
|
monthLabel: "Th\xE1ng",
|
|
341
|
-
destiny: "M\u1EC7nh"
|
|
371
|
+
destiny: "M\u1EC7nh",
|
|
372
|
+
// Thứ tự bắt đầu từ Xuân Phân (kinh độ Mặt Trời 0°), xem getSolarTermIndex trong lunar.ts
|
|
373
|
+
solarTermNames: [
|
|
374
|
+
"Xu\xE2n Ph\xE2n",
|
|
375
|
+
"Thanh Minh",
|
|
376
|
+
"C\u1ED1c V\u0169",
|
|
377
|
+
"L\u1EADp H\u1EA1",
|
|
378
|
+
"Ti\u1EC3u M\xE3n",
|
|
379
|
+
"Mang Ch\u1EE7ng",
|
|
380
|
+
"H\u1EA1 Ch\xED",
|
|
381
|
+
"Ti\u1EC3u Th\u1EED",
|
|
382
|
+
"\u0110\u1EA1i Th\u1EED",
|
|
383
|
+
"L\u1EADp Thu",
|
|
384
|
+
"X\u1EED Th\u1EED",
|
|
385
|
+
"B\u1EA1ch L\u1ED9",
|
|
386
|
+
"Thu Ph\xE2n",
|
|
387
|
+
"H\xE0n L\u1ED9",
|
|
388
|
+
"S\u01B0\u01A1ng Gi\xE1ng",
|
|
389
|
+
"L\u1EADp \u0110\xF4ng",
|
|
390
|
+
"Ti\u1EC3u Tuy\u1EBFt",
|
|
391
|
+
"\u0110\u1EA1i Tuy\u1EBFt",
|
|
392
|
+
"\u0110\xF4ng Ch\xED",
|
|
393
|
+
"Ti\u1EC3u H\xE0n",
|
|
394
|
+
"\u0110\u1EA1i H\xE0n",
|
|
395
|
+
"L\u1EADp Xu\xE2n",
|
|
396
|
+
"V\u0169 Th\u1EE7y",
|
|
397
|
+
"Kinh Tr\u1EADp"
|
|
398
|
+
],
|
|
399
|
+
// Thứ tự bắt đầu từ Kiến (0), xem getTrucIndex trong feng-shui.ts
|
|
400
|
+
trucNames: ["Ki\u1EBFn", "Tr\u1EEB", "M\xE3n", "B\xECnh", "\u0110\u1ECBnh", "Ch\u1EA5p", "Ph\xE1", "Nguy", "Th\xE0nh", "Thu", "Khai", "B\u1EBF"],
|
|
401
|
+
// Thứ tự: sinh, được sinh, khắc, bị khắc, hòa — xem getElementRelationIndex trong feng-shui.ts
|
|
402
|
+
elementRelationNames: ["T\u01B0\u01A1ng sinh", "\u0110\u01B0\u1EE3c sinh", "T\u01B0\u01A1ng kh\u1EAFc", "B\u1ECB kh\u1EAFc", "T\u01B0\u01A1ng h\xF2a"],
|
|
403
|
+
// Thứ tự: xấu, trung bình, tốt — xem getTrucQualityIndex trong feng-shui.ts
|
|
404
|
+
trucQualityNames: ["X\u1EA5u", "Trung b\xECnh", "T\u1ED1t"]
|
|
342
405
|
},
|
|
343
406
|
en: {
|
|
344
407
|
heavenlyStems: ["Gi\xE1p", "\u1EA4t", "B\xEDnh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\xE2n", "Nh\xE2m", "Qu\xFD"],
|
|
@@ -353,7 +416,36 @@ var translations = {
|
|
|
353
416
|
leapLabel: "Leap",
|
|
354
417
|
yearLabel: "Year",
|
|
355
418
|
monthLabel: "Month",
|
|
356
|
-
destiny: "Destiny"
|
|
419
|
+
destiny: "Destiny",
|
|
420
|
+
solarTermNames: [
|
|
421
|
+
"Spring Equinox",
|
|
422
|
+
"Clear and Bright",
|
|
423
|
+
"Grain Rain",
|
|
424
|
+
"Start of Summer",
|
|
425
|
+
"Grain Full",
|
|
426
|
+
"Grain in Ear",
|
|
427
|
+
"Summer Solstice",
|
|
428
|
+
"Minor Heat",
|
|
429
|
+
"Major Heat",
|
|
430
|
+
"Start of Autumn",
|
|
431
|
+
"End of Heat",
|
|
432
|
+
"White Dew",
|
|
433
|
+
"Autumn Equinox",
|
|
434
|
+
"Cold Dew",
|
|
435
|
+
"Frost's Descent",
|
|
436
|
+
"Start of Winter",
|
|
437
|
+
"Minor Snow",
|
|
438
|
+
"Major Snow",
|
|
439
|
+
"Winter Solstice",
|
|
440
|
+
"Minor Cold",
|
|
441
|
+
"Major Cold",
|
|
442
|
+
"Start of Spring",
|
|
443
|
+
"Rain Water",
|
|
444
|
+
"Awakening of Insects"
|
|
445
|
+
],
|
|
446
|
+
trucNames: ["Ki\u1EBFn", "Tr\u1EEB", "M\xE3n", "B\xECnh", "\u0110\u1ECBnh", "Ch\u1EA5p", "Ph\xE1", "Nguy", "Th\xE0nh", "Thu", "Khai", "B\u1EBF"],
|
|
447
|
+
elementRelationNames: ["Generates", "Generated By", "Overcomes", "Overcome By", "Same Element"],
|
|
448
|
+
trucQualityNames: ["Bad", "Neutral", "Good"]
|
|
357
449
|
},
|
|
358
450
|
ja: {
|
|
359
451
|
heavenlyStems: ["\u7532", "\u4E59", "\u4E19", "\u4E01", "\u620A", "\u5DF1", "\u5E9A", "\u8F9B", "\u58EC", "\u7678"],
|
|
@@ -368,7 +460,36 @@ var translations = {
|
|
|
368
460
|
leapLabel: "\u958F",
|
|
369
461
|
yearLabel: "\u5E74",
|
|
370
462
|
monthLabel: "\u6708",
|
|
371
|
-
destiny: "\u547D"
|
|
463
|
+
destiny: "\u547D",
|
|
464
|
+
solarTermNames: [
|
|
465
|
+
"\u6625\u5206",
|
|
466
|
+
"\u6E05\u660E",
|
|
467
|
+
"\u7A40\u96E8",
|
|
468
|
+
"\u7ACB\u590F",
|
|
469
|
+
"\u5C0F\u6E80",
|
|
470
|
+
"\u8292\u7A2E",
|
|
471
|
+
"\u590F\u81F3",
|
|
472
|
+
"\u5C0F\u6691",
|
|
473
|
+
"\u5927\u6691",
|
|
474
|
+
"\u7ACB\u79CB",
|
|
475
|
+
"\u51E6\u6691",
|
|
476
|
+
"\u767D\u9732",
|
|
477
|
+
"\u79CB\u5206",
|
|
478
|
+
"\u5BD2\u9732",
|
|
479
|
+
"\u971C\u964D",
|
|
480
|
+
"\u7ACB\u51AC",
|
|
481
|
+
"\u5C0F\u96EA",
|
|
482
|
+
"\u5927\u96EA",
|
|
483
|
+
"\u51AC\u81F3",
|
|
484
|
+
"\u5C0F\u5BD2",
|
|
485
|
+
"\u5927\u5BD2",
|
|
486
|
+
"\u7ACB\u6625",
|
|
487
|
+
"\u96E8\u6C34",
|
|
488
|
+
"\u5553\u87C4"
|
|
489
|
+
],
|
|
490
|
+
trucNames: ["\u5EFA", "\u9664", "\u6E80", "\u5E73", "\u5B9A", "\u57F7", "\u7834", "\u5371", "\u6210", "\u53CE", "\u958B", "\u9589"],
|
|
491
|
+
elementRelationNames: ["\u76F8\u751F", "\u88AB\u751F", "\u76F8\u514B", "\u88AB\u514B", "\u6BD4\u548C"],
|
|
492
|
+
trucQualityNames: ["\u51F6", "\u666E\u901A", "\u5409"]
|
|
372
493
|
},
|
|
373
494
|
ko: {
|
|
374
495
|
heavenlyStems: ["\uAC11", "\uC744", "\uBCD1", "\uC815", "\uBB34", "\uAE30", "\uACBD", "\uC2E0", "\uC784", "\uACC4"],
|
|
@@ -383,7 +504,36 @@ var translations = {
|
|
|
383
504
|
leapLabel: "\uC724",
|
|
384
505
|
yearLabel: "\uB144",
|
|
385
506
|
monthLabel: "\uC6D4",
|
|
386
|
-
destiny: "\uBA85"
|
|
507
|
+
destiny: "\uBA85",
|
|
508
|
+
solarTermNames: [
|
|
509
|
+
"\uCD98\uBD84",
|
|
510
|
+
"\uCCAD\uBA85",
|
|
511
|
+
"\uACE1\uC6B0",
|
|
512
|
+
"\uC785\uD558",
|
|
513
|
+
"\uC18C\uB9CC",
|
|
514
|
+
"\uB9DD\uC885",
|
|
515
|
+
"\uD558\uC9C0",
|
|
516
|
+
"\uC18C\uC11C",
|
|
517
|
+
"\uB300\uC11C",
|
|
518
|
+
"\uC785\uCD94",
|
|
519
|
+
"\uCC98\uC11C",
|
|
520
|
+
"\uBC31\uB85C",
|
|
521
|
+
"\uCD94\uBD84",
|
|
522
|
+
"\uD55C\uB85C",
|
|
523
|
+
"\uC0C1\uAC15",
|
|
524
|
+
"\uC785\uB3D9",
|
|
525
|
+
"\uC18C\uC124",
|
|
526
|
+
"\uB300\uC124",
|
|
527
|
+
"\uB3D9\uC9C0",
|
|
528
|
+
"\uC18C\uD55C",
|
|
529
|
+
"\uB300\uD55C",
|
|
530
|
+
"\uC785\uCD98",
|
|
531
|
+
"\uC6B0\uC218",
|
|
532
|
+
"\uACBD\uCE69"
|
|
533
|
+
],
|
|
534
|
+
trucNames: ["\uAC74", "\uC81C", "\uB9CC", "\uD3C9", "\uC815", "\uC9D1", "\uD30C", "\uC704", "\uC131", "\uC218", "\uAC1C", "\uD3D0"],
|
|
535
|
+
elementRelationNames: ["\uC0C1\uC0DD", "\uD53C\uC0DD", "\uC0C1\uADF9", "\uD53C\uADF9", "\uBE44\uD654"],
|
|
536
|
+
trucQualityNames: ["\uD749", "\uBCF4\uD1B5", "\uAE38"]
|
|
387
537
|
}
|
|
388
538
|
};
|
|
389
539
|
function t(locale) {
|
|
@@ -392,28 +542,12 @@ function t(locale) {
|
|
|
392
542
|
function getZodiacAnimal(branchIndex, locale = "vi") {
|
|
393
543
|
return translations[locale].zodiacAnimals[branchIndex % 12];
|
|
394
544
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return (n % m + m) % m;
|
|
399
|
-
}
|
|
400
|
-
function getYearDetails(year) {
|
|
401
|
-
const stemIndex = mod(year - 4, 10);
|
|
402
|
-
const branchIndex = mod(year - 4, 12);
|
|
403
|
-
const stemWeight = getStemWeight(stemIndex);
|
|
404
|
-
const branchWeight = getBranchWeight(branchIndex);
|
|
405
|
-
let elementValue = stemWeight + branchWeight;
|
|
406
|
-
if (elementValue > 5) {
|
|
407
|
-
elementValue -= 5;
|
|
408
|
-
}
|
|
409
|
-
const elementIndex = elementValue - 1;
|
|
410
|
-
return {
|
|
411
|
-
can: HEAVENLY_STEMS[stemIndex],
|
|
412
|
-
chi: EARTHLY_BRANCHES[branchIndex],
|
|
413
|
-
menh: FIVE_ELEMENTS[elementIndex],
|
|
414
|
-
fullString: `${HEAVENLY_STEMS[stemIndex]} ${EARTHLY_BRANCHES[branchIndex]} - M\u1EC7nh ${FIVE_ELEMENTS[elementIndex]}`
|
|
415
|
-
};
|
|
545
|
+
function getWeekDayLabels(locale, firstDayOfWeek = 0) {
|
|
546
|
+
const { weekDays } = translations[locale];
|
|
547
|
+
return firstDayOfWeek === 0 ? [...weekDays] : [...weekDays.slice(1), weekDays[0]];
|
|
416
548
|
}
|
|
549
|
+
|
|
550
|
+
// src/core/can-chi.ts
|
|
417
551
|
function getDayCanChi(jd, locale = "vi") {
|
|
418
552
|
const stemIndex = (jd + 9) % 10;
|
|
419
553
|
const branchIndex = (jd + 1) % 12;
|
|
@@ -436,6 +570,229 @@ function getHourCanChi(hour, dayJd, locale = "vi") {
|
|
|
436
570
|
const { heavenlyStems, earthlyBranches } = t(locale);
|
|
437
571
|
return `${heavenlyStems[hourStemIndex]} ${earthlyBranches[hourBranchIndex]}`;
|
|
438
572
|
}
|
|
573
|
+
|
|
574
|
+
// src/utils/math.ts
|
|
575
|
+
function mod(n, m) {
|
|
576
|
+
return (n % m + m) % m;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// src/core/ngu-hanh.ts
|
|
580
|
+
var NAP_AM_ELEMENT_INDEX = [
|
|
581
|
+
0,
|
|
582
|
+
3,
|
|
583
|
+
1,
|
|
584
|
+
4,
|
|
585
|
+
0,
|
|
586
|
+
3,
|
|
587
|
+
2,
|
|
588
|
+
4,
|
|
589
|
+
0,
|
|
590
|
+
1,
|
|
591
|
+
2,
|
|
592
|
+
4,
|
|
593
|
+
3,
|
|
594
|
+
1,
|
|
595
|
+
2,
|
|
596
|
+
0,
|
|
597
|
+
3,
|
|
598
|
+
1,
|
|
599
|
+
4,
|
|
600
|
+
0,
|
|
601
|
+
3,
|
|
602
|
+
2,
|
|
603
|
+
4,
|
|
604
|
+
0,
|
|
605
|
+
1,
|
|
606
|
+
2,
|
|
607
|
+
4,
|
|
608
|
+
3,
|
|
609
|
+
1,
|
|
610
|
+
2
|
|
611
|
+
];
|
|
612
|
+
function getSexagenaryIndex(stemIndex, branchIndex) {
|
|
613
|
+
for (let i = 0; i < 60; i++) {
|
|
614
|
+
if (i % 10 === stemIndex && i % 12 === branchIndex) {
|
|
615
|
+
return i;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
throw new RangeError(`Lichta: Invalid Can Chi combination (stem=${stemIndex}, chi=${branchIndex})`);
|
|
619
|
+
}
|
|
620
|
+
function getNapAmElementIndex(stemIndex, branchIndex) {
|
|
621
|
+
const sexagenaryIndex = getSexagenaryIndex(stemIndex, branchIndex);
|
|
622
|
+
return NAP_AM_ELEMENT_INDEX[Math.floor(sexagenaryIndex / 2)];
|
|
623
|
+
}
|
|
624
|
+
function getElementName(index, locale = "vi") {
|
|
625
|
+
return t(locale).fiveElements[mod(index, 5)];
|
|
626
|
+
}
|
|
627
|
+
function getDayElementIndex(jd) {
|
|
628
|
+
const stemIndex = (jd + 9) % 10;
|
|
629
|
+
const branchIndex = (jd + 1) % 12;
|
|
630
|
+
return getNapAmElementIndex(stemIndex, branchIndex);
|
|
631
|
+
}
|
|
632
|
+
function getDayElement(jd, locale = "vi") {
|
|
633
|
+
return getElementName(getDayElementIndex(jd), locale);
|
|
634
|
+
}
|
|
635
|
+
function getMonthElementIndex(lunarMonth, lunarYear) {
|
|
636
|
+
const yearStemIndex = (lunarYear + 6) % 10;
|
|
637
|
+
const monthStemOffset = yearStemIndex % 5 * 2 + 2;
|
|
638
|
+
const monthStemIndex = (monthStemOffset + lunarMonth - 1) % 10;
|
|
639
|
+
const monthBranchIndex = (lunarMonth + 1) % 12;
|
|
640
|
+
return getNapAmElementIndex(monthStemIndex, monthBranchIndex);
|
|
641
|
+
}
|
|
642
|
+
function getMonthElement(lunarMonth, lunarYear, locale = "vi") {
|
|
643
|
+
return getElementName(getMonthElementIndex(lunarMonth, lunarYear), locale);
|
|
644
|
+
}
|
|
645
|
+
function getHourElementIndex(hour, dayJd) {
|
|
646
|
+
const hourBranchIndex = Math.floor((hour + 1) / 2) % 12;
|
|
647
|
+
const dayStemIndex = (dayJd + 9) % 10;
|
|
648
|
+
const hourStemOffset = dayStemIndex % 5 * 2;
|
|
649
|
+
const hourStemIndex = (hourStemOffset + hourBranchIndex) % 10;
|
|
650
|
+
return getNapAmElementIndex(hourStemIndex, hourBranchIndex);
|
|
651
|
+
}
|
|
652
|
+
function getHourElement(hour, dayJd, locale = "vi") {
|
|
653
|
+
return getElementName(getHourElementIndex(hour, dayJd), locale);
|
|
654
|
+
}
|
|
655
|
+
var ELEMENT_SINH_TARGET = [2, 3, 1, 4, 0];
|
|
656
|
+
var ELEMENT_KHAC_TARGET = [1, 4, 3, 0, 2];
|
|
657
|
+
function getElementRelationIndex(fromIndex, toIndex) {
|
|
658
|
+
const a = mod(fromIndex, 5);
|
|
659
|
+
const b = mod(toIndex, 5);
|
|
660
|
+
if (a === b) return 4;
|
|
661
|
+
if (ELEMENT_SINH_TARGET[a] === b) return 0;
|
|
662
|
+
if (ELEMENT_SINH_TARGET[b] === a) return 1;
|
|
663
|
+
if (ELEMENT_KHAC_TARGET[a] === b) return 2;
|
|
664
|
+
return 3;
|
|
665
|
+
}
|
|
666
|
+
function getElementRelation(fromIndex, toIndex, locale = "vi") {
|
|
667
|
+
const { elementRelationNames } = t(locale);
|
|
668
|
+
return elementRelationNames[getElementRelationIndex(fromIndex, toIndex)];
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// src/core/tiet-khi.ts
|
|
672
|
+
function getSolarTermName(index, locale = "vi") {
|
|
673
|
+
const { solarTermNames } = t(locale);
|
|
674
|
+
return solarTermNames[(index % 24 + 24) % 24];
|
|
675
|
+
}
|
|
676
|
+
function getSolarTerm(day, month, year, timeZone = 7, locale = "vi") {
|
|
677
|
+
const jd = jdFromDate(day, month, year);
|
|
678
|
+
const index = getSolarTermIndex(jd + 1, timeZone);
|
|
679
|
+
return { index, name: getSolarTermName(index, locale), date: { day, month, year }, jd };
|
|
680
|
+
}
|
|
681
|
+
var occurrencesCache = /* @__PURE__ */ new Map();
|
|
682
|
+
function getSolarTermOccurrencesInYear(year, timeZone) {
|
|
683
|
+
const cacheKey = `${year}:${timeZone}`;
|
|
684
|
+
const cached = occurrencesCache.get(cacheKey);
|
|
685
|
+
if (cached) return cached;
|
|
686
|
+
const startJd = jdFromDate(1, 1, year) - 5;
|
|
687
|
+
const endJd = jdFromDate(31, 12, year) + 5;
|
|
688
|
+
const occurrences = [];
|
|
689
|
+
let prevIndex = getSolarTermIndex(startJd, timeZone);
|
|
690
|
+
for (let jd = startJd + 1; jd <= endJd; jd++) {
|
|
691
|
+
const index = getSolarTermIndex(jd, timeZone);
|
|
692
|
+
if (index !== prevIndex) {
|
|
693
|
+
const termJd = jd - 1;
|
|
694
|
+
const [, , jdYear] = jdToDate(termJd);
|
|
695
|
+
if (jdYear === year) {
|
|
696
|
+
occurrences.push({ index, jd: termJd });
|
|
697
|
+
}
|
|
698
|
+
prevIndex = index;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
occurrencesCache.set(cacheKey, occurrences);
|
|
702
|
+
return occurrences;
|
|
703
|
+
}
|
|
704
|
+
function getSolarTermsInYear(year, timeZone = 7, locale = "vi") {
|
|
705
|
+
return getSolarTermOccurrencesInYear(year, timeZone).map(({ index, jd }) => {
|
|
706
|
+
const [day, month, jdYear] = jdToDate(jd);
|
|
707
|
+
return { index, name: getSolarTermName(index, locale), date: { day, month, year: jdYear }, jd };
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// src/core/truc-zodiac.ts
|
|
712
|
+
var TRUC_COUNT = 12;
|
|
713
|
+
function getTrucIndex(jd, timeZone = 7) {
|
|
714
|
+
const [, , year] = jdToDate(jd);
|
|
715
|
+
const tietTerms = [year - 1, year, year + 1].flatMap((y) => getSolarTermOccurrencesInYear(y, timeZone)).filter((term) => term.index % 2 === 1);
|
|
716
|
+
let governingTietJd = -Infinity;
|
|
717
|
+
for (const term of tietTerms) {
|
|
718
|
+
if (term.jd <= jd && term.jd > governingTietJd) {
|
|
719
|
+
governingTietJd = term.jd;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return mod(jd - governingTietJd, TRUC_COUNT);
|
|
723
|
+
}
|
|
724
|
+
function getTrucName(index, locale = "vi") {
|
|
725
|
+
const { trucNames } = t(locale);
|
|
726
|
+
return trucNames[mod(index, TRUC_COUNT)];
|
|
727
|
+
}
|
|
728
|
+
function getTruc(jd, timeZone = 7, locale = "vi") {
|
|
729
|
+
return getTrucName(getTrucIndex(jd, timeZone), locale);
|
|
730
|
+
}
|
|
731
|
+
var TRUC_QUALITY_INDEX = [1, 1, 1, 1, 1, 1, 0, 0, 2, 1, 2, 1];
|
|
732
|
+
function getTrucQualityIndex(trucIndex) {
|
|
733
|
+
return TRUC_QUALITY_INDEX[mod(trucIndex, TRUC_COUNT)];
|
|
734
|
+
}
|
|
735
|
+
function getTrucQuality(trucIndex, locale = "vi") {
|
|
736
|
+
const { trucQualityNames } = t(locale);
|
|
737
|
+
return trucQualityNames[getTrucQualityIndex(trucIndex)];
|
|
738
|
+
}
|
|
739
|
+
function getXungBranchIndex(branchIndex) {
|
|
740
|
+
return mod(branchIndex + 6, 12);
|
|
741
|
+
}
|
|
742
|
+
function isXung(branchIndexA, branchIndexB) {
|
|
743
|
+
return getXungBranchIndex(mod(branchIndexA, 12)) === mod(branchIndexB, 12);
|
|
744
|
+
}
|
|
745
|
+
var HAI_BRANCH_TARGET = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8];
|
|
746
|
+
function getHaiBranchIndex(branchIndex) {
|
|
747
|
+
return HAI_BRANCH_TARGET[mod(branchIndex, 12)];
|
|
748
|
+
}
|
|
749
|
+
function isHai(branchIndexA, branchIndexB) {
|
|
750
|
+
return getHaiBranchIndex(mod(branchIndexA, 12)) === mod(branchIndexB, 12);
|
|
751
|
+
}
|
|
752
|
+
var TU_HANH_XUNG_GROUP = [0, 2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1];
|
|
753
|
+
var TU_HANH_XUNG_MEMBERS = [
|
|
754
|
+
[0, 3, 6, 9],
|
|
755
|
+
// Tý, Mão, Ngọ, Dậu
|
|
756
|
+
[2, 5, 8, 11],
|
|
757
|
+
// Dần, Tỵ, Thân, Hợi
|
|
758
|
+
[1, 4, 7, 10]
|
|
759
|
+
// Sửu, Thìn, Mùi, Tuất
|
|
760
|
+
];
|
|
761
|
+
function getTuHanhXungGroupIndex(branchIndex) {
|
|
762
|
+
return TU_HANH_XUNG_GROUP[mod(branchIndex, 12)];
|
|
763
|
+
}
|
|
764
|
+
function getTuHanhXungGroupMembers(branchIndex) {
|
|
765
|
+
return [...TU_HANH_XUNG_MEMBERS[getTuHanhXungGroupIndex(branchIndex)]];
|
|
766
|
+
}
|
|
767
|
+
function isTuHanhXung(branchIndexA, branchIndexB) {
|
|
768
|
+
const a = mod(branchIndexA, 12);
|
|
769
|
+
const b = mod(branchIndexB, 12);
|
|
770
|
+
return a !== b && getTuHanhXungGroupIndex(a) === getTuHanhXungGroupIndex(b);
|
|
771
|
+
}
|
|
772
|
+
function getZodiacConflicts(branchIndexA, branchIndexB) {
|
|
773
|
+
return {
|
|
774
|
+
xung: isXung(branchIndexA, branchIndexB),
|
|
775
|
+
hai: isHai(branchIndexA, branchIndexB),
|
|
776
|
+
tuHanhXung: isTuHanhXung(branchIndexA, branchIndexB)
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// src/constants/five-elements.ts
|
|
781
|
+
var FIVE_ELEMENTS = ["Kim", "M\u1ED9c", "Th\u1EE7y", "H\u1ECFa", "Th\u1ED5"];
|
|
782
|
+
|
|
783
|
+
// src/core/almanac.ts
|
|
784
|
+
function getYearDetails(year) {
|
|
785
|
+
const stemIndex = mod(year - 4, 10);
|
|
786
|
+
const branchIndex = mod(year - 4, 12);
|
|
787
|
+
const elementIndex = getNapAmElementIndex(stemIndex, branchIndex);
|
|
788
|
+
return {
|
|
789
|
+
can: HEAVENLY_STEMS[stemIndex],
|
|
790
|
+
chi: EARTHLY_BRANCHES[branchIndex],
|
|
791
|
+
menh: FIVE_ELEMENTS[elementIndex],
|
|
792
|
+
menhIndex: elementIndex,
|
|
793
|
+
fullString: `${HEAVENLY_STEMS[stemIndex]} ${EARTHLY_BRANCHES[branchIndex]} - M\u1EC7nh ${FIVE_ELEMENTS[elementIndex]}`
|
|
794
|
+
};
|
|
795
|
+
}
|
|
439
796
|
var AUSPICIOUS_HOURS_TABLE = [
|
|
440
797
|
[0, 1, 3, 6, 7, 9],
|
|
441
798
|
// Ngày Tý (0) / Ngọ (6)
|
|
@@ -462,6 +819,18 @@ function getAuspiciousHourIndices(dayJd) {
|
|
|
462
819
|
const groupIndex = branchIndex % 6;
|
|
463
820
|
return [...AUSPICIOUS_HOURS_TABLE[groupIndex]];
|
|
464
821
|
}
|
|
822
|
+
function getInauspiciousHourIndices(dayJd) {
|
|
823
|
+
const auspicious = new Set(getAuspiciousHourIndices(dayJd));
|
|
824
|
+
const inauspicious = [];
|
|
825
|
+
for (let i = 0; i < 12; i++) {
|
|
826
|
+
if (!auspicious.has(i)) inauspicious.push(i);
|
|
827
|
+
}
|
|
828
|
+
return inauspicious;
|
|
829
|
+
}
|
|
830
|
+
function getInauspiciousHours(dayJd, locale = "vi") {
|
|
831
|
+
const { earthlyBranches } = t(locale);
|
|
832
|
+
return getInauspiciousHourIndices(dayJd).map((i) => earthlyBranches[i]);
|
|
833
|
+
}
|
|
465
834
|
|
|
466
835
|
// src/utils/format.ts
|
|
467
836
|
var MONTH_NAMES = [
|
|
@@ -545,11 +914,20 @@ function formatTraditional(lunar) {
|
|
|
545
914
|
function dateKey(date) {
|
|
546
915
|
return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
|
|
547
916
|
}
|
|
548
|
-
function
|
|
917
|
+
function getISOWeekNumber(date) {
|
|
918
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
919
|
+
const dayNum = (d.getUTCDay() + 6) % 7;
|
|
920
|
+
d.setUTCDate(d.getUTCDate() - dayNum + 3);
|
|
921
|
+
const firstThursday = new Date(Date.UTC(d.getUTCFullYear(), 0, 4));
|
|
922
|
+
const firstThursdayDayNum = (firstThursday.getUTCDay() + 6) % 7;
|
|
923
|
+
firstThursday.setUTCDate(firstThursday.getUTCDate() - firstThursdayDayNum + 3);
|
|
924
|
+
return 1 + Math.round((d.getTime() - firstThursday.getTime()) / 6048e5);
|
|
925
|
+
}
|
|
926
|
+
function getCalendarGrid(month, year, selectedDate, firstDayOfWeek = 0) {
|
|
549
927
|
const grid = [];
|
|
550
928
|
const firstDay = new Date(year, month - 1, 1);
|
|
551
929
|
const lastDay = new Date(year, month, 0);
|
|
552
|
-
const startingDayOfWeek = firstDay.getDay();
|
|
930
|
+
const startingDayOfWeek = (firstDay.getDay() - firstDayOfWeek + 7) % 7;
|
|
553
931
|
const daysInMonth = lastDay.getDate();
|
|
554
932
|
const todayKey = dateKey(/* @__PURE__ */ new Date());
|
|
555
933
|
const selectedKey = selectedDate ? dateKey(selectedDate) : "";
|
|
@@ -560,7 +938,9 @@ function getCalendarGrid(month, year, selectedDate) {
|
|
|
560
938
|
lunar: LichTa.toLunar(d, m, y),
|
|
561
939
|
isToday: dateKey(solar) === todayKey,
|
|
562
940
|
isSelected: dateKey(solar) === selectedKey,
|
|
563
|
-
isCurrentMonth
|
|
941
|
+
isCurrentMonth,
|
|
942
|
+
weekNumber: 0
|
|
943
|
+
// gán lại theo từng hàng ở bước cuối, xem vòng lặp bên dưới
|
|
564
944
|
});
|
|
565
945
|
};
|
|
566
946
|
for (let i = startingDayOfWeek - 1; i >= 0; i--) {
|
|
@@ -578,6 +958,13 @@ function getCalendarGrid(month, year, selectedDate) {
|
|
|
578
958
|
const y = month + 1 > 12 ? year + 1 : year;
|
|
579
959
|
pushCell(new Date(y, m - 1, d), d, m, y, false);
|
|
580
960
|
}
|
|
961
|
+
const thursdayOffset = (4 - firstDayOfWeek + 7) % 7;
|
|
962
|
+
for (let row = 0; row < grid.length; row += 7) {
|
|
963
|
+
const weekNumber = getISOWeekNumber(grid[row + thursdayOffset].solar);
|
|
964
|
+
for (let i = row; i < row + 7; i++) {
|
|
965
|
+
grid[i].weekNumber = weekNumber;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
581
968
|
return grid;
|
|
582
969
|
}
|
|
583
970
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -589,12 +976,41 @@ function getCalendarGrid(month, year, selectedDate) {
|
|
|
589
976
|
getAuspiciousHours,
|
|
590
977
|
getCalendarGrid,
|
|
591
978
|
getDayCanChi,
|
|
979
|
+
getDayElement,
|
|
980
|
+
getDayElementIndex,
|
|
592
981
|
getDayName,
|
|
982
|
+
getElementName,
|
|
983
|
+
getElementRelation,
|
|
984
|
+
getElementRelationIndex,
|
|
985
|
+
getHaiBranchIndex,
|
|
593
986
|
getHourCanChi,
|
|
987
|
+
getHourElement,
|
|
988
|
+
getHourElementIndex,
|
|
989
|
+
getISOWeekNumber,
|
|
990
|
+
getInauspiciousHourIndices,
|
|
991
|
+
getInauspiciousHours,
|
|
594
992
|
getMonthCanChi,
|
|
993
|
+
getMonthElement,
|
|
994
|
+
getMonthElementIndex,
|
|
595
995
|
getMonthName,
|
|
996
|
+
getSolarTerm,
|
|
997
|
+
getSolarTermName,
|
|
998
|
+
getSolarTermsInYear,
|
|
999
|
+
getTruc,
|
|
1000
|
+
getTrucIndex,
|
|
1001
|
+
getTrucName,
|
|
1002
|
+
getTrucQuality,
|
|
1003
|
+
getTrucQualityIndex,
|
|
1004
|
+
getTuHanhXungGroupIndex,
|
|
1005
|
+
getTuHanhXungGroupMembers,
|
|
1006
|
+
getWeekDayLabels,
|
|
1007
|
+
getXungBranchIndex,
|
|
596
1008
|
getYearDetails,
|
|
597
1009
|
getZodiacAnimal,
|
|
1010
|
+
getZodiacConflicts,
|
|
1011
|
+
isHai,
|
|
1012
|
+
isTuHanhXung,
|
|
1013
|
+
isXung,
|
|
598
1014
|
jdFromDate,
|
|
599
1015
|
jdToDate,
|
|
600
1016
|
t
|