npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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.

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.

npm version types bundle size license tests


📑 Table of Contents


✨ 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, or NepaliDate
  • 🇳🇵 Devanagari I/O — both input parsing AND output rendering
  • 🧱 Immutable NepaliDate class — safe to share, no defensive copies
  • 🪶 100+ date-fns-style helpersaddDays, 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-max

Works 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, and formatFiscalYear all accept a one-off { locale: "ne" } (or a Locale object) 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: formatDistance is a pure duration — it's just the gap between two moments and never adds "ago"/"in". formatDistanceToNow always 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 Date behavior). For BS-format strings (e.g. "2081-01-15"), pre-parse with NepaliDate.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+F will 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 \| stringNepaliDate |

| 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 2083

Birthday → age in years

import { NepaliDate, differenceInYears } from "nepali-date-pro-max";
const dob = NepaliDate.fromAd(1990, 6, 15);
differenceInYears(NepaliDate.now(), dob);   // e.g. 35

Fiscal-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.


📜 License

MIT © l3lackcurtains


Made with ❤️ for the Nepali developer community

नेपाली डेभलपर समुदायका लागि माया साथ बनाइएको

धन्यवाद! 🙏