If you've ever built a web or mobile application in Nepal, you know the struggle.
Handling Bikram Sambat (BS) dates in JavaScript has historically been painful:
- ❌ Legacy libraries from 2014 with outdated
Dateprototype modifications. - ❌ No Day.js / date-fns syntax parity, forcing you to learn awkward, proprietary helper functions.
- ❌ Bloated bundles loaded with megabytes of un-treeshakable JSON.
- ❌ Missing TypeScript types or broken CJS/ESM compatibility in modern bundlers (Next.js App Router, Vite, Turbopack).
- ❌ No headless UI support, forcing you to use un-themeable, rigid datepicker widgets from the jQuery era.
- ❌ Zero built-in support for Nepali Fiscal Years (
आर्थिक वर्ष), Banking Workdays (T+2 settlements), KYC age verification, or Devanagari numerals (०-९).
Today, that changes. 🎉
Introducing bsday.js — an ultra-fast, zero-dependency, Day.js-compatible dual calendar (Bikram Sambat ↔ Gregorian) SDK and 111-year astronomical Panchang engine for modern JavaScript and TypeScript.
🌟 What is bsday.js?
bsday.js is a modern, modular ecosystem built from the ground up for modern web development:
bsday.js Ecosystem
├── 📦 @bsday.js/core # ~12KB gzipped, zero-dep dual calendar engine with Day.js API parity
├── 🕉️ @bsday.js/dataset # 111-Year (1990–2100 BS / 40,543 days) astronomical Panchang & festivals
├── ⚛️ @bsday.js/react # Headless React hooks (useBSDatePicker, useBSRangePicker, WAI-ARIA)
├── 🟢 @bsday.js/vue # Vue 3 Composition API composables with v-model support
├── 🅰️ @bsday.js/angular # Headless Angular Signals & Reactive Form ControlValueAccessor
└── 🟧 @bsday.js/svelte # Svelte 4/5 reactive stores and runes primitives
🌐 Interactive Playground: https://bsdayjs.vercel.app
📖 Full Documentation: https://bsdayjs.vercel.app/docs
🐙 GitHub Repository: https://github.com/shurajcodx/bsday.js
🚀 Quick start in 60 Seconds
Install the core package:
npm install @bsday.js/core
# or
pnpm add @bsday.js/core
# or
yarn add @bsday.js/core
1. Familiar Day.js syntax parity
If you know Day.js or Moment.js, you already know bsday.js:
import bsday from '@bsday.js/core';
// 1. Create a Bikram Sambat Date
const today = bsday(); // Current BS date
const customDate = bsday.bs(2081, 5, 15); // Bhadra 15, 2081
// 2. Chaining & Date Arithmetic
const nextMonth = customDate.add(1, 'month').subtract(2, 'day');
console.log(nextMonth.format('YYYY/MM/DD')); // "2081/06/13"
// 3. Bidirectional BS ↔ AD Conversion
const adDate = customDate.toAD(); // Native JavaScript Date: 2024-08-31
const bsFromAD = bsday(new Date('2024-08-31')); // Converted back to BS
// 4. Start/End of Unit
console.log(customDate.startOf('month').format('YYYY/MM/DD')); // "2081/05/01"
console.log(customDate.endOf('month').format('YYYY/MM/DD')); // "2081/05/31"
// 5. Query & Comparisons
console.log(customDate.isBefore(nextMonth)); // true
console.log(customDate.isSame(bsday.bs(2081, 5, 15), 'day')); // true
🇳🇵 6 Killer features you'll love
1. Direct devanagari numeral string parsing (०-९)
Users in Nepal often paste or type dates in Devanagari script. bsday.js handles both ASCII and Devanagari numerals natively:
import bsday, { normalizeNepaliDigits, toDevanagariDigits } from '@bsday.js/core';
// Parse Devanagari string directly!
const date = bsday.bs('२०८१/०५/१५');
console.log(date.format('YYYY-MM-DD')); // "2081-05-15"
// Localize to Nepali with Devanagari output
console.log(date.locale('ne').format('YYYY MMMM DD, dddd'));
// Output: "२०८१ भाद्र १५, शनिबार"
// Standalone conversion helpers
console.log(toDevanagariDigits('2081/05/15')); // "२०८१/०५/१५"
console.log(normalizeNepaliDigits('२०८१/०५/१५')); // "2081/05/15"
2. Built-in nepali banking & business day engine 🏦
In Nepal, the workweek runs from Sunday to Friday, with Saturday as the national weekend. Public holidays during Dashain, Tihar, or Shivaratri alter settlement deadlines (T+2 in NEPSE / clearing house SLA).
bsday.js has a first-class business day calculation engine:
import bsday from '@bsday.js/core';
const friday = bsday.bs(2081, 5, 14); // Friday
// Check business day status
console.log(friday.isBusinessDay()); // true
console.log(friday.isSaturday); // false
// Add business days (automatically skips Saturdays and holidays!)
const nextWorkday = friday.addBusinessDays(1);
console.log(nextWorkday.format('YYYY/MM/DD')); // Sunday: 2081/05/16 (skips Saturday!)
// Calculate workdays between two dates
const start = bsday.bs(2081, 5, 1);
const end = bsday.bs(2081, 5, 15);
console.log(start.businessDaysBetween(end)); // Exact count excluding Saturdays
3. Nepali fiscal year (आर्थिक वर्ष) Engine 📊
Nepali fiscal years start on Shrawan 1 and end on Ashadh End. Calculating tax quarters and fiscal representations (FY 2081/82 or आ.व. २०८१/८२) is now a one-liner:
import bsday from '@bsday.js/core';
const taxDate = bsday.bs(2081, 5, 15); // Bhadra 2081
console.log(taxDate.fiscalYear('short')); // "2081/82"
console.log(taxDate.fiscalYear('extended')); // "FY 2081/82"
console.log(taxDate.locale('ne').fiscalYear('extended')); // "आ.व. २०८१/८२"
// Fiscal Quarters (Q1: Shrawan–Ashwin, Q2: Kartik–Poush, etc.)
console.log(taxDate.fiscalQuarter()); // 1
// Start and End of Fiscal Year
const fyStart = taxDate.startOf('fiscalYear'); // 2081/04/01 (Shrawan 1)
const fyEnd = taxDate.endOf('fiscalYear'); // 2082/03/31 (Ashadh 31)
4. KYC & chronological age verification 🆔
Building banking KYC or onboarding verification? Calculate precise chronological age in years, months, and days:
import bsday from '@bsday.js/core';
const dob = bsday.bs(2062, 10, 5); // Magh 5, 2062
// Check legal age threshold
console.log(dob.isAdult(18)); // true
// Exact breakdown
const ageInfo = dob.age();
console.log(ageInfo); // { years: 19, months: 7, days: 10 }
console.log(dob.formatAge()); // "19 years, 7 months, 10 days"
5. 111-Year astronomical vedic panchang dataset 🕉️
Need Tithi, Nakshatra, Yoga, Karana, Sunrise/Sunset, or Dashain/Tihar festival dates?
Install the dataset package:
npm install @bsday.js/dataset
import { bsday, BSDay } from '@bsday.js/core';
import { dataset } from '@bsday.js/dataset/all';
// Hydrate 111-year dataset (1990–2100 BS / 40,543 verified days)
BSDay.setDataset(dataset);
const dashami = bsday.bs(2081, 6, 26).locale('ne');
console.log(dashami.tithi); // "दशमी" (Dashami)
console.log(dashami.festivals); // ["विजया दशमी"]
console.log(dashami.isHoliday); // true
// Astronomical details
const astro = dashami.data('en');
console.log(astro?.nakshatra); // "Shravana"
console.log(astro?.sunrise); // "06:04 AM"
6. Headless react hook (@bsday.js/react) ⚛️
Build stunning, custom Tailwind CSS datepickers without fighting opinionated styles. Full WAI-ARIA accessibility and keyboard navigation included!
npm install @bsday.js/react @bsday.js/core
import React from 'react';
import { useBSDatePicker } from '@bsday.js/react';
export function NepaliDatePicker() {
const {
isOpen,
setIsOpen,
viewYear,
viewMonth,
selectedDate,
calendarMatrix,
selectDate,
nextMonth,
prevMonth,
} = useBSDatePicker({
defaultValue: '2081/05/15',
closeOnSelect: true,
});
return (
<div className="relative inline-block">
{/* Trigger Input */}
<button
onClick={() => setIsOpen(!isOpen)}
className="px-4 py-2 bg-white dark:bg-slate-900 border rounded-xl shadow-sm text-sm font-medium"
>
📅 {selectedDate ? selectedDate.format('YYYY/MM/DD') : 'Select BS Date'}
</button>
{/* Calendar Dropdown */}
{isOpen && (
<div className="absolute top-12 left-0 z-50 p-4 bg-white dark:bg-slate-950 border rounded-2xl shadow-xl w-72">
{/* Header */}
<div className="flex items-center justify-between mb-3">
<button onClick={prevMonth} className="p-1 hover:bg-slate-100 rounded-lg">‹</button>
<span className="font-semibold text-sm">
{viewYear} Month {viewMonth}
</span>
<button onClick={nextMonth} className="p-1 hover:bg-slate-100 rounded-lg">›</button>
</div>
{/* 6x7 42-Cell Grid */}
<div className="grid grid-cols-7 gap-1 text-center text-xs">
{['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map((d) => (
<div key={d} className="font-semibold text-slate-400 py-1">{d}</div>
))}
{calendarMatrix.map((cell, idx) => (
<button
key={idx}
disabled={!cell.isCurrentMonth}
onClick={() => selectDate(cell.date)}
className={`h-8 w-8 rounded-lg flex items-center justify-center transition-all ${
!cell.isCurrentMonth
? 'text-slate-300 opacity-40'
: cell.isSelected
? 'bg-indigo-600 text-white font-bold'
: cell.isToday
? 'border border-indigo-500 text-indigo-600'
: 'hover:bg-slate-100 text-slate-700 dark:text-slate-200'
}`}
>
{cell.day}
</button>
))}
</div>
</div>
)}
</div>
);
}
⚡ Framework support matrix
| Framework | Package | Features |
|---|---|---|
| Vanilla / Node.js | @bsday.js/core |
Zero dependencies, ~12KB gzipped, 100% TypeScript |
| React / Next.js | @bsday.js/react |
useBSDatePicker, useBSRangePicker, useBSCalendarGrid
|
| Vue 3 / Nuxt | @bsday.js/vue |
Composition API composables with v-model binding |
| Angular | @bsday.js/angular |
Signals-based services & Reactive Form Directives |
| Svelte | @bsday.js/svelte |
Svelte 4/5 reactive stores & runes calendar primitives |
📊 Performance & bundle size
| Feature / Metric | @bsday.js/core |
Legacy Libraries |
|---|---|---|
| Bundle Size (Gzipped) | ~12 KB | 45 KB – 120 KB |
| Runtime Dependencies | 0 (Zero) | 2–6 dependencies |
| Day.js API Parity | ✅ 100% Parity | ❌ Proprietary APIs |
| Devanagari Parsing | ✅ Native | ❌ Manual regex |
| Banking / Workday Engine | ✅ Built-in | ❌ Not available |
| Fiscal Year (आ.व.) Support | ✅ Built-in | ❌ Not available |
| Headless UI Primitives | ✅ React/Vue/Angular/Svelte | ❌ jQuery / Vanilla DOM only |
| TypeScript Support | ✅ 100% Strict | ⚠️ Partial or .d.ts missing |
🛠️ Backend & schema validation (zod example)
Easily validate Bikram Sambat date inputs in your backend APIs or frontend forms:
import { z } from 'zod';
import { isValidBSDate } from '@bsday.js/core';
export const UserRegistrationSchema = z.object({
fullName: z.string().min(2),
dateOfBirthBS: z.string().refine(
(val) => isValidBSDate(val),
{ message: 'Invalid Bikram Sambat date format (expected YYYY/MM/DD)' }
),
});
🤝 Try it out & get involved!
bsday.js is 100% open-source under the MIT License.
- 🌐 Live Website & Playground: https://bsdayjs.vercel.app
- 📖 Documentation: https://bsdayjs.vercel.app/docs
- 📅 Calendar Explorer: https://bsdayjs.vercel.app/calendar
- ⭐ GitHub Repository: https://github.com/shurajcodx/bsday.js
If you find this project useful for your apps in Nepal, please consider starring the repository on GitHub ⭐ and sharing it with your fellow developers!
Let me know in the comments below: what features or framework recipes would you like to see next? 💬🚀
Top comments (0)