@thyrith/momentkh 3.0.0 → 3.0.1
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 +56 -56
- package/dist/momentkh.d.ts +43 -28
- package/dist/momentkh.d.ts.map +1 -1
- package/dist/momentkh.js +99 -88
- package/momentkh.js +1087 -11
- package/momentkh.ts +102 -98
- package/package.json +3 -2
package/momentkh.ts
CHANGED
|
@@ -24,20 +24,20 @@ export enum MoonPhase {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export enum MonthIndex {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
Migasir = 0, // មិគសិរ
|
|
28
|
+
Boss = 1, // បុស្ស
|
|
29
29
|
Meak = 2, // មាឃ
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
Phalkun = 3, // ផល្គុន
|
|
31
|
+
Cheit = 4, // ចេត្រ
|
|
32
|
+
Pisakh = 5, // ពិសាខ
|
|
33
33
|
Jesth = 6, // ជេស្ឋ
|
|
34
|
-
|
|
34
|
+
Asadh = 7, // អាសាឍ
|
|
35
35
|
Srap = 8, // ស្រាពណ៍
|
|
36
|
-
|
|
36
|
+
Phatrabot = 9, // ភទ្របទ
|
|
37
37
|
Assoch = 10, // អស្សុជ
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
Kadeuk = 11, // កត្ដិក
|
|
39
|
+
Pathamasadh = 12, // បឋមាសាឍ
|
|
40
|
+
Tutiyasadh = 13 // ទុតិយាសាឍ
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export enum AnimalYear {
|
|
@@ -56,16 +56,16 @@ export enum AnimalYear {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
export enum EraYear {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
SamridhiSak = 0, // សំរឹទ្ធិស័ក
|
|
60
|
+
AekSak = 1, // ឯកស័ក
|
|
61
|
+
ToSak = 2, // ទោស័ក
|
|
62
|
+
TreiSak = 3, // ត្រីស័ក
|
|
63
|
+
ChattvaSak = 4, // ចត្វាស័ក
|
|
64
|
+
PanchaSak = 5, // បញ្ចស័ក
|
|
65
|
+
ChhaSak = 6, // ឆស័ក
|
|
66
|
+
SappaSak = 7, // សប្តស័ក
|
|
67
|
+
AtthaSak = 8, // អដ្ឋស័ក
|
|
68
|
+
NappaSak = 9 // នព្វស័ក
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
export enum DayOfWeek {
|
|
@@ -531,7 +531,7 @@ function getNumberOfDaysInKhmerMonth(monthIndex: MonthIndex | number, beYear: nu
|
|
|
531
531
|
if (idx === MonthIndex.Jesth && leapType === 2) { // ជេស្ឋ with leap day
|
|
532
532
|
return 30;
|
|
533
533
|
}
|
|
534
|
-
if (idx === MonthIndex.
|
|
534
|
+
if (idx === MonthIndex.Pathamasadh || idx === MonthIndex.Tutiyasadh) { // បឋមាសាឍ, ទុតិយាសាឍ
|
|
535
535
|
return leapType === 1 ? 30 : 0;
|
|
536
536
|
}
|
|
537
537
|
// Alternating pattern: even months = 29 days, odd months = 30 days
|
|
@@ -551,11 +551,11 @@ function nextMonthOf(monthIndex: MonthIndex | number, beYear: number): MonthInde
|
|
|
551
551
|
const idx = typeof monthIndex === 'number' ? monthIndex : monthIndex as number;
|
|
552
552
|
|
|
553
553
|
if (idx === MonthIndex.Jesth && leapType === 1) { // ជេស្ឋ in leap month year
|
|
554
|
-
return MonthIndex.
|
|
554
|
+
return MonthIndex.Pathamasadh; // បឋមាសាឍ
|
|
555
555
|
}
|
|
556
|
-
if (idx === MonthIndex.
|
|
557
|
-
if (idx === MonthIndex.
|
|
558
|
-
if (idx === MonthIndex.
|
|
556
|
+
if (idx === MonthIndex.Kadeuk) return MonthIndex.Migasir; // កត្ដិក -> មិគសិរ
|
|
557
|
+
if (idx === MonthIndex.Pathamasadh) return MonthIndex.Tutiyasadh; // បឋមាសាឍ -> ទុតិយាសាឍ
|
|
558
|
+
if (idx === MonthIndex.Tutiyasadh) return MonthIndex.Srap; // ទុតិយាសាឍ -> ស្រាពណ៍
|
|
559
559
|
|
|
560
560
|
return (idx + 1) as MonthIndex;
|
|
561
561
|
}
|
|
@@ -564,10 +564,10 @@ function previousMonthOf(monthIndex: MonthIndex | number, beYear: number): Month
|
|
|
564
564
|
const leapType = getLeapType(beYear);
|
|
565
565
|
const idx = typeof monthIndex === 'number' ? monthIndex : monthIndex as number;
|
|
566
566
|
|
|
567
|
-
if (idx === MonthIndex.
|
|
568
|
-
if (idx === MonthIndex.Srap && leapType === 1) return MonthIndex.
|
|
569
|
-
if (idx === MonthIndex.
|
|
570
|
-
if (idx === MonthIndex.
|
|
567
|
+
if (idx === MonthIndex.Migasir) return MonthIndex.Kadeuk; // មិគសិរ -> កត្ដិក
|
|
568
|
+
if (idx === MonthIndex.Srap && leapType === 1) return MonthIndex.Tutiyasadh; // ស្រាពណ៍ -> ទុតិយាសាឍ (leap)
|
|
569
|
+
if (idx === MonthIndex.Tutiyasadh) return MonthIndex.Pathamasadh; // ទុតិយាសាឍ -> បឋមាសាឍ
|
|
570
|
+
if (idx === MonthIndex.Pathamasadh) return MonthIndex.Jesth; // បឋមាសាឍ -> ជេស្ឋ
|
|
571
571
|
|
|
572
572
|
return (idx - 1) as MonthIndex;
|
|
573
573
|
}
|
|
@@ -784,7 +784,7 @@ class KhmerDate {
|
|
|
784
784
|
const newDay = KhmerDate.fromDayNumber(newDayNum);
|
|
785
785
|
|
|
786
786
|
let newBeYear = result.beYear;
|
|
787
|
-
if (result.monthIndex === MonthIndex.
|
|
787
|
+
if (result.monthIndex === MonthIndex.Pisakh) { // ពិសាខ
|
|
788
788
|
if (result.moonPhase === MoonPhase.Waxing && newDay.moonPhase === MoonPhase.Waning) {
|
|
789
789
|
newBeYear++;
|
|
790
790
|
}
|
|
@@ -795,7 +795,7 @@ class KhmerDate {
|
|
|
795
795
|
} else {
|
|
796
796
|
remaining -= (daysLeftInMonth + 1);
|
|
797
797
|
const nextMonth = nextMonthOf(result.monthIndex, result.beYear);
|
|
798
|
-
const newBeYear = (result.monthIndex === MonthIndex.
|
|
798
|
+
const newBeYear = (result.monthIndex === MonthIndex.Cheit) ? result.beYear + 1 : result.beYear;
|
|
799
799
|
result = new KhmerDate(1, MoonPhase.Waxing, nextMonth, newBeYear); // Start at 1កើត
|
|
800
800
|
}
|
|
801
801
|
}
|
|
@@ -817,7 +817,7 @@ class KhmerDate {
|
|
|
817
817
|
const newDay = KhmerDate.fromDayNumber(newDayNum);
|
|
818
818
|
|
|
819
819
|
let newBeYear = result.beYear;
|
|
820
|
-
if (result.monthIndex === MonthIndex.
|
|
820
|
+
if (result.monthIndex === MonthIndex.Pisakh) { // ពិសាខ
|
|
821
821
|
if (result.moonPhase === MoonPhase.Waning && newDay.moonPhase === MoonPhase.Waxing) {
|
|
822
822
|
newBeYear--;
|
|
823
823
|
}
|
|
@@ -828,7 +828,7 @@ class KhmerDate {
|
|
|
828
828
|
} else {
|
|
829
829
|
remaining -= (currentDayNum + 1);
|
|
830
830
|
const prevMonth = previousMonthOf(result.monthIndex, result.beYear);
|
|
831
|
-
const newBeYear = (result.monthIndex === MonthIndex.
|
|
831
|
+
const newBeYear = (result.monthIndex === MonthIndex.Pisakh) ? result.beYear - 1 : result.beYear;
|
|
832
832
|
const daysInPrevMonth = getNumberOfDaysInKhmerMonth(prevMonth, newBeYear);
|
|
833
833
|
const newDay = KhmerDate.fromDayNumber(daysInPrevMonth - 1);
|
|
834
834
|
result = new KhmerDate(newDay.day, newDay.moonPhase, prevMonth, newBeYear);
|
|
@@ -857,7 +857,7 @@ function getMaybeBEYear(year: number, month: number): number {
|
|
|
857
857
|
}
|
|
858
858
|
}
|
|
859
859
|
|
|
860
|
-
// Cache for
|
|
860
|
+
// Cache for Pisakha Bochea dates by year
|
|
861
861
|
const visakhaBocheaCache: Record<number, number> = {};
|
|
862
862
|
|
|
863
863
|
// Cache for New Year Full Info
|
|
@@ -868,7 +868,7 @@ const newYearInfoCache: Record<number, NewYearFullInfo> = {};
|
|
|
868
868
|
* BE year increases on ១រោច ខែពិសាខ (1st waning day of Pisakh = dayNumber 15 of month 5)
|
|
869
869
|
* Returns timestamp in milliseconds at midnight of that day
|
|
870
870
|
*/
|
|
871
|
-
function
|
|
871
|
+
function getPisakhaBochea(year: number, isSearching: boolean = false): number {
|
|
872
872
|
if (visakhaBocheaCache[year]) {
|
|
873
873
|
return visakhaBocheaCache[year];
|
|
874
874
|
}
|
|
@@ -879,7 +879,7 @@ function getVisakhaBochea(year: number, isSearching: boolean = false): number {
|
|
|
879
879
|
for (let searchDay = 1; searchDay <= daysInMonth; searchDay++) {
|
|
880
880
|
// Avoid infinite recursion by using simplified BE year during search
|
|
881
881
|
const result = gregorianToKhmerInternal(year, searchMonth, searchDay, 12, 0, 0, true);
|
|
882
|
-
if (result.khmer.monthIndex === MonthIndex.
|
|
882
|
+
if (result.khmer.monthIndex === MonthIndex.Pisakh && result._khmerDateObj.getDayNumber() === 15) {
|
|
883
883
|
// Found 1រោច Pisakh - return timestamp at midnight (start of BE year change day)
|
|
884
884
|
// BE year changes at 00:00 on this day
|
|
885
885
|
const timestamp = new Date(year, searchMonth - 1, searchDay, 0, 0, 0, 0).getTime();
|
|
@@ -982,7 +982,7 @@ function gregorianToKhmerInternal(
|
|
|
982
982
|
} else {
|
|
983
983
|
// Normal mode: compare against exact BE year transition datetime (1រោច Pisakh at 00:00)
|
|
984
984
|
const inputTimestamp = new Date(year, month - 1, day, hour, minute, second).getTime();
|
|
985
|
-
const beYearTransitionTimestamp =
|
|
985
|
+
const beYearTransitionTimestamp = getPisakhaBochea(year);
|
|
986
986
|
|
|
987
987
|
if (inputTimestamp >= beYearTransitionTimestamp) {
|
|
988
988
|
// On or after 1រោច Pisakh (new BE year)
|
|
@@ -998,15 +998,15 @@ function gregorianToKhmerInternal(
|
|
|
998
998
|
let animalYearIndex = ((beYear + 4) % 12 + 12) % 12;
|
|
999
999
|
|
|
1000
1000
|
// Adjust Era and Animal Year based on Khmer New Year logic
|
|
1001
|
-
// They should change at New Year, not wait for
|
|
1001
|
+
// They should change at New Year, not wait for Pisakha Bochea (which changes BE)
|
|
1002
1002
|
if (!isSearching) {
|
|
1003
1003
|
const newYearInfo = getNewYearFullInfo(year);
|
|
1004
1004
|
const inputTimestamp = new Date(year, month - 1, day, hour, minute, second).getTime();
|
|
1005
|
-
const visakhaBocheaTimestamp =
|
|
1005
|
+
const visakhaBocheaTimestamp = getPisakhaBochea(year);
|
|
1006
1006
|
|
|
1007
1007
|
// Animal Year changes at Moha Songkran (exact New Year time)
|
|
1008
|
-
// Only apply manual increment if we are in the gap between New Year and
|
|
1009
|
-
// (After
|
|
1008
|
+
// Only apply manual increment if we are in the gap between New Year and Pisakha Bochea
|
|
1009
|
+
// (After Pisakha Bochea, the BE year increments, so the formula based on BE automatically gives the new Animal Year)
|
|
1010
1010
|
if (inputTimestamp >= newYearInfo.newYearMoment.getTime() && inputTimestamp <= visakhaBocheaTimestamp) {
|
|
1011
1011
|
animalYearIndex = (animalYearIndex + 1) % 12;
|
|
1012
1012
|
}
|
|
@@ -1068,7 +1068,7 @@ function khmerToGregorian(day: number, moonPhase: MoonPhase | number, monthIndex
|
|
|
1068
1068
|
for (let gDay = 1; gDay <= daysInMonth; gDay++) {
|
|
1069
1069
|
// For BE year transition day (1រោច Pisakh) and the day before (15កើត Pisakh),
|
|
1070
1070
|
// check multiple times during the day because BE year can change during this period
|
|
1071
|
-
const isAroundBEYearChange = monthIndexNum === MonthIndex.
|
|
1071
|
+
const isAroundBEYearChange = monthIndexNum === MonthIndex.Pisakh &&
|
|
1072
1072
|
((day === 15 && moonPhaseNum === MoonPhase.Waxing) || (day === 1 && moonPhaseNum === MoonPhase.Waning));
|
|
1073
1073
|
const timesToCheck = isAroundBEYearChange
|
|
1074
1074
|
? [0, 6, 12, 18, 23] // Check at different hours
|
|
@@ -1225,7 +1225,7 @@ function getKhmerNewYear(ceYear: number): NewYearInfo {
|
|
|
1225
1225
|
// Formatting Functions
|
|
1226
1226
|
// ============================================================================
|
|
1227
1227
|
|
|
1228
|
-
function
|
|
1228
|
+
function formatKhmer(khmerData: KhmerConversionResult, formatString?: string): string {
|
|
1229
1229
|
if (!formatString) {
|
|
1230
1230
|
// Default format
|
|
1231
1231
|
const { khmer } = khmerData;
|
|
@@ -1274,64 +1274,68 @@ function gregorianToKhmer(year: number, month: number, day: number, hour: number
|
|
|
1274
1274
|
// Public API
|
|
1275
1275
|
// ============================================================================
|
|
1276
1276
|
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1277
|
+
// Conversion functions
|
|
1278
|
+
export function fromGregorian(year: number, month: number, day: number, hour: number = 0, minute: number = 0, second: number = 0): KhmerConversionResult {
|
|
1279
|
+
return gregorianToKhmer(year, month, day, hour, minute, second);
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
export function fromKhmer(day: number, moonPhase: MoonPhase | number, monthIndex: MonthIndex | number, beYear: number): GregorianDate {
|
|
1283
|
+
return khmerToGregorian(day, moonPhase, monthIndex, beYear);
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// New Year function
|
|
1287
|
+
export function getNewYear(ceYear: number): NewYearInfo {
|
|
1288
|
+
return getKhmerNewYear(ceYear);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// Format function
|
|
1292
|
+
export function format(khmerData: KhmerConversionResult, formatString?: string): string {
|
|
1293
|
+
return formatKhmer(khmerData, formatString);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// Utility for creating date from Date object
|
|
1297
|
+
export function fromDate(date: Date): KhmerConversionResult {
|
|
1298
|
+
// Validate Date object
|
|
1299
|
+
validateDateObject(date);
|
|
1300
|
+
return gregorianToKhmer(
|
|
1301
|
+
date.getFullYear(),
|
|
1302
|
+
date.getMonth() + 1,
|
|
1303
|
+
date.getDate(),
|
|
1304
|
+
date.getHours(),
|
|
1305
|
+
date.getMinutes(),
|
|
1306
|
+
date.getSeconds()
|
|
1307
|
+
);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
// Convert Khmer to Date object
|
|
1311
|
+
export function toDate(day: number, moonPhase: MoonPhase | number, monthIndex: MonthIndex | number, beYear: number): Date {
|
|
1312
|
+
const greg = khmerToGregorian(day, moonPhase, monthIndex, beYear);
|
|
1313
|
+
return new Date(greg.year, greg.month - 1, greg.day);
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
// Constants export
|
|
1317
|
+
export const constants = {
|
|
1318
|
+
LunarMonths,
|
|
1319
|
+
LunarMonthNames,
|
|
1320
|
+
SolarMonthNames,
|
|
1321
|
+
AnimalYearNames,
|
|
1322
|
+
EraYearNames,
|
|
1323
|
+
WeekdayNames,
|
|
1324
|
+
MoonStatusNames
|
|
1325
|
+
};
|
|
1326
|
+
|
|
1327
|
+
// Default export - aggregate all exports for convenience
|
|
1328
|
+
export default {
|
|
1329
|
+
fromGregorian,
|
|
1330
|
+
fromKhmer,
|
|
1331
|
+
getNewYear,
|
|
1332
|
+
format,
|
|
1333
|
+
fromDate,
|
|
1334
|
+
toDate,
|
|
1335
|
+
constants,
|
|
1329
1336
|
MoonPhase,
|
|
1330
1337
|
MonthIndex,
|
|
1331
1338
|
AnimalYear,
|
|
1332
1339
|
EraYear,
|
|
1333
1340
|
DayOfWeek
|
|
1334
1341
|
};
|
|
1335
|
-
|
|
1336
|
-
// Default export
|
|
1337
|
-
export default momentkh;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thyrith/momentkh",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Working on khmer calendar by implementting moment js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "component",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"LICENSE"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
|
-
"build": "tsc",
|
|
19
|
+
"build": "tsc && node build-browser.js",
|
|
20
|
+
"build:dist": "tsc",
|
|
20
21
|
"test": "npm run test:validation && npm run test:gregorian && npm run test:khmer && npm run test:newyear && npm run test:verify-conversion && npm run test:verify-newyear && npm run test:verify-roundtrip",
|
|
21
22
|
"test:validation": "node test/validation.test.js",
|
|
22
23
|
"test:gregorian": "node test/gregorian-to-khmer.test.js",
|