bs-ad-converter
Version:
A library for converting between BS (Bikram Sambat) and AD (Anno Domini) dates.
132 lines • 5.25 kB
JavaScript
// src/nepali-date.ts
import { BS_DATA, DAYS_OF_WEEK, ENGLISH_MONTHS, NEPALI_DAYS, NEPALI_MONTHS, NEPALI_NUMBERS } from './bs-data.js';
/** Check if a Gregorian year is a leap year */
export const isLeapYear = (year) => (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0);
/** Get index of Nepali year in BS_DATA */
const getNepaliYearIndex = (yy) => yy - 2000;
/** Validate English date */
const validateEngDate = (yy, mm, dd) => {
if (yy < 1944 || yy > 2099)
throw new Error('Supported English years are from 1944 to 2099');
if (mm < 1 || mm > 12)
throw new Error('Month must be between 1-12');
if (dd < 1 || dd > 31)
throw new Error('Day must be between 1-31');
};
/** Validate Nepali date */
const validateNepDate = (yy, mm, dd) => {
if (yy < 2000 || yy > 2099)
throw new Error('Supported Nepali years are from 2000 to 2099');
if (mm < 1 || mm > 12)
throw new Error('Month must be between 1-12');
const daysInMonth = BS_DATA[getNepaliYearIndex(yy)]?.[mm] ?? 0;
if (dd < 1 || dd > daysInMonth)
throw new Error(`Day must be between 1-${daysInMonth} for ${yy}-${mm}`);
};
/** Convert English date (yyyy-mm-dd) to Nepali (BS) date */
export const adToBS = (yy, mm, dd) => {
validateEngDate(yy, mm, dd);
const engMonthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const engLeapMonthDays = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Reference: 1944-01-01 AD = 2000-09-17 BS, Saturday (5)
const refEyy = 1944, refEmm = 1, refEdd = 1;
const refNyy = 2000, refNmm = 9, refNdd = 17;
const refDayOfWeek = 6; // Saturday (Sunday = 0, Saturday = 6)
let totalEngDays = 0;
for (let i = refEyy; i < yy; i++) {
totalEngDays += isLeapYear(i) ? 366 : 365;
}
const daysInCurrentYearMonths = isLeapYear(yy) ? engLeapMonthDays : engMonthDays;
for (let i = 1; i < mm; i++) {
totalEngDays += daysInCurrentYearMonths[i];
}
totalEngDays += dd - refEdd;
let nepYear = refNyy, nepMonth = refNmm, nepDate = refNdd;
let daysToAdd = totalEngDays;
while (daysToAdd > 0) {
let daysInCurrentNepMonth = BS_DATA[getNepaliYearIndex(nepYear)]?.[nepMonth] ?? 0;
let daysRemainingInMonth = daysInCurrentNepMonth - nepDate + 1;
if (daysToAdd >= daysRemainingInMonth) {
daysToAdd -= daysRemainingInMonth;
nepMonth++;
nepDate = 1;
if (nepMonth > 12) {
nepYear++;
nepMonth = 1;
}
}
else {
nepDate += daysToAdd;
daysToAdd = 0;
}
}
const dayOfWeek = (refDayOfWeek + totalEngDays) % 7;
return {
year: nepYear,
month: nepMonth,
date: nepDate,
day: NEPALI_DAYS[dayOfWeek],
nmonth: NEPALI_MONTHS[nepMonth - 1],
num_day: dayOfWeek + 1
};
};
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
/** Convert Nepali date (yyyy-mm-dd) to English (AD) date */
export const bsToAD = (yy, mm, dd) => {
validateNepDate(yy, mm, dd);
const engMonthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const engLeapMonthDays = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Reference: 1944-01-01 AD = 2000-09-17 BS, Saturday (5)
const refEyy = 1944, refEmm = 1, refEdd = 1;
const refNyy = 2000, refNmm = 9, refNdd = 17;
const refDayOfWeek = 6; // Saturday (Sunday = 0, Saturday = 6)
let totalNepDays = 0;
for (let i = refNyy; i < yy; i++) {
const yearData = BS_DATA[getNepaliYearIndex(i)];
for (let j = 1; j <= 12; j++) {
totalNepDays += yearData?.[j] ?? 0;
}
}
for (let j = 1; j < mm; j++) {
totalNepDays += BS_DATA[getNepaliYearIndex(yy)]?.[j] ?? 0;
}
totalNepDays += dd - refNdd;
let engYear = refEyy, engMonth = refEmm, engDate = refEdd;
let daysToAdd = totalNepDays;
while (daysToAdd > 0) {
const daysInCurrentEngMonth = isLeapYear(engYear) ? engLeapMonthDays[engMonth] : engMonthDays[engMonth];
const daysRemainingInMonth = daysInCurrentEngMonth - engDate + 1;
if (daysToAdd >= daysRemainingInMonth) {
daysToAdd -= daysRemainingInMonth;
engMonth++;
engDate = 1;
if (engMonth > 12) {
engYear++;
engMonth = 1;
}
}
else {
engDate += daysToAdd;
daysToAdd = 0;
}
}
const dayOfWeek = (refDayOfWeek + totalNepDays) % 7;
return {
year: engYear,
month: engMonth,
date: engDate,
day: DAYS_OF_WEEK[dayOfWeek],
emonth: ENGLISH_MONTHS[engMonth - 1],
num_day: dayOfWeek + 1
};
};
/** Convert number to Nepali numerals */
export const convertToNepaliNumber = (str) => {
return String(str).split('').map(ch => {
const digit = parseInt(ch, 10);
return isNaN(digit) ? ch : NEPALI_NUMBERS[digit];
}).join('');
};
console.log(adToBS(1998, 10, 24));
console.log(bsToAD(2055, 7, 7));
//# sourceMappingURL=test.js.map