@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 CHANGED
@@ -1,12 +1,12 @@
1
1
  # @lichta/core
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@lichta/core.svg)](https://www.npmjs.com/package/@lichta/core)
4
- [![npm version](https://img.shields.io/npm/v/@lichta/react.svg)](https://www.npmjs.com/package/@lichta/react)
5
- [![npm version](https://img.shields.io/npm/v/@lichta/vue.svg)](https://www.npmjs.com/package/@lichta/vue)
6
- [![npm version](https://img.shields.io/npm/v/@lichta/svelte.svg)](https://www.npmjs.com/package/@lichta/svelte)
7
- [![npm version](https://img.shields.io/npm/v/@lichta/full-calendar.svg)](https://www.npmjs.com/package/@lichta/full-calendar)
8
- [![npm version](https://img.shields.io/npm/v/@lichta/event-calendar.svg)](https://www.npmjs.com/package/@lichta/event-calendar)
9
- [![npm version](https://img.shields.io/npm/v/@lichta/react-big-calendar.svg)](https://www.npmjs.com/package/@lichta/react-big-calendar)
3
+ [![@lichta/core](https://img.shields.io/npm/v/@lichta/core.svg?label=%40lichta%2Fcore)](https://www.npmjs.com/package/@lichta/core)
4
+ [![@lichta/react](https://img.shields.io/npm/v/@lichta/react.svg?label=%40lichta%2Freact)](https://www.npmjs.com/package/@lichta/react)
5
+ [![@lichta/vue](https://img.shields.io/npm/v/@lichta/vue.svg?label=%40lichta%2Fvue)](https://www.npmjs.com/package/@lichta/vue)
6
+ [![@lichta/svelte](https://img.shields.io/npm/v/@lichta/svelte.svg?label=%40lichta%2Fsvelte)](https://www.npmjs.com/package/@lichta/svelte)
7
+ [![@lichta/full-calendar](https://img.shields.io/npm/v/@lichta/full-calendar.svg?label=%40lichta%2Ffull-calendar)](https://www.npmjs.com/package/@lichta/full-calendar)
8
+ [![@lichta/event-calendar](https://img.shields.io/npm/v/@lichta/event-calendar.svg?label=%40lichta%2Fevent-calendar)](https://www.npmjs.com/package/@lichta/event-calendar)
9
+ [![@lichta/react-big-calendar](https://img.shields.io/npm/v/@lichta/react-big-calendar.svg?label=%40lichta%2Freact-big-calendar)](https://www.npmjs.com/package/@lichta/react-big-calendar)
10
10
 
11
11
  🚀 **[Demo trực tiếp](https://lichta.zeneo.app/)**
12
12
 
@@ -42,25 +42,102 @@ const lunarGmt8 = LichTa.toLunar(10, 2, 2024, 8);
42
42
  ## Can Chi & Phong Thủy
43
43
 
44
44
  ```typescript
45
- import { LichTa, getYearDetails, getDayCanChi, getMonthCanChi, getHourCanChi, getAuspiciousHours, getAuspiciousHourIndices } from '@lichta/core';
45
+ import { LichTa, getYearDetails, getDayCanChi, getMonthCanChi, getHourCanChi, getAuspiciousHours, getAuspiciousHourIndices, getInauspiciousHours, getInauspiciousHourIndices } from '@lichta/core';
46
46
 
47
47
  getYearDetails(2024);
48
- // → { can: 'Giáp', chi: 'Thìn', menh: 'Thủy', fullString: 'Giáp Thìn - Mệnh Thủy' }
48
+ // → { can: 'Giáp', chi: 'Thìn', menh: 'Hỏa', menhIndex: 3, fullString: 'Giáp Thìn - Mệnh Hỏa' }
49
49
  // getYearDetails() nhận mọi số năm nguyên (kể cả 0 hoặc âm) — chu kỳ Can Chi 60 năm lặp vô hạn.
50
+ // menh dùng bảng tra cứu Nạp Âm 60 Hoa Giáp chuẩn (không phải công thức suy diễn) — xem mục Ngũ Hành bên dưới.
50
51
 
51
52
  const lunar = LichTa.toLunar(10, 2, 2024);
52
53
  getDayCanChi(lunar.jd); // 'Giáp Thìn'
53
54
  getMonthCanChi(lunar.month, lunar.year); // 'Bính Dần'
54
55
  getHourCanChi(8, lunar.jd); // giờ Thìn (7h-9h)
55
- getAuspiciousHours(lunar.jd); // 6 giờ Hoàng Đạo trong ngày (tên Địa Chi)
56
+ getAuspiciousHours(lunar.jd); // ['Tý', 'Mão', 'Thìn', 'Ngọ', 'Dậu', 'Tuất'] — 6 giờ Hoàng Đạo (giờ tốt)
57
+ getInauspiciousHours(lunar.jd); // ['Sửu', 'Dần', 'Tỵ', 'Mùi', 'Thân', 'Hợi'] — 6 giờ Hắc Đạo (giờ xấu), phần bù
56
58
 
57
59
  // Mỗi hàm trên đều nhận thêm tham số `locale` tùy chọn (mặc định 'vi', không đổi hành vi cũ)
58
60
  getDayCanChi(lunar.jd, 'ja'); // Can Chi bằng chữ Nhật
59
61
 
60
62
  // Cần index Địa Chi thay vì tên (ví dụ để tự map sang UI riêng)?
61
- getAuspiciousHourIndices(lunar.jd); // [0, 2, 3, 6, 8, 10] — index 0-11 (0 = Tý)
63
+ getAuspiciousHourIndices(lunar.jd); // [0, 3, 4, 6, 9, 10] — index 0-11 (0 = Tý)
64
+ getInauspiciousHourIndices(lunar.jd); // [1, 2, 5, 7, 8, 11] — phần bù, luôn tăng dần
62
65
  ```
63
66
 
67
+ ## Ngũ Hành (Nạp Âm & Tương Sinh Tương Khắc)
68
+
69
+ ```typescript
70
+ import { getElementName, getDayElement, getMonthElement, getHourElement, getElementRelation, getElementRelationIndex } from '@lichta/core';
71
+
72
+ // Mệnh (Ngũ Hành Nạp Âm) cho Ngày/Tháng/Giờ — dùng chung bảng Nạp Âm 60 Hoa Giáp với getYearDetails()
73
+ getDayElement(lunar.jd); // 'Hỏa' (Giáp Thìn/Ất Tỵ = Phú Đăng Hỏa)
74
+ getMonthElement(lunar.month, lunar.year); // 'Hỏa' (Bính Dần/Đinh Mão = Lư Trung Hỏa)
75
+ getHourElement(8, lunar.jd); // 'Mộc' (giờ Mậu Thìn/Kỷ Tỵ = Đại Lâm Mộc)
76
+
77
+ // Mỗi hàm trên có bản `*Index` đi kèm, trả về index 0-4 (vào FIVE_ELEMENTS) thay vì tên:
78
+ // getDayElementIndex(jd), getMonthElementIndex(month, year), getHourElementIndex(hour, dayJd)
79
+ getElementName(3); // 'Hỏa' — tra tên từ index
80
+
81
+ // Tương sinh / Tương khắc giữa 2 hành (nhận index 0-4, không phải tên — dùng getElementName/*ElementIndex để chuyển đổi)
82
+ getElementRelation(1, 3); // 'Tương sinh' — Mộc (1) sinh Hỏa (3)
83
+ getElementRelation(3, 1); // 'Được sinh' — từ góc nhìn của Hỏa: được Mộc sinh
84
+ getElementRelationIndex(1, 3); // 0 — xem bảng index bên dưới
85
+ ```
86
+
87
+ **Bảng Nạp Âm 60 Hoa Giáp:** không có công thức đóng (closed-form) — đây là bảng tra cứu chuẩn theo quy ước truyền thống, `@lichta/core` dùng bảng tra cứu 30 nhóm thay vì suy diễn bằng công thức cộng (bản trước đây từng dùng công thức cộng trọng số Can+Chi, sai lệch 48/60 tổ hợp so với bảng chuẩn — đã fix).
88
+
89
+ **Index quan hệ Ngũ Hành** (`getElementRelationIndex`): `0` = sinh, `1` = được sinh, `2` = khắc, `3` = bị khắc, `4` = hòa (cùng hành).
90
+
91
+ ## Tiết Khí (24 Solar Terms)
92
+
93
+ ```typescript
94
+ import { getSolarTerm, getSolarTermsInYear, getSolarTermName } from '@lichta/core';
95
+
96
+ getSolarTerm(21, 6, 2024);
97
+ // → { index: 6, name: 'Hạ Chí', date: { day: 21, month: 6, year: 2024 }, jd: 2460483 }
98
+
99
+ getSolarTermsInYear(2024);
100
+ // → mảng 24 Tiết Khí trong năm 2024, theo thứ tự thời gian tăng dần, mỗi phần tử { index, name, date, jd }
101
+
102
+ getSolarTermName(18, 'en'); // 'Winter Solstice' — tra tên thuần túy theo index (0-23) + locale
103
+ ```
104
+
105
+ Index 0 = Xuân Phân (kinh độ Mặt Trời 0°), tăng dần mỗi 15°; 12 index lẻ (1, 3, 5, ..., 23) là **Tiết** (Lập Xuân, Kinh Trập, ...), 12 index chẵn là **Trung Khí** (Xuân Phân, Hạ Chí, Đông Chí, ...). Ngày được tính theo quy ước: nếu thời điểm chuyển Tiết Khí rơi vào bất kỳ lúc nào trong ngày, ngày đó được xem là ngày Tiết Khí bắt đầu (khớp cách almanac truyền thống ghi ngày).
106
+
107
+ ## Trực (12 Kiến Trừ)
108
+
109
+ ```typescript
110
+ import { getTruc, getTrucIndex, getTrucQuality, getTrucQualityIndex } from '@lichta/core';
111
+
112
+ getTruc(lunar.jd); // 'Phá'
113
+ getTrucIndex(lunar.jd); // 6
114
+
115
+ getTrucQuality(getTrucIndex(lunar.jd)); // 'Xấu'
116
+ ```
117
+
118
+ Trực được neo theo **Tiết** (12 mốc: Lập Xuân, Kinh Trập, ...) — **không** theo số tháng âm lịch, vì tháng nhuận âm lịch không tương ứng với một Tiết mới (dùng số tháng âm lịch sẽ cho kết quả sai trong các tháng nhuận). Ngày Tiết bắt đầu luôn là "Kiến", Trực tăng dần 1 mỗi ngày và reset về "Kiến" vào Tiết kế tiếp.
119
+
120
+ `getTrucQuality()`/`getTrucQualityIndex()` chỉ phân loại dứt khoát **Phá, Nguy = Xấu** và **Thành, Khai = Tốt** — 4 Trực có sự đồng thuận rất cao giữa các nguồn. 8 Trực còn lại (Kiến, Trừ, Mãn, Bình, Định, Chấp, Thu, Bế) được xếp **"Trung bình"** một cách bảo thủ, vì mức tốt/xấu chi tiết của chúng phụ thuộc vào từng việc cụ thể và có dị bản giữa các nguồn almanac.
121
+
122
+ ## Kỵ — Tuổi Xung Khắc
123
+
124
+ ```typescript
125
+ import { isXung, isHai, isTuHanhXung, getZodiacConflicts, getXungBranchIndex, getHaiBranchIndex, getTuHanhXungGroupMembers } from '@lichta/core';
126
+
127
+ // Tý (0) và Ngọ (6): vừa Lục Xung vừa cùng nhóm Tứ Hành Xung
128
+ getZodiacConflicts(0, 6);
129
+ // → { xung: true, hai: false, tuHanhXung: true }
130
+
131
+ isXung(0, 6); // true — Lục Xung: Tý-Ngọ, Sửu-Mùi, Dần-Thân, Mão-Dậu, Thìn-Tuất, Tỵ-Hợi
132
+ isHai(0, 7); // true — Lục Hại: Tý-Mùi, Sửu-Ngọ, Dần-Tỵ, Mão-Thìn, Thân-Hợi, Dậu-Tuất
133
+ isTuHanhXung(0, 3); // true — Tứ Hành Xung: {Tý,Mão,Ngọ,Dậu} / {Dần,Tỵ,Thân,Hợi} / {Sửu,Thìn,Mùi,Tuất}
134
+
135
+ getXungBranchIndex(0); // 6 — Chi đối xung với Tý
136
+ getTuHanhXungGroupMembers(0); // [0, 3, 6, 9] — cả nhóm chứa Tý
137
+ ```
138
+
139
+ Tất cả nhận vào **index Địa Chi (0-11, 0 = Tý)**, cùng thứ tự với `getZodiacAnimal()`.
140
+
64
141
  ## Format & Hiển thị
65
142
 
66
143
  ```typescript
@@ -81,13 +158,17 @@ formatLunarDate(lunar, 'dd/MM/yyyy', 'en');
81
158
 
82
159
  ## Lưới lịch tháng (dựng UI Calendar riêng)
83
160
 
84
- Nếu bạn muốn tự dựng UI lịch tháng thay vì dùng component `Calendar` có sẵn (xem [`@lichta/react`](https://www.npmjs.com/package/@lichta/react)/[`@lichta/vue`](https://www.npmjs.com/package/@lichta/vue)/[`@lichta/svelte`](https://www.npmjs.com/package/@lichta/svelte)), `getCalendarGrid()` dựng sẵn lưới 42 ô (6 tuần) cho 1 tháng, gồm cả ngày tràn từ tháng trước/sau và ngày âm lịch tương ứng cho mỗi ô — đây cũng chính là hàm mà `Calendar` và `DatePicker` ở các package binding dùng nội bộ.
161
+ Nếu bạn muốn tự dựng UI lịch tháng thay vì dùng component `Calendar` có sẵn (xem [`@lichta/react`](https://www.npmjs.com/package/@lichta/react)/[`@lichta/vue`](https://www.npmjs.com/package/@lichta/vue)/[`@lichta/svelte`](https://www.npmjs.com/package/@lichta/svelte)), `getCalendarGrid()` dựng sẵn lưới 42 ô (6 tuần) cho 1 tháng, gồm cả ngày tràn từ tháng trước/sau và ngày âm lịch tương ứng cho mỗi ô — đây cũng chính là hàm mà `Calendar` và `DatePicker` ở các package binding dùng nội bộ. Hàm này hỗ trợ cả tuần bắt đầu từ Chủ Nhật (0, mặc định) hoặc Thứ Hai (1).
85
162
 
86
163
  ```typescript
87
- import { getCalendarGrid } from '@lichta/core';
164
+ import { getCalendarGrid, getISOWeekNumber } from '@lichta/core';
165
+
166
+ // Lấy lưới lịch với tuần bắt đầu bằng Thứ Hai (1)
167
+ const grid = getCalendarGrid(2, 2024, null, 1); // tháng, năm, ngày đang chọn (hoặc null), FirstDayOfWeek (0 | 1)
168
+ // → CalendarDayCell[42], mỗi ô: { solar: Date, lunar: LunarDate, isToday, isSelected, isCurrentMonth, weekNumber: number }
88
169
 
89
- const grid = getCalendarGrid(2, 2024, null); // tháng, năm, ngày đang chọn (hoặc null)
90
- // CalendarDayCell[42], mỗi ô: { solar: Date, lunar: LunarDate, isToday, isSelected, isCurrentMonth }
170
+ // Lấy số tuần theo chuẩn ISO-8601
171
+ const weekNum = getISOWeekNumber(new Date(2024, 0, 1)); // 1
91
172
  ```
92
173
 
93
174
  ## i18n
@@ -112,11 +193,15 @@ getZodiacAnimal(0, 'vi'); // 'Chuột'
112
193
  |---|---|
113
194
  | Solar ↔ Lunar | `LichTa.toLunar()`, `LichTa.toSolar()` |
114
195
  | Julian Day Number | `jdFromDate()`, `jdToDate()` |
115
- | Can Chi & Phong Thủy | `getYearDetails()`, `getDayCanChi()`, `getMonthCanChi()`, `getHourCanChi()`, `getAuspiciousHours()`, `getAuspiciousHourIndices()` |
196
+ | Can Chi & Phong Thủy | `getYearDetails()`, `getDayCanChi()`, `getMonthCanChi()`, `getHourCanChi()`, `getAuspiciousHours()`, `getAuspiciousHourIndices()`, `getInauspiciousHours()`, `getInauspiciousHourIndices()` |
197
+ | Ngũ Hành | `getElementName()`, `getDayElement()`, `getDayElementIndex()`, `getMonthElement()`, `getMonthElementIndex()`, `getHourElement()`, `getHourElementIndex()`, `getElementRelation()`, `getElementRelationIndex()` |
198
+ | Tiết Khí | `getSolarTerm()`, `getSolarTermsInYear()`, `getSolarTermName()` |
199
+ | Trực | `getTruc()`, `getTrucIndex()`, `getTrucName()`, `getTrucQuality()`, `getTrucQualityIndex()` |
200
+ | Kỵ — Tuổi Xung Khắc | `isXung()`, `isHai()`, `isTuHanhXung()`, `getZodiacConflicts()`, `getXungBranchIndex()`, `getHaiBranchIndex()`, `getTuHanhXungGroupIndex()`, `getTuHanhXungGroupMembers()` |
116
201
  | Format & Hiển thị | `formatLunarDate()`, `formatTraditional()`, `getMonthName()`, `getDayName()` |
117
- | Lưới lịch | `getCalendarGrid()` |
118
- | i18n | `t()`, `getZodiacAnimal()` |
119
- | Types | `LunarDate`, `SolarDate`, `Locale`, `YearDetails`, `CalendarDayCell` |
202
+ | Lưới lịch | `getCalendarGrid()`, `getISOWeekNumber()` |
203
+ | i18n | `t()`, `getZodiacAnimal()`, `getWeekDayLabels()` |
204
+ | Types | `LunarDate`, `SolarDate`, `Locale`, `YearDetails`, `SolarTerm`, `ZodiacConflicts`, `CalendarDayCell`, `FirstDayOfWeek` |
120
205
 
121
206
  Xem chi tiết đầy đủ (tham số, kiểu trả về, ví dụ đã chạy thật) tại trang [API Reference](https://lichta.zeneo.app/api).
122
207