nepali-date-pro-max
v2.0.1
Published
नेपाली Bikram Sambat ↔ Gregorian date library for the Nepali developer community. 1975–2099 BS range, full date+time, Devanagari, calendar grid, fiscal year, AD↔BS range conversion, 100+ date-fns-style helpers. TypeScript-first, zero deps, ESM+CJS.
Maintainers
Readme
🇳🇵 nepali-date-pro-max
नेपाली डेट प्रो म्याक्स
The all-in-one Bikram Sambat library for the Nepali developer community. BS ↔ AD conversion · full date+time · Devanagari I/O · calendar grids · fiscal year · 100+ date-fns-style helpers — in one tight TypeScript package with zero dependencies.
📑 Table of Contents
- ✨ Highlights
- 📦 Install
- ⚡ Quick Start
- 📊 Comparison
- 🧠 Mental Model
- 🌐 Locale (Devanagari / Roman)
- 📅 Calendar Grid — the hero use case
- 🔁 AD ↔ BS Range Conversion
- ⏱️ Distance & Relative Time
- 🏛️ Fiscal Year
- 🧰 Full API Reference
- 🎯 Recipes
- 📐 Range & Accuracy
- 🤝 Contributing
- 📜 License
✨ Highlights
नमस्ते 👋 — whether you're building the next Hamro Patro, a payroll app, a सरकारी fiscal-year report, or just showing "आज को मिति" on your homepage — this library has you covered.
- 🎯 125-year range — BS 1975 → 2099 (≈ AD 1918 → 2043), the widest verified table on npm
- 📅 Calendar grid builder — drop-in data shape for any UI framework
- 🔁 AD ↔ BS range conversion — convert bounds or every day between
- 🏛️ Fiscal year helpers (आर्थिक वर्ष, Shrawan-Ashad)
- ⏱️ Time-ago in English & Nepali — pass
Date, timestamp, ISO string, orNepaliDate - 🇳🇵 Devanagari I/O — both input parsing AND output rendering
- 🧱 Immutable
NepaliDateclass — safe to share, no defensive copies - 🪶 100+ date-fns-style helpers —
addDays,isWeekend,eachDayOfInterval,formatDistance, … - 🔒 TypeScript-first with full type definitions and JSDoc
- 📦 Zero dependencies · dual ESM + CJS · MIT licensed
- ✅ 120 unit tests verifying round-trips across the full year range
📦 Install
npm install nepali-date-pro-max
pnpm add nepali-date-pro-max
yarn add nepali-date-pro-max
bun add nepali-date-pro-maxWorks in Node.js 14+, Bun, Deno, and modern browsers. Ships dual ESM + CJS — any module system works.
⚡ Quick Start
import {
bsToAd, adToBs, NepaliDate,
formatDistanceToNow,
getCalendarMonth, getFiscalYear, formatFiscalYear,
} from "nepali-date-pro-max";
// 1. Convert
bsToAd(2081, 1, 1); // → { year: 2024, month: 4, day: 13 }
adToBs(2024, 4, 13); // → { year: 2081, month: 1, day: 1 }
// 2. The class — Day.js style, chainable, locale-aware
const d = NepaliDate.fromBs(2081, 1, 1);
d.format("DD MMMM, YYYY (dddd)"); // "01 Baishakh, 2081 (Saturday)"
d.locale("ne").format("DD MMMM YYYY"); // "०१ बैशाख २०८१"
// 3. Time-ago — locale-driven (set once globally, or pass per call)
NepaliDate.locale("ne");
formatDistanceToNow(post.createdAt); // "५ मिनेट अघि"
formatDistanceToNow(Date.now() - 5 * 60_000, { locale: "en" }); // "5 minutes ago"
// 4. UI-ready calendar grid — picks up the global locale automatically
const cal = getCalendarMonth(2081, 1);
// → { weeks: [...], weekdayHeaders: ["आइतबार", ...], monthName: "बैशाख", ... }
// 5. Fiscal year
formatFiscalYear(getFiscalYear(NepaliDate.now())); // "२०८३/८४" (under "ne")📊 Comparison
| Feature | nepali-date-pro-max | nepali-date-converter | bikram-sambat | nepali-datetime | @sbmdkl/nepali-date-converter |
|---|:---:|:---:|:---:|:---:|:---:|
| Weekly downloads | new | ~9.6k | ~6.9k | ~700 | ~750 |
| BS year range | 1975–2099 | 1975–2099 | 1970–2090 | 2000–2099 | 1978–2099 |
| Time-of-day | ✅ | ❌ | ❌ | ✅ | ❌ |
| Immutable API | ✅ | ❌ | ✅ | ❌ | n/a |
| Calendar grid builder | ✅ | ❌ | ❌ | ❌ | ❌ |
| AD↔BS range conversion | ✅ | ❌ | ❌ | ❌ | ❌ |
| Fiscal year (Shrawan-Ashad) | ✅ | ❌ | ❌ | ❌ | ❌ |
| date-fns-style utilities | ✅ 100+ | ❌ | ❌ | ❌ | partial |
| Time-ago accepts timestamp/Date/string | ✅ | ❌ | ❌ | ❌ | ❌ |
| TypeScript-first | ✅ | ✅ | ❌ | ✅ | ✅ |
| Dual ESM + CJS | ✅ | UMD only | CJS only | ✅ | ✅ |
| Devanagari output | ✅ | ✅ | ✅ | ✅ | ❌ |
| Devanagari input parsing | ✅ | ❌ | ❌ | ❌ | ❌ |
| formatDistance (en + नेपाली) | ✅ | ❌ | ❌ | ❌ | ❌ |
| License | MIT | MIT | Apache-2.0 | GPL-3.0 | MIT |
| Zero dependencies | ✅ | ✅ | ❌ | ✅ | ✅ |
🧠 Mental Model
A small list of rules that explain everything else:
| Rule | Detail |
|---|---|
| 1-indexed months | 1 = Baishakh / January, 12 = Chaitra / December. Never JavaScript's 0-indexed style. |
| Calendar values, not instants | BS dates have no inherent timezone. The NepaliDate class additionally carries an optional time-of-day in Asia/Kathmandu (UTC+05:45) wall-clock. |
| Immutable | NepaliDate instances never change. Every "mutating" method (addDays, setMonth, …) returns a NEW instance. |
| Range | BS 1975 → 2099 inclusive. Out-of-range inputs throw RangeError. |
| Date inputs use UTC fields | new Date("2024-04-13") always means April 13. For local-time semantics, pass a { year, month, day } object. |
| Nepal-aware defaults | Week starts Sunday (weekStartsOn: 0). Weekend = Saturday only ([6]). |
🌐 Locale (Devanagari / Roman)
Two locales ship built-in:
| Locale | Script | Digits | Example |
|---|---|---|---|
| "en" (default) | Roman | ASCII | "15 Baishakh 2081 (Saturday)" |
| "ne" | Devanagari | Devanagari | "१५ बैशाख २०८१ (शनिबार)" |
Set it once at app boot; everything else inherits — Day.js style:
import { NepaliDate, getCalendarMonth } from "nepali-date-pro-max";
NepaliDate.locale("ne"); // global default
NepaliDate.now().format("DD MMMM YYYY (dddd)"); // "१५ बैशाख २०८१ (शनिबार)"
getCalendarMonth(2081, 1).weekdayHeaders[0]; // "आइतबार"Override per-instance — chainable, returns a NEW immutable date:
const d = NepaliDate.fromBs(2081, 1, 15);
d.locale("ne").format("DD MMMM YYYY"); // "१५ बैशाख २०८१"
d.locale("en").format("DD MMMM YYYY"); // "15 Baishakh 2081"
// Locale flows through chained ops
d.locale("ne").addDays(7).format("dddd"); // "शनिबार"Override per-call when you don't need to switch globally:
formatBs({ year: 2081, month: 1, day: 1 }, "DD MMMM YYYY", { locale: "ne" });
getCalendarMonth(2081, 1, { locale: "ne" });For bilingual UIs that need both forms in the same view, the calendar grid (getCalendarMonth) populates each cell with both weekdayName/monthName (locale-driven) and locale-independent weekdayNameNepali / monthNameNepali / bsDayNepali fields — see the calendar section below.
Custom locales (e.g. romanised Nepali)
import { registerLocale } from "nepali-date-pro-max";
registerLocale({
name: "ne-rom",
months: ["Baishak", "Jeth", "Asar", "Saun", "Bhadau", "Asoj",
"Kartik", "Mangsir", "Push", "Magh", "Falgun", "Chait"],
monthsShort: ["Bai", "Jet", "Asa", "Sau", "Bha", "Aso",
"Kar", "Man", "Pus", "Mag", "Fal", "Cha"],
weekdays: ["Aaitabar", "Sombar", "Mangalbar", "Budhabar",
"Bihibar", "Sukrabar", "Sanibar"],
weekdaysShort: ["Aai", "Som", "Man", "Bud", "Bih", "Suk", "San"],
weekdaysMin: ["Aa", "So", "Ma", "Bu", "Bi", "Su", "Sa"],
digits: (n) => String(n),
});
NepaliDate.now().locale("ne-rom").format("DD MMMM YYYY (dddd)");
// → "15 Baishak 2081 (Sanibar)"Locale API
| Function | Purpose |
|---|---|
| NepaliDate.locale() | Get the current global locale name |
| NepaliDate.locale(name) | Set the global locale (returns the new name) |
| d.locale() | Resolved locale on this instance (instance → global → "en") |
| d.locale(name) | NEW instance with the given locale |
| registerLocale(locale) | Add a custom locale to the registry |
| getLocale(name) / hasLocale(name) / listLocales() | Inspect the registry |
| getGlobalLocale() / setGlobalLocale(name) | Functional equivalents of NepaliDate.locale() |
| getMonthNames(locale?, length?) | 12 BS month names — "long" (default) or "short" (2.0.1+) |
| getWeekdayNames(locale?, length?) | 7 weekday names — "long" / "short" / "min" (2.0.1+) |
| localizeDigits(value, locale?) | Render a number/string in the locale's numeral system (2.0.1+) |
import { getMonthNames, getWeekdayNames, localizeDigits } from "nepali-date-pro-max";
getMonthNames("ne"); // ["बैशाख", "जेठ", "असार", …]
getWeekdayNames("en", "min"); // ["Su", "Mo", "Tu", …]
localizeDigits(2081, "ne"); // "२०८१"
format(), the calendar functions, the distance/relative formatters, andformatFiscalYearall accept a one-off{ locale: "ne" }(or aLocaleobject) which always wins over the instance/global default.
📅 Calendar Grid — Build a Nepali Calendar
getCalendarMonth() returns a fully-prepared 7-column grid where every cell already knows its BS day, AD day, weekday, "is today", "is Saturday/weekend", and "is in current month". Drop it straight into your template — no further computation needed.
React example — Hamro Patro–style month view
import { getCalendarMonth } from "nepali-date-pro-max";
export function NepaliCalendar({ year, month }: { year: number; month: number }) {
const cal = getCalendarMonth(year, month, { locale: "ne" });
return (
<div className="nepali-calendar">
<h2>{cal.monthNameNepali} {cal.yearNepali}</h2>
<div className="grid grid-cols-7 text-center">
{cal.weekdayHeadersShort.map(h => (
<div key={h} className="font-bold text-sm py-2">{h}</div>
))}
{cal.weeks.flatMap(w => w.days).map(c => (
<div
key={`${c.bs.year}-${c.bs.month}-${c.bs.day}`}
className={[
"p-2 border",
!c.isCurrentMonth && "text-gray-300",
c.isToday && "bg-red-500 text-white rounded-full",
c.isSaturday && c.isCurrentMonth && "text-red-600",
].filter(Boolean).join(" ")}
>
<div className="text-lg">{c.bsDayNepali}</div>
<div className="text-xs opacity-60">{c.adDay}</div>
</div>
))}
</div>
</div>
);
}Cell shape
{
bs: { year: 2081, month: 1, day: 1 },
ad: { year: 2024, month: 4, day: 13 },
weekday: 6, // 0=Sun..6=Sat
weekdayName: "Saturday",
weekdayNameNepali: "शनिबार",
bsDay: 1,
bsDayNepali: "१", // always Devanagari
bsDayLocalized: "1", // active locale's digits (2.0.1+)
adDay: 13,
adMonthName: "April", // English Gregorian (2.0.1+)
adMonthNameShort: "Apr", // English Gregorian (2.0.1+)
isCurrentMonth: true, // false = adjacent-month padding
isToday: false,
isSaturday: true, isSunday: false, isWeekend: true,
date: NepaliDate { … } // for click-handlers etc.
}CalendarMonth itself also exposes yearLocalized (active-locale digits) alongside the existing yearNepali (always Devanagari) and year (number).
Options
getCalendarMonth(year, month, {
weekStartsOn: 0, // 0=Sunday (default — Nepal standard), 1=Monday, …
padding: true, // include leading/trailing adjacent-month cells
today: NepaliDate.now(), // override "today" (for tests)
weekendDays: [6], // [6]=Sat only (default), [0,6]=Sun+Sat
locale: "ne", // override locale for this call (defaults to NepaliDate.locale())
});Other calendar helpers
import { getCalendarYear, getCalendarDay, flattenCalendarMonth } from "nepali-date-pro-max";
getCalendarYear(2081); // → 12 CalendarMonth objects (Baishakh..Chaitra)
getCalendarDay(NepaliDate.now()); // → single CalendarDayCell
flattenCalendarMonth(cal); // → flat CalendarDayCell[] (no week grouping)🔁 AD ↔ BS Range Conversion
Forms, reports, analytics — anywhere you have a date range in one calendar and need it in the other.
import {
convertAdRangeToBs, convertBsRangeToAd,
eachBsDayInAdRange, eachAdDayInBsRange, eachBsMonthInAdRange,
} from "nepali-date-pro-max";
// Just the bounds — fast, returns one pair
convertAdRangeToBs(
{ year: 2024, month: 1, day: 1 },
{ year: 2024, month: 12, day: 31 },
{ format: "DD MMMM YYYY" },
);
// → { start: "16 Poush 2080", end: "16 Poush 2081" }
// Devanagari, every day enumerated
eachBsDayInAdRange(
new Date("2024-04-13"),
new Date("2024-04-15"),
{ format: "YYYY-MM-DD", locale: "ne" },
);
// → ["२०८१-०१-०१", "२०८१-०१-०२", "२०८१-०१-०३"]
// Inverse: BS → AD
convertBsRangeToAd(
{ year: 2081, month: 1, day: 1 },
{ year: 2082, month: 1, day: 1 },
{ format: "MMM D, YYYY" },
);
// → { start: "Apr 13, 2024", end: "Apr 14, 2025" }Type-safe overloads: when format is omitted, you get raw BsDate[] / AdDate[]; when provided, string[].
⏱️ Distance & Relative Time
Three locale-driven functions. Pick by intent (formatDistance is a pure gap; formatDistanceToNow always carries an "ago"/"in" suffix; formatRelative is the smart phrasing). Every input accepts NepaliDate | Date | number | string. Locale defaults to NepaliDate.locale(); pass { locale: "ne" } to override per call.
| Function | Suffix | en example | ne example |
|---|---|---|---|
| formatDistance(a, b) | no | "5 days" | "५ दिन" |
| formatDistanceToNow(x) | yes | "5 minutes ago" / "in 3 days" | "५ मिनेट अघि" / "३ दिन पछि" |
| formatRelative(x, base?) | smart | "yesterday" / "in 3 days" | "हिजो" / "३ दिनमा" |
Suffix rule:
formatDistanceis a pure duration — it's just the gap between two moments and never adds "ago"/"in".formatDistanceToNowalways adds the suffix because the comparison is implicitly to now.
import {
formatDistance, formatDistanceToNow, formatRelative, NepaliDate,
} from "nepali-date-pro-max";
// Time-ago vs. now — pass a timestamp, Date, ISO string, or NepaliDate
formatDistanceToNow(post.createdAt); // "5 minutes ago"
formatDistanceToNow(new Date("2024-04-13")); // "2 years ago"
formatDistanceToNow(Date.now() + 86_400_000); // "in 1 day"
// Devanagari output — set globally once, or per call
NepaliDate.locale("ne");
formatDistanceToNow(Date.now() - 5 * 60_000); // "५ मिनेट अघि"
formatDistanceToNow(Date.now() + 86_400_000, { locale: "en" }); // override → "in 1 day"
// Pure duration between two arbitrary moments — never has a suffix
formatDistance("2024-04-13", "2024-04-20"); // "7 days"
formatDistance("2024-04-13", "2024-04-20", { locale: "ne" }); // "७ दिन"
// Smart relative phrasing
formatRelative(Date.now() - 86_400_000); // "yesterday"
formatRelative(Date.now() + 3 * 86_400_000); // "in 3 days"
formatRelative(Date.now() - 86_400_000, undefined, { locale: "ne" }); // "हिजो"
formatRelative(Date.now() + 3 * 86_400_000, undefined, { locale: "ne" }); // "३ दिनमा"Strings are interpreted as Gregorian ISO (matching
Datebehavior). For BS-format strings (e.g."2081-01-15"), pre-parse withNepaliDate.parse()and pass the instance.
🏛️ Fiscal Year (आर्थिक वर्ष)
Nepal's fiscal year runs Shrawan 1 → Ashad-end of the next year. FY 2081/82 starts on Shrawan 1, 2081 (≈ mid-July 2024 AD).
import {
getFiscalYear, startOfFiscalYear, endOfFiscalYear,
formatFiscalYear, getFiscalQuarter,
} from "nepali-date-pro-max";
getFiscalYear(NepaliDate.fromBs(2081, 5, 1)); // 2081
getFiscalYear(NepaliDate.fromBs(2081, 3, 30)); // 2080 (still in FY 2080/81)
startOfFiscalYear(2081); // Shrawan 1, 2081
endOfFiscalYear(2081); // Ashad-end, 2082
formatFiscalYear(2081); // "2081/82"
formatFiscalYear(2081, { locale: "ne" }); // "२०८१/८२"
getFiscalQuarter(NepaliDate.fromBs(2081, 7, 1)); // 2 (Kartik-Poush)🧰 Full API Reference
Every public symbol is listed below in tables —
Ctrl+Fwill hit any name. Detailed JSDoc is included in the TypeScript definitions.
| Symbol | Description |
|---|---|
| bsToAd(year, month, day) | BS → AD calendar |
| adToBs(year, month, day) | AD → BS calendar |
| fromJsDate(date) | JS Date → BS (shifted to NPT, UTC+05:45) |
| bsWeekday(year, month, day) | weekday: 0=Sun..6=Sat |
| bsDayOfYear(year, month, day) | day-of-year: 1..(365 \| 366) |
| bsFromDayOfYear(year, dayOfYear) | inverse of bsDayOfYear |
| toNepaliDate(input) | coerce NepaliDate \| Date \| number \| string → NepaliDate |
| Symbol | Description |
|---|---|
| FIRST_BS_YEAR | 1975 |
| LAST_BS_YEAR | 2099 |
| BS_YEAR_DATA | raw [m1..m12, total] table per year |
| ANCHOR_AD_YEAR | 1918 (AD anchor for BS 1975-01-01) |
| ANCHOR_AD_MONTH | 4 (April) |
| ANCHOR_AD_DAY | 13 |
| daysInBsMonth(year, month) | days in a BS month (29..32) |
| daysInBsYear(year) | 365 or 366 |
| isBsLeapYear(year) | true if year has 366 days |
| Symbol | Value / Description |
|---|---|
| BS_MONTH_NAMES | ["Baishakh", "Jestha", … , "Chaitra"] |
| BS_MONTH_NAMES_SHORT | ["Bai", "Jes", … , "Cha"] |
| BS_MONTH_NAMES_NP | ["बैशाख", "जेठ", … , "चैत"] |
| AD_MONTH_NAMES | ["January", … , "December"] |
| AD_MONTH_NAMES_SHORT | ["Jan", … , "Dec"] |
| WEEKDAY_NAMES | ["Sunday", … , "Saturday"] |
| WEEKDAY_NAMES_SHORT | ["Sun", … , "Sat"] |
| WEEKDAY_NAMES_MIN | ["Su", … , "Sa"] |
| WEEKDAY_NAMES_NP | ["आइतबार", … , "शनिबार"] |
| WEEKDAY_NAMES_NP_SHORT | ["आइत", … , "शनि"] |
| DEVANAGARI_DIGITS | ["०", "१", … , "९"] |
| toDevanagariDigits(input) | ASCII → Devanagari (2081 → "२०८१") |
| toAsciiDigits(input) | Devanagari → ASCII ("२०८१" → "2081") |
| Function | Description |
|---|---|
| parseBs(string) | Parse YYYY-MM-DD (also /, .; ASCII or Devanagari digits) → BsDate |
| formatBs(date, pattern) | Format with token pattern in the global locale |
| formatBs(date, pattern, { locale: "ne" }) | Format in a specific locale (Devanagari for "ne") |
Format tokens (case-sensitive):
| Token | Output | Token | Output |
|---|---|---|---|
| YYYY / YY | year | dddd / ddd / dd | weekday |
| MMMM / MMM / MM / M | month | HH / H | 24-hour |
| DD / D | day-of-month | hh / h | 12-hour |
| mm / m | minute | ss / s | second |
| A / a | AM/PM | […] | literal escape |
Static factories
| Method | Description |
|---|---|
| NepaliDate.now() | Current Nepal moment (UTC+05:45) |
| NepaliDate.fromBs(y, m, d, h?, min?, s?, ms?) | From BS year/month/day (+optional time) |
| NepaliDate.fromAd(y, m, d, h?, min?, s?, ms?) | From AD year/month/day (+optional time) |
| NepaliDate.fromJsDate(date) | From a JS Date (instant → BS calendar fields) |
| NepaliDate.parse(string) | Parse a BS string |
Accessors
| Method | Returns |
|---|---|
| .getYear() | BS year |
| .getMonth() | BS month, 1-indexed (1=Baishakh) |
| .getDate() | BS day-of-month |
| .getDay() | weekday, 0=Sun..6=Sat |
| .getDayOfYear() | 1..(365 \| 366) |
| .getHours() / .getMinutes() / .getSeconds() / .getMilliseconds() | time-of-day fields |
| .getMonthName() | month name in active locale ("Baishakh" / "बैशाख") |
| .getDayName() | weekday name in active locale ("Saturday" / "शनिबार") |
| .daysInMonth() | days in this BS month |
| .daysInYear() | 365 or 366 |
| .locale() / .locale(name) | get/set locale (chainable) — see Locale |
Predicates
| Method | Returns |
|---|---|
| .isWeekend(weekendDays?) | true if in weekend set (default [6] = Saturday) |
| .isLeapYear() | year has 366 days |
| .isFirstDayOfMonth() | day-of-month is 1 |
| .isLastDayOfMonth() | day-of-month is the month's last |
| .isBefore(other) / .isAfter(other) | ordering |
| .isSameDay(other) | same calendar day (ignores time) |
Conversion
| Method | Returns |
|---|---|
| .toBs() | { year, month, day } |
| .toAd() | { year, month, day } (Gregorian) |
| .toJsDate() | native JS Date |
| .toString() | "YYYY-MM-DD" |
| .toJSON() | { bs, ad, iso } |
| .getDetails() | full breakdown — useful for UI/AI |
Formatting
| Method | Returns |
|---|---|
| .format(pattern, options?) | token-based string in the active locale |
| .format(pattern, { locale: "ne" }) | one-off Devanagari output |
Arithmetic (every method returns a NEW instance)
| Method | Returns |
|---|---|
| .addDays(n) / .addMonths(n) / .addYears(n) | shifted instance (addMonths clamps day) |
| .addHours(n) / .addMinutes(n) / .addSeconds(n) / .addMilliseconds(n) | time-shifted instance |
| .startOfDay() / .endOfDay() | day boundaries |
| .startOfMonth() / .endOfMonth() | month boundaries |
| .startOfYear() / .endOfYear() | year boundaries |
Diff
| Method | Returns |
|---|---|
| .diffDays(other) | signed integer days (this − other) |
| Add | Subtract | Description |
|---|---|---|
| addDays(d, n) | subDays(d, n) | shift by days |
| addMonths(d, n) | subMonths(d, n) | shift by BS months (clamps day) |
| addYears(d, n) | subYears(d, n) | shift by BS years |
| addHours(d, n) | subHours(d, n) | shift by hours |
| addMinutes(d, n) | subMinutes(d, n) | shift by minutes |
| addSeconds(d, n) | subSeconds(d, n) | shift by seconds |
| addMilliseconds(d, n) | subMilliseconds(d, n) | shift by milliseconds |
| Function | Description |
|---|---|
| setYear(d, year) | replace BS year (clamps day-of-month) |
| setMonth(d, month) | replace BS month (clamps day-of-month) |
| setDate(d, day) | replace day-of-month |
| setDay(d, weekday, options?) | move to a weekday within current week |
| setDayOfYear(d, doy) | jump to a day-of-year |
| setHours(d, h) | replace hour (0..23) |
| setMinutes(d, m) | replace minute (0..59) |
| setSeconds(d, s) | replace second (0..59) |
| setMilliseconds(d, ms) | replace millisecond (0..999) |
| Function | Returns true when… |
|---|---|
| isBefore(a, b) | a precedes b |
| isAfter(a, b) | a follows b |
| isEqual(a, b) | exactly the same instant |
| isSameDay(a, b) | same BS calendar day |
| isSameMonth(a, b) | same BS year + month |
| isSameYear(a, b) | same BS year |
| isSameWeek(a, b, options?) | same week (weekStartsOn default Sunday) |
| isToday(d) | today (Nepal time) |
| isYesterday(d) | yesterday |
| isTomorrow(d) | tomorrow |
| isThisMonth(d) | current BS month |
| isThisYear(d) | current BS year |
| isThisWeek(d, options?) | current week |
| isSunday(d) | weekday is Sunday |
| isMonday(d) | weekday is Monday |
| isTuesday(d) | weekday is Tuesday |
| isWednesday(d) | weekday is Wednesday |
| isThursday(d) | weekday is Thursday |
| isFriday(d) | weekday is Friday |
| isSaturday(d) | weekday is Saturday (Nepal's weekly holiday) |
| isWeekend(d, options?) | in weekend set (default [6], Saturday only) |
| isFirstDayOfMonth(d) | day-of-month is 1 |
| isLastDayOfMonth(d) | day-of-month is month's last |
| isLeapYear(d) | year has 366 days |
| isWithinInterval(d, interval) | within [start, end] inclusive |
| areIntervalsOverlapping(a, b) | intervals share at least one day |
| isValid(value) | value is a NepaliDate instance |
| Start | End | Description |
|---|---|---|
| startOfDay(d) | endOfDay(d) | 00:00:00.000 / 23:59:59.999 |
| startOfWeek(d, options?) | endOfWeek(d, options?) | week boundaries (default Sunday-start) |
| startOfMonth(d) | endOfMonth(d) | first / last day of BS month |
| startOfYear(d) | endOfYear(d) | Baishakh 1 / Chaitra-end |
| Function | Returns |
|---|---|
| differenceInMilliseconds(a, b) | signed ms |
| differenceInSeconds(a, b) | signed whole seconds |
| differenceInMinutes(a, b) | signed whole minutes |
| differenceInHours(a, b) | signed whole hours |
| differenceInDays(a, b) | signed whole days |
| differenceInWeeks(a, b) | signed whole weeks |
| differenceInMonths(a, b) | calendar-aware whole months (matches date-fns) |
| differenceInYears(a, b) | calendar-aware whole years |
| differenceInCalendarDays(a, b) | day-boundary count (ignores time) |
| differenceInCalendarMonths(a, b) | month-boundary count |
| differenceInCalendarYears(a, b) | year-boundary count |
| Function | Returns |
|---|---|
| eachDayOfInterval(interval) | every day in [start, end] inclusive |
| eachWeekOfInterval(interval, options?) | every week-start in interval |
| eachMonthOfInterval(interval) | first day of each BS month |
| eachYearOfInterval(interval) | Baishakh 1 of each BS year |
| eachWeekendOfInterval(interval, weekday = 6) | every Nth weekday (default Saturday) |
| Function | Suffix | en | ne |
|---|---|---|---|
| formatDistance(a, b, options?) | ❌ | "5 days" | "५ दिन" |
| formatDistanceToNow(input, options?) | ✅ | "5 minutes ago" | "५ मिनेट अघि" |
| formatRelative(input, base?, options?) | smart | "yesterday" / "in 3 days" | "हिजो" / "३ दिनमा" |
options.locale defaults to NepaliDate.locale(). All inputs accept NepaliDate \| Date \| number \| string.
Related types: DateInput · DistanceOptions
| Function | Description |
|---|---|
| NepaliDate.locale() / NepaliDate.locale(name) | Get/set the global default locale |
| d.locale() / d.locale(name) | Get this instance's resolved locale, or return a new instance with name |
| registerLocale(locale) | Add a custom locale to the registry |
| getLocale(name) / hasLocale(name) / listLocales() | Inspect the registry |
| getGlobalLocale() / setGlobalLocale(name) | Functional equivalents of NepaliDate.locale() |
Built-in locales: "en" (Roman, ASCII digits) and "ne" (Devanagari).
Related types: Locale · LocaleRelativeTime
| Function | Returns |
|---|---|
| min(dates) | earliest of array, or undefined if empty |
| max(dates) | latest of array, or undefined if empty |
| clamp(d, { start, end }) | start if before, end if after, else d |
| closestTo(target, candidates) | candidate nearest to target by day-distance |
| closestIndexTo(target, candidates) | index of nearest candidate |
| Function | Description |
|---|---|
| convertAdRangeToBs(start, end, options?) | bounds-only AD → BS |
| convertBsRangeToAd(start, end, options?) | bounds-only BS → AD |
| eachBsDayInAdRange(start, end, options?) | every BS day across an AD range |
| eachBsMonthInAdRange(start, end, options?) | every BS month-start touched by AD range |
| eachAdDayInBsRange(start, end, options?) | every AD day across a BS range |
When options.format is provided → returns string[]. When omitted → returns raw BsDate[] / AdDate[].
Related types: AdInput · RangeConvertOptions · AdRangeFormatOptions
| Function | Returns |
|---|---|
| getCalendarMonth(year, month, options?) | CalendarMonth — weeks × 7 cells with all flags pre-computed |
| getCalendarYear(year, options?) | CalendarMonth[] — 12 entries (Baishakh..Chaitra) |
| getCalendarDay(date, options?) | CalendarDayCell — single-day view |
| flattenCalendarMonth(month) | CalendarDayCell[] — drop the week grouping |
Related types: CalendarMonth · CalendarWeek · CalendarDayCell · CalendarMonthOptions
| Symbol | Description |
|---|---|
| getFiscalYear(date) | the FY a date belongs to (Shrawan-start) |
| startOfFiscalYear(fy) | Shrawan 1 of FY |
| endOfFiscalYear(fy) | Ashad-end of next BS year |
| formatFiscalYear(fy, options?) | "2081/82" or "२०८१/८२" |
| getFiscalQuarter(date) | 1..4 within the fiscal year |
| FISCAL_YEAR_START_MONTH | 4 (Shrawan) |
| Type | Shape |
|---|---|
| BsDate | { year, month, day } (BS) |
| AdDate | { year, month, day } (Gregorian) |
| BsDateTime | BsDate + optional hour, minute, second, millisecond |
| NepaliDateDetails | full breakdown returned by getDetails() |
| NepaliInterval | { start: NepaliDate, end: NepaliDate } |
| FormatOptions | { nepali?: boolean } |
| DateInput | NepaliDate \| Date \| number \| string |
| AdInput | AdDate \| Date |
| RangeConvertOptions | { format?: string, nepali?: boolean } |
| AdRangeFormatOptions | { format?: string } |
| CalendarMonth | full month grid (see Calendar Grid section) |
| CalendarWeek | { weekNumber, days: CalendarDayCell[] } |
| CalendarDayCell | one cell with bs, ad, weekday, flags, etc. |
| CalendarMonthOptions | { weekStartsOn?, padding?, today?, weekendDays?, locale? } |
🎯 Recipes
"आज को मिति" header
import { NepaliDate } from "nepali-date-pro-max";
export function TodayHeader() {
const d = NepaliDate.now();
return (
<div>
<div>{d.locale("ne").format("dddd, DD MMMM YYYY")}</div>
<div className="text-xs">{d.locale("en").format("dddd, DD MMMM YYYY")}</div>
</div>
);
}
// → शनिबार, १७ बैशाख २०८३
// Saturday, 17 Baishakh 2083Birthday → age in years
import { NepaliDate, differenceInYears } from "nepali-date-pro-max";
const dob = NepaliDate.fromAd(1990, 6, 15);
differenceInYears(NepaliDate.now(), dob); // e.g. 35Fiscal-year report header
import { NepaliDate, getFiscalYear, formatFiscalYear } from "nepali-date-pro-max";
const fy = getFiscalYear(NepaliDate.now());
const label = formatFiscalYear(fy, { locale: "ne" });
// → "आर्थिक वर्ष २०८३/८४"Form: AD date-range → BS strings for the API
import { convertAdRangeToBs } from "nepali-date-pro-max";
function onSubmit({ startAd, endAd }: { startAd: Date; endAd: Date }) {
const bs = convertAdRangeToBs(startAd, endAd, { format: "YYYY-MM-DD" });
api.post("/reports", { startBs: bs.start, endBs: bs.end });
}All Saturdays this month (बिदा / weekly holidays)
import { NepaliDate, eachWeekendOfInterval } from "nepali-date-pro-max";
const m = NepaliDate.now();
const saturdays = eachWeekendOfInterval(
{ start: m.startOfMonth(), end: m.endOfMonth() },
6,
);"५ मिनेट अघि" — relative time from any timestamp
import { formatDistanceToNow } from "nepali-date-pro-max";
formatDistanceToNow(post.createdAt); // "5 minutes ago"
formatDistanceToNow(post.createdAt, { locale: "ne" }); // "५ मिनेट अघि"📐 Range & Accuracy
This package supports BS 1975 → 2099 — a span of 125 years, corresponding to roughly AD 1918-04-13 → 2043-04-13.
The Bikram Sambat calendar is not algorithmic. Month lengths are determined astronomically and ratified each year by the Nepali calendar committee (पंचाङ्ग निर्णायक समिति), so every BS↔AD library — ours included — relies on a hand-curated lookup table.
The table shipped here covers the full 125-year range and is verified by 120 unit tests including:
- Round-trip BS→AD→BS on every year boundary across the entire range
- Day-by-day monotonic verification on sample years
- Well-known reference dates (Nepal New Year, Republic Day, Constitution Day, etc.)
- Weekday correctness against native
Date.getUTCDay()
Spot a wrong date? Open an issue with the BS↔AD pair — calendar-data fixes ship as patch releases.
🤝 Contributing
Bugs, suggestions, calendar-data corrections, and new helpers are very welcome.
- 🐛 Open an issue
- 🔧 Send a PR
- 💬 If your team uses this in production, we'd love to hear about it!
📜 License
MIT © l3lackcurtains
Made with ❤️ for the Nepali developer community
नेपाली डेभलपर समुदायका लागि माया साथ बनाइएको
धन्यवाद! 🙏
