zgba Network

Meet bsday.js — The Ultra-Fast, Zero-Dependency Bikram Sambat (BS) Calendar Engine for JavaScript & TypeScript 🇳🇵

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 Date prototype 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 (

{/* 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’} {/ Calendar Dropdown /} {isOpen && (
{/ Header /}
{viewYear} Month {viewMonth}
{/
6x7 42-Cell Grid */}
{[‘Su’, ‘Mo’, ‘Tu’, ‘We’, ‘Th’, ‘Fr’, ‘Sa’].map((d) => (
{d}
))} {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} ))}
)}
); } ⚡ 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? 💬🚀

View original article