@lichta/core 2.0.1 → 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/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
15
15
  }
16
16
  return to;
17
17
  };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
19
19
 
20
20
  // src/index.ts
21
21
  var index_exports = {};
@@ -23,14 +23,45 @@ __export(index_exports, {
23
23
  LichTa: () => LichTa,
24
24
  formatLunarDate: () => formatLunarDate,
25
25
  formatTraditional: () => formatTraditional,
26
+ getAuspiciousHourIndices: () => getAuspiciousHourIndices,
26
27
  getAuspiciousHours: () => getAuspiciousHours,
28
+ getCalendarGrid: () => getCalendarGrid,
27
29
  getDayCanChi: () => getDayCanChi,
30
+ getDayElement: () => getDayElement,
31
+ getDayElementIndex: () => getDayElementIndex,
28
32
  getDayName: () => getDayName,
33
+ getElementName: () => getElementName,
34
+ getElementRelation: () => getElementRelation,
35
+ getElementRelationIndex: () => getElementRelationIndex,
36
+ getHaiBranchIndex: () => getHaiBranchIndex,
29
37
  getHourCanChi: () => getHourCanChi,
38
+ getHourElement: () => getHourElement,
39
+ getHourElementIndex: () => getHourElementIndex,
40
+ getISOWeekNumber: () => getISOWeekNumber,
41
+ getInauspiciousHourIndices: () => getInauspiciousHourIndices,
42
+ getInauspiciousHours: () => getInauspiciousHours,
30
43
  getMonthCanChi: () => getMonthCanChi,
44
+ getMonthElement: () => getMonthElement,
45
+ getMonthElementIndex: () => getMonthElementIndex,
31
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,
32
59
  getYearDetails: () => getYearDetails,
33
60
  getZodiacAnimal: () => getZodiacAnimal,
61
+ getZodiacConflicts: () => getZodiacConflicts,
62
+ isHai: () => isHai,
63
+ isTuHanhXung: () => isTuHanhXung,
64
+ isXung: () => isXung,
34
65
  jdFromDate: () => jdFromDate,
35
66
  jdToDate: () => jdToDate,
36
67
  t: () => t
@@ -50,9 +81,6 @@ var HEAVENLY_STEMS = [
50
81
  "Nh\xE2m",
51
82
  "Qu\xFD"
52
83
  ];
53
- function getStemWeight(index) {
54
- return Math.floor(index / 2) + 1;
55
- }
56
84
 
57
85
  // src/constants/earthly-branches.ts
58
86
  var EARTHLY_BRANCHES = [
@@ -69,12 +97,8 @@ var EARTHLY_BRANCHES = [
69
97
  "Tu\u1EA5t",
70
98
  "H\u1EE3i"
71
99
  ];
72
- function getBranchWeight(index) {
73
- const normalizedIndex = index % 6;
74
- return Math.floor(normalizedIndex / 2);
75
- }
76
100
 
77
- // src/core/lunar.ts
101
+ // src/core/astronomical.ts
78
102
  var PI = Math.PI;
79
103
  function INT(d) {
80
104
  return Math.floor(d);
@@ -130,7 +154,7 @@ function NewMoon(k) {
130
154
  function getNewMoonDay(k, timeZone) {
131
155
  return INT(NewMoon(k) + 0.5 + timeZone / 24);
132
156
  }
133
- function getSunLongitude(jdn, timeZone) {
157
+ function sunLongitudeDegrees(jdn, timeZone) {
134
158
  const T = (jdn - 24515455e-1 - timeZone / 24) / 36525;
135
159
  const T2 = T * T;
136
160
  const dr = PI / 180;
@@ -140,11 +164,22 @@ function getSunLongitude(jdn, timeZone) {
140
164
  DL = DL + (0.019993 - 101e-6 * T) * Math.sin(dr * 2 * M) + 29e-5 * Math.sin(dr * 3 * M);
141
165
  let L = L0 + DL;
142
166
  L = L - 360 * INT(L / 360);
143
- return INT(L / 30);
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);
144
179
  }
145
180
  function getLunarMonth11(yy, timeZone) {
146
181
  const off = jdFromDate(31, 12, yy) - 2415021076998695e-9;
147
- const k = INT(off / 29.530588853);
182
+ const k = INT2(off / 29.530588853);
148
183
  let nm = getNewMoonDay(k, timeZone);
149
184
  const sunLong = getSunLongitude(nm, timeZone);
150
185
  if (sunLong >= 9) {
@@ -153,7 +188,7 @@ function getLunarMonth11(yy, timeZone) {
153
188
  return nm;
154
189
  }
155
190
  function getLeapMonthOffset(a11, timeZone) {
156
- const k = INT((a11 - 2415021076998695e-9) / 29.530588853 + 0.5);
191
+ const k = INT2((a11 - 2415021076998695e-9) / 29.530588853 + 0.5);
157
192
  let last;
158
193
  let i = 1;
159
194
  let arc = getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone);
@@ -217,7 +252,7 @@ var LichTa = class {
217
252
  throw new RangeError(`Lichta: Day must be between 1 and 31, got ${day}`);
218
253
  }
219
254
  const dayNumber = jdFromDate(day, month, year);
220
- const k = INT((dayNumber - 2415021076998695e-9) / 29.530588853);
255
+ const k = INT2((dayNumber - 2415021076998695e-9) / 29.530588853);
221
256
  let monthStart = getNewMoonDay(k + 1, timeZone);
222
257
  if (monthStart > dayNumber) {
223
258
  monthStart = getNewMoonDay(k, timeZone);
@@ -233,7 +268,7 @@ var LichTa = class {
233
268
  b11 = getLunarMonth11(year + 1, timeZone);
234
269
  }
235
270
  const lunarDay = dayNumber - monthStart + 1;
236
- const diff = INT((monthStart - a11) / 29);
271
+ const diff = INT2((monthStart - a11) / 29);
237
272
  let lunarLeap = false;
238
273
  let lunarMonth = diff + 11;
239
274
  if (b11 - a11 > 365) {
@@ -294,7 +329,7 @@ var LichTa = class {
294
329
  a11 = getLunarMonth11(lunarYear, timeZone);
295
330
  b11 = getLunarMonth11(lunarYear + 1, timeZone);
296
331
  }
297
- const k = INT(0.5 + (a11 - 2415021076998695e-9) / 29.530588853);
332
+ const k = INT2(0.5 + (a11 - 2415021076998695e-9) / 29.530588853);
298
333
  let off = lunarMonth - 11;
299
334
  if (off < 0) {
300
335
  off += 12;
@@ -318,45 +353,445 @@ var LichTa = class {
318
353
  }
319
354
  };
320
355
 
321
- // src/constants/five-elements.ts
322
- var FIVE_ELEMENTS = ["Kim", "M\u1ED9c", "Th\u1EE7y", "H\u1ECFa", "Th\u1ED5"];
356
+ // src/constants/i18n.ts
357
+ var translations = {
358
+ vi: {
359
+ heavenlyStems: ["Gi\xE1p", "\u1EA4t", "B\xEDnh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\xE2n", "Nh\xE2m", "Qu\xFD"],
360
+ earthlyBranches: ["T\xFD", "S\u1EEDu", "D\u1EA7n", "M\xE3o", "Th\xECn", "T\u1EF5", "Ng\u1ECD", "M\xF9i", "Th\xE2n", "D\u1EADu", "Tu\u1EA5t", "H\u1EE3i"],
361
+ fiveElements: ["Kim", "M\u1ED9c", "Th\u1EE7y", "H\u1ECFa", "Th\u1ED5"],
362
+ zodiacAnimals: ["Chu\u1ED9t", "Tr\xE2u", "C\u1ECDp", "Th\u1ECF", "R\u1ED3ng", "R\u1EAFn", "Ng\u1EF1a", "D\xEA", "Kh\u1EC9", "G\xE0", "Ch\xF3", "Heo"],
363
+ // @deprecated Ngữ nghĩa không nhất quán giữa các locale (xem lunarMonthNames/solarMonthNames).
364
+ monthNames: ["Gi\xEAng", "Hai", "Ba", "T\u01B0", "N\u0103m", "S\xE1u", "B\u1EA3y", "T\xE1m", "Ch\xEDn", "M\u01B0\u1EDDi", "M\u1ED9t", "Ch\u1EA1p"],
365
+ lunarMonthNames: ["Gi\xEAng", "Hai", "Ba", "T\u01B0", "N\u0103m", "S\xE1u", "B\u1EA3y", "T\xE1m", "Ch\xEDn", "M\u01B0\u1EDDi", "M\u1ED9t", "Ch\u1EA1p"],
366
+ solarMonthNames: ["Th\xE1ng 1", "Th\xE1ng 2", "Th\xE1ng 3", "Th\xE1ng 4", "Th\xE1ng 5", "Th\xE1ng 6", "Th\xE1ng 7", "Th\xE1ng 8", "Th\xE1ng 9", "Th\xE1ng 10", "Th\xE1ng 11", "Th\xE1ng 12"],
367
+ weekDays: ["CN", "T2", "T3", "T4", "T5", "T6", "T7"],
368
+ leapLabel: "Nhu\u1EADn",
369
+ yearLabel: "N\u0103m",
370
+ monthLabel: "Th\xE1ng",
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"]
405
+ },
406
+ en: {
407
+ heavenlyStems: ["Gi\xE1p", "\u1EA4t", "B\xEDnh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\xE2n", "Nh\xE2m", "Qu\xFD"],
408
+ earthlyBranches: ["T\xFD", "S\u1EEDu", "D\u1EA7n", "M\xE3o", "Th\xECn", "T\u1EF5", "Ng\u1ECD", "M\xF9i", "Th\xE2n", "D\u1EADu", "Tu\u1EA5t", "H\u1EE3i"],
409
+ fiveElements: ["Metal", "Wood", "Water", "Fire", "Earth"],
410
+ zodiacAnimals: ["Rat", "Ox", "Tiger", "Rabbit", "Dragon", "Snake", "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"],
411
+ // @deprecated Ngữ nghĩa không nhất quán giữa các locale (xem lunarMonthNames/solarMonthNames).
412
+ monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
413
+ lunarMonthNames: ["Month 1", "Month 2", "Month 3", "Month 4", "Month 5", "Month 6", "Month 7", "Month 8", "Month 9", "Month 10", "Month 11", "Month 12"],
414
+ solarMonthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
415
+ weekDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
416
+ leapLabel: "Leap",
417
+ yearLabel: "Year",
418
+ monthLabel: "Month",
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"]
449
+ },
450
+ ja: {
451
+ heavenlyStems: ["\u7532", "\u4E59", "\u4E19", "\u4E01", "\u620A", "\u5DF1", "\u5E9A", "\u8F9B", "\u58EC", "\u7678"],
452
+ earthlyBranches: ["\u5B50", "\u4E11", "\u5BC5", "\u536F", "\u8FB0", "\u5DF3", "\u5348", "\u672A", "\u7533", "\u9149", "\u620C", "\u4EA5"],
453
+ fiveElements: ["\u91D1", "\u6728", "\u6C34", "\u706B", "\u571F"],
454
+ zodiacAnimals: ["\u9F20", "\u725B", "\u864E", "\u514E", "\u7ADC", "\u86C7", "\u99AC", "\u7F8A", "\u733F", "\u9D8F", "\u72AC", "\u732A"],
455
+ // @deprecated Ngữ nghĩa không nhất quán giữa các locale (xem lunarMonthNames/solarMonthNames).
456
+ monthNames: ["1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708"],
457
+ lunarMonthNames: ["\u65E7\u66A61\u6708", "\u65E7\u66A62\u6708", "\u65E7\u66A63\u6708", "\u65E7\u66A64\u6708", "\u65E7\u66A65\u6708", "\u65E7\u66A66\u6708", "\u65E7\u66A67\u6708", "\u65E7\u66A68\u6708", "\u65E7\u66A69\u6708", "\u65E7\u66A610\u6708", "\u65E7\u66A611\u6708", "\u65E7\u66A612\u6708"],
458
+ solarMonthNames: ["1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708"],
459
+ weekDays: ["\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728", "\u91D1", "\u571F"],
460
+ leapLabel: "\u958F",
461
+ yearLabel: "\u5E74",
462
+ monthLabel: "\u6708",
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"]
493
+ },
494
+ ko: {
495
+ heavenlyStems: ["\uAC11", "\uC744", "\uBCD1", "\uC815", "\uBB34", "\uAE30", "\uACBD", "\uC2E0", "\uC784", "\uACC4"],
496
+ earthlyBranches: ["\uC790", "\uCD95", "\uC778", "\uBB18", "\uC9C4", "\uC0AC", "\uC624", "\uBBF8", "\uC2E0", "\uC720", "\uC220", "\uD574"],
497
+ fiveElements: ["\uAE08", "\uBAA9", "\uC218", "\uD654", "\uD1A0"],
498
+ zodiacAnimals: ["\uC950", "\uC18C", "\uD638\uB791\uC774", "\uD1A0\uB07C", "\uC6A9", "\uBC40", "\uB9D0", "\uC591", "\uC6D0\uC22D\uC774", "\uB2ED", "\uAC1C", "\uB3FC\uC9C0"],
499
+ // @deprecated Ngữ nghĩa không nhất quán giữa các locale (xem lunarMonthNames/solarMonthNames).
500
+ monthNames: ["1\uC6D4", "2\uC6D4", "3\uC6D4", "4\uC6D4", "5\uC6D4", "6\uC6D4", "7\uC6D4", "8\uC6D4", "9\uC6D4", "10\uC6D4", "11\uC6D4", "12\uC6D4"],
501
+ lunarMonthNames: ["\uC74C\uB825 1\uC6D4", "\uC74C\uB825 2\uC6D4", "\uC74C\uB825 3\uC6D4", "\uC74C\uB825 4\uC6D4", "\uC74C\uB825 5\uC6D4", "\uC74C\uB825 6\uC6D4", "\uC74C\uB825 7\uC6D4", "\uC74C\uB825 8\uC6D4", "\uC74C\uB825 9\uC6D4", "\uC74C\uB825 10\uC6D4", "\uC74C\uB825 11\uC6D4", "\uC74C\uB825 12\uC6D4"],
502
+ solarMonthNames: ["1\uC6D4", "2\uC6D4", "3\uC6D4", "4\uC6D4", "5\uC6D4", "6\uC6D4", "7\uC6D4", "8\uC6D4", "9\uC6D4", "10\uC6D4", "11\uC6D4", "12\uC6D4"],
503
+ weekDays: ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"],
504
+ leapLabel: "\uC724",
505
+ yearLabel: "\uB144",
506
+ monthLabel: "\uC6D4",
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"]
537
+ }
538
+ };
539
+ function t(locale) {
540
+ return translations[locale];
541
+ }
542
+ function getZodiacAnimal(branchIndex, locale = "vi") {
543
+ return translations[locale].zodiacAnimals[branchIndex % 12];
544
+ }
545
+ function getWeekDayLabels(locale, firstDayOfWeek = 0) {
546
+ const { weekDays } = translations[locale];
547
+ return firstDayOfWeek === 0 ? [...weekDays] : [...weekDays.slice(1), weekDays[0]];
548
+ }
323
549
 
324
- // src/core/feng-shui.ts
325
- function getYearDetails(year) {
326
- const stemIndex = (year - 4) % 10;
327
- const branchIndex = (year - 4) % 12;
328
- const stemWeight = getStemWeight(stemIndex);
329
- const branchWeight = getBranchWeight(branchIndex);
330
- let elementValue = stemWeight + branchWeight;
331
- if (elementValue > 5) {
332
- elementValue -= 5;
550
+ // src/core/can-chi.ts
551
+ function getDayCanChi(jd, locale = "vi") {
552
+ const stemIndex = (jd + 9) % 10;
553
+ const branchIndex = (jd + 1) % 12;
554
+ const { heavenlyStems, earthlyBranches } = t(locale);
555
+ return `${heavenlyStems[stemIndex]} ${earthlyBranches[branchIndex]}`;
556
+ }
557
+ function getMonthCanChi(lunarMonth, lunarYear, locale = "vi") {
558
+ const yearStemIndex = (lunarYear + 6) % 10;
559
+ const monthStemOffset = yearStemIndex % 5 * 2 + 2;
560
+ const monthStemIndex = (monthStemOffset + lunarMonth - 1) % 10;
561
+ const monthBranchIndex = (lunarMonth + 1) % 12;
562
+ const { heavenlyStems, earthlyBranches } = t(locale);
563
+ return `${heavenlyStems[monthStemIndex]} ${earthlyBranches[monthBranchIndex]}`;
564
+ }
565
+ function getHourCanChi(hour, dayJd, locale = "vi") {
566
+ const hourBranchIndex = Math.floor((hour + 1) / 2) % 12;
567
+ const dayStemIndex = (dayJd + 9) % 10;
568
+ const hourStemOffset = dayStemIndex % 5 * 2;
569
+ const hourStemIndex = (hourStemOffset + hourBranchIndex) % 10;
570
+ const { heavenlyStems, earthlyBranches } = t(locale);
571
+ return `${heavenlyStems[hourStemIndex]} ${earthlyBranches[hourBranchIndex]}`;
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
+ }
333
617
  }
334
- const elementIndex = elementValue - 1;
335
- return {
336
- can: HEAVENLY_STEMS[stemIndex],
337
- chi: EARTHLY_BRANCHES[branchIndex],
338
- menh: FIVE_ELEMENTS[elementIndex],
339
- fullString: `${HEAVENLY_STEMS[stemIndex]} ${EARTHLY_BRANCHES[branchIndex]} - M\u1EC7nh ${FIVE_ELEMENTS[elementIndex]}`
340
- };
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)];
341
626
  }
342
- function getDayCanChi(jd) {
627
+ function getDayElementIndex(jd) {
343
628
  const stemIndex = (jd + 9) % 10;
344
629
  const branchIndex = (jd + 1) % 12;
345
- return `${HEAVENLY_STEMS[stemIndex]} ${EARTHLY_BRANCHES[branchIndex]}`;
630
+ return getNapAmElementIndex(stemIndex, branchIndex);
631
+ }
632
+ function getDayElement(jd, locale = "vi") {
633
+ return getElementName(getDayElementIndex(jd), locale);
346
634
  }
347
- function getMonthCanChi(lunarMonth, lunarYear) {
635
+ function getMonthElementIndex(lunarMonth, lunarYear) {
348
636
  const yearStemIndex = (lunarYear + 6) % 10;
349
637
  const monthStemOffset = yearStemIndex % 5 * 2 + 2;
350
638
  const monthStemIndex = (monthStemOffset + lunarMonth - 1) % 10;
351
639
  const monthBranchIndex = (lunarMonth + 1) % 12;
352
- return `${HEAVENLY_STEMS[monthStemIndex]} ${EARTHLY_BRANCHES[monthBranchIndex]}`;
640
+ return getNapAmElementIndex(monthStemIndex, monthBranchIndex);
353
641
  }
354
- function getHourCanChi(hour, dayJd) {
642
+ function getMonthElement(lunarMonth, lunarYear, locale = "vi") {
643
+ return getElementName(getMonthElementIndex(lunarMonth, lunarYear), locale);
644
+ }
645
+ function getHourElementIndex(hour, dayJd) {
355
646
  const hourBranchIndex = Math.floor((hour + 1) / 2) % 12;
356
647
  const dayStemIndex = (dayJd + 9) % 10;
357
648
  const hourStemOffset = dayStemIndex % 5 * 2;
358
649
  const hourStemIndex = (hourStemOffset + hourBranchIndex) % 10;
359
- return `${HEAVENLY_STEMS[hourStemIndex]} ${EARTHLY_BRANCHES[hourBranchIndex]}`;
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
+ };
360
795
  }
361
796
  var AUSPICIOUS_HOURS_TABLE = [
362
797
  [0, 1, 3, 6, 7, 9],
@@ -372,11 +807,29 @@ var AUSPICIOUS_HOURS_TABLE = [
372
807
  [2, 5, 6, 8, 11, 0]
373
808
  // Ngày Tỵ (5) / Hợi (11)
374
809
  ];
375
- function getAuspiciousHours(dayJd) {
810
+ function getAuspiciousHours(dayJd, locale = "vi") {
376
811
  const branchIndex = (dayJd + 1) % 12;
377
812
  const groupIndex = branchIndex % 6;
378
813
  const hourIndices = AUSPICIOUS_HOURS_TABLE[groupIndex];
379
- return hourIndices.map((i) => EARTHLY_BRANCHES[i]);
814
+ const { earthlyBranches } = t(locale);
815
+ return hourIndices.map((i) => earthlyBranches[i]);
816
+ }
817
+ function getAuspiciousHourIndices(dayJd) {
818
+ const branchIndex = (dayJd + 1) % 12;
819
+ const groupIndex = branchIndex % 6;
820
+ return [...AUSPICIOUS_HOURS_TABLE[groupIndex]];
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]);
380
833
  }
381
834
 
382
835
  // src/utils/format.ts
@@ -435,7 +888,7 @@ function getDayName(day) {
435
888
  }
436
889
  return "Ba M\u01B0\u01A1i";
437
890
  }
438
- function formatLunarDate(lunar, pattern) {
891
+ function formatLunarDate(lunar, pattern, locale = "vi") {
439
892
  let result = pattern;
440
893
  result = result.replace(/yyyy/g, String(lunar.year));
441
894
  result = result.replace(/yy/g, String(lunar.year).slice(-2));
@@ -444,7 +897,7 @@ function formatLunarDate(lunar, pattern) {
444
897
  result = result.replace(/CC/g, lunar.yearCanChi ?? "");
445
898
  result = result.replace(/DC/g, lunar.dayCanChi ?? "");
446
899
  result = result.replace(/MC/g, lunar.monthCanChi ?? "");
447
- result = result.replace(/L/g, lunar.isLeap ? "Nhu\u1EADn" : "");
900
+ result = result.replace(/L/g, lunar.isLeap ? t(locale).leapLabel : "");
448
901
  result = result.replace(/(?<![0-9])d(?![0-9d])/g, String(lunar.day));
449
902
  result = result.replace(/(?<![0-9])M(?![0-9MC])/g, String(lunar.month));
450
903
  return result.trim();
@@ -457,76 +910,107 @@ function formatTraditional(lunar) {
457
910
  return `${dayName} th\xE1ng ${monthName}${leapSuffix} n\u0103m ${yearCanChi}`.trim();
458
911
  }
459
912
 
460
- // src/constants/i18n.ts
461
- var translations = {
462
- vi: {
463
- heavenlyStems: ["Gi\xE1p", "\u1EA4t", "B\xEDnh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\xE2n", "Nh\xE2m", "Qu\xFD"],
464
- earthlyBranches: ["T\xFD", "S\u1EEDu", "D\u1EA7n", "M\xE3o", "Th\xECn", "T\u1EF5", "Ng\u1ECD", "M\xF9i", "Th\xE2n", "D\u1EADu", "Tu\u1EA5t", "H\u1EE3i"],
465
- fiveElements: ["Kim", "M\u1ED9c", "Th\u1EE7y", "H\u1ECFa", "Th\u1ED5"],
466
- zodiacAnimals: ["Chu\u1ED9t", "Tr\xE2u", "C\u1ECDp", "Th\u1ECF", "R\u1ED3ng", "R\u1EAFn", "Ng\u1EF1a", "D\xEA", "Kh\u1EC9", "G\xE0", "Ch\xF3", "Heo"],
467
- monthNames: ["Gi\xEAng", "Hai", "Ba", "T\u01B0", "N\u0103m", "S\xE1u", "B\u1EA3y", "T\xE1m", "Ch\xEDn", "M\u01B0\u1EDDi", "M\u1ED9t", "Ch\u1EA1p"],
468
- weekDays: ["CN", "T2", "T3", "T4", "T5", "T6", "T7"],
469
- leapLabel: "Nhu\u1EADn",
470
- yearLabel: "N\u0103m",
471
- monthLabel: "Th\xE1ng",
472
- destiny: "M\u1EC7nh"
473
- },
474
- en: {
475
- heavenlyStems: ["Gi\xE1p", "\u1EA4t", "B\xEDnh", "\u0110inh", "M\u1EADu", "K\u1EF7", "Canh", "T\xE2n", "Nh\xE2m", "Qu\xFD"],
476
- earthlyBranches: ["T\xFD", "S\u1EEDu", "D\u1EA7n", "M\xE3o", "Th\xECn", "T\u1EF5", "Ng\u1ECD", "M\xF9i", "Th\xE2n", "D\u1EADu", "Tu\u1EA5t", "H\u1EE3i"],
477
- fiveElements: ["Metal", "Wood", "Water", "Fire", "Earth"],
478
- zodiacAnimals: ["Rat", "Ox", "Tiger", "Rabbit", "Dragon", "Snake", "Horse", "Goat", "Monkey", "Rooster", "Dog", "Pig"],
479
- monthNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
480
- weekDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
481
- leapLabel: "Leap",
482
- yearLabel: "Year",
483
- monthLabel: "Month",
484
- destiny: "Destiny"
485
- },
486
- ja: {
487
- heavenlyStems: ["\u7532", "\u4E59", "\u4E19", "\u4E01", "\u620A", "\u5DF1", "\u5E9A", "\u8F9B", "\u58EC", "\u7678"],
488
- earthlyBranches: ["\u5B50", "\u4E11", "\u5BC5", "\u536F", "\u8FB0", "\u5DF3", "\u5348", "\u672A", "\u7533", "\u9149", "\u620C", "\u4EA5"],
489
- fiveElements: ["\u91D1", "\u6728", "\u6C34", "\u706B", "\u571F"],
490
- zodiacAnimals: ["\u9F20", "\u725B", "\u864E", "\u514E", "\u7ADC", "\u86C7", "\u99AC", "\u7F8A", "\u733F", "\u9D8F", "\u72AC", "\u732A"],
491
- monthNames: ["1\u6708", "2\u6708", "3\u6708", "4\u6708", "5\u6708", "6\u6708", "7\u6708", "8\u6708", "9\u6708", "10\u6708", "11\u6708", "12\u6708"],
492
- weekDays: ["\u65E5", "\u6708", "\u706B", "\u6C34", "\u6728", "\u91D1", "\u571F"],
493
- leapLabel: "\u958F",
494
- yearLabel: "\u5E74",
495
- monthLabel: "\u6708",
496
- destiny: "\u547D"
497
- },
498
- ko: {
499
- heavenlyStems: ["\uAC11", "\uC744", "\uBCD1", "\uC815", "\uBB34", "\uAE30", "\uACBD", "\uC2E0", "\uC784", "\uACC4"],
500
- earthlyBranches: ["\uC790", "\uCD95", "\uC778", "\uBB18", "\uC9C4", "\uC0AC", "\uC624", "\uBBF8", "\uC2E0", "\uC720", "\uC220", "\uD574"],
501
- fiveElements: ["\uAE08", "\uBAA9", "\uC218", "\uD654", "\uD1A0"],
502
- zodiacAnimals: ["\uC950", "\uC18C", "\uD638\uB791\uC774", "\uD1A0\uB07C", "\uC6A9", "\uBC40", "\uB9D0", "\uC591", "\uC6D0\uC22D\uC774", "\uB2ED", "\uAC1C", "\uB3FC\uC9C0"],
503
- monthNames: ["1\uC6D4", "2\uC6D4", "3\uC6D4", "4\uC6D4", "5\uC6D4", "6\uC6D4", "7\uC6D4", "8\uC6D4", "9\uC6D4", "10\uC6D4", "11\uC6D4", "12\uC6D4"],
504
- weekDays: ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"],
505
- leapLabel: "\uC724",
506
- yearLabel: "\uB144",
507
- monthLabel: "\uC6D4",
508
- destiny: "\uBA85"
509
- }
510
- };
511
- function t(locale) {
512
- return translations[locale];
913
+ // src/utils/calendar-grid.ts
914
+ function dateKey(date) {
915
+ return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
513
916
  }
514
- function getZodiacAnimal(branchIndex, locale = "vi") {
515
- return translations[locale].zodiacAnimals[branchIndex % 12];
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) {
927
+ const grid = [];
928
+ const firstDay = new Date(year, month - 1, 1);
929
+ const lastDay = new Date(year, month, 0);
930
+ const startingDayOfWeek = (firstDay.getDay() - firstDayOfWeek + 7) % 7;
931
+ const daysInMonth = lastDay.getDate();
932
+ const todayKey = dateKey(/* @__PURE__ */ new Date());
933
+ const selectedKey = selectedDate ? dateKey(selectedDate) : "";
934
+ const prevMonthLastDay = new Date(year, month - 1, 0).getDate();
935
+ const pushCell = (solar, d, m, y, isCurrentMonth) => {
936
+ grid.push({
937
+ solar,
938
+ lunar: LichTa.toLunar(d, m, y),
939
+ isToday: dateKey(solar) === todayKey,
940
+ isSelected: dateKey(solar) === selectedKey,
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
944
+ });
945
+ };
946
+ for (let i = startingDayOfWeek - 1; i >= 0; i--) {
947
+ const d = prevMonthLastDay - i;
948
+ const m = month - 1 < 1 ? 12 : month - 1;
949
+ const y = month - 1 < 1 ? year - 1 : year;
950
+ pushCell(new Date(y, m - 1, d), d, m, y, false);
951
+ }
952
+ for (let d = 1; d <= daysInMonth; d++) {
953
+ pushCell(new Date(year, month - 1, d), d, month, year, true);
954
+ }
955
+ const remaining = 42 - grid.length;
956
+ for (let d = 1; d <= remaining; d++) {
957
+ const m = month + 1 > 12 ? 1 : month + 1;
958
+ const y = month + 1 > 12 ? year + 1 : year;
959
+ pushCell(new Date(y, m - 1, d), d, m, y, false);
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
+ }
968
+ return grid;
516
969
  }
517
970
  // Annotate the CommonJS export names for ESM import in node:
518
971
  0 && (module.exports = {
519
972
  LichTa,
520
973
  formatLunarDate,
521
974
  formatTraditional,
975
+ getAuspiciousHourIndices,
522
976
  getAuspiciousHours,
977
+ getCalendarGrid,
523
978
  getDayCanChi,
979
+ getDayElement,
980
+ getDayElementIndex,
524
981
  getDayName,
982
+ getElementName,
983
+ getElementRelation,
984
+ getElementRelationIndex,
985
+ getHaiBranchIndex,
525
986
  getHourCanChi,
987
+ getHourElement,
988
+ getHourElementIndex,
989
+ getISOWeekNumber,
990
+ getInauspiciousHourIndices,
991
+ getInauspiciousHours,
526
992
  getMonthCanChi,
993
+ getMonthElement,
994
+ getMonthElementIndex,
527
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,
528
1008
  getYearDetails,
529
1009
  getZodiacAnimal,
1010
+ getZodiacConflicts,
1011
+ isHai,
1012
+ isTuHanhXung,
1013
+ isXung,
530
1014
  jdFromDate,
531
1015
  jdToDate,
532
1016
  t