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

@namlo/nepali-calendar

v0.1.3

Published

Offline Bikram Sambat (Nepali) calendar for JS/TS: BS↔AD conversion, astronomically computed panchang (tithi, nakshatra, yoga, karana, sunrise/sunset), and curated festivals/holidays. Works in React, React Native and Node.

Readme

@namlo/nepali-calendar

Offline Bikram Sambat (BS) calendar for JavaScript & TypeScript — accurate date conversion, astronomically computed panchang, and curated festivals/holidays. Zero network calls, zero native dependencies, works everywhere JavaScript runs.

License: MIT Node Types


Why this exists

Most JavaScript Nepali-calendar libraries only do date conversion (BS ↔ AD) and stop there. The few that include panchang (tithi, nakshatra, yoga, karana) reuse static almanac tables where the tithi/paksha is frequently mislabeled, and festival lists are hardcoded once and never re-verified.

This package instead:

  • Computes panchang from real ephemeris (via astronomy-engine) using the Lahiri (Chitrapaksha) ayanamsa — the same math used by professional Nepali panchang publishers — instead of a lookup table.
  • Verifies festival placement programmatically. Curated festival data is built against the computed panchang with assertions (e.g. "Ekadashi must fall on tithi 11 or 26"), catching the kind of month-shift errors (adhik māsa / leap-month handling) that silently break hand-transcribed data.
  • Ships as one offline package for React, React Native, and Node — no API, no rate limits, no stale cache.

Features

| | | |---|---| | 🔁 | BS ↔ AD conversion, validated against per-day Gregorian anchors | | 🌙 | Computed panchang — tithi, paksha, nakshatra, yoga, karana | | ☀️ | Sunrise / sunset / moonrise / moonset, computed for any location | | 🎉 | Curated festivals & public holidays, keyed by BS year/month/day | | 📱 | Works in React, React Native (Expo), and Node — no network, no native modules | | 🌐 | Nepali (Devanagari) + English month/weekday names and numeral conversion | | 📦 | Dual ESM + CJS build with full TypeScript types, tree-shakeable |


Installation

npm install @namlo/nepali-calendar
yarn add @namlo/nepali-calendar
# or
pnpm add @namlo/nepali-calendar

Requires Node.js 18+ (or any modern bundler/RN runtime — the package has no Node-only dependencies at runtime).


Quick start

A step-by-step tour of the API, from simplest to most complete.

1. What's today's date in BS?

import { getToday, formatBs } from "@namlo/nepali-calendar";

const today = getToday();       // { year: 2083, month: 3, day: 26 }
formatBs(today, "np");          // "असार २६, २०८३"
formatBs(today, "en");          // "Ashadh 26, 2083"

2. Convert between BS and AD

import { adToBs, bsToAd } from "@namlo/nepali-calendar";

adToBs(new Date("2026-04-14"));            // { year: 2083, month: 1, day: 1 }
bsToAd({ year: 2083, month: 1, day: 1 });  // Date → 2026-04-14T00:00:00.000Z

3. Get a full month grid (for rendering a patro)

import { getBsMonth } from "@namlo/nepali-calendar";

const month = getBsMonth(2083, 1); // Baishakh 2083
month.totalDays;      // 31
month.startWeekday;   // 2  (0=Sun..6=Sat — Baishakh 1 falls on a Tuesday)
month.days[17].ad;    // "2026-05-01" (Baishakh 18)

4. Get one fully-resolved day — conversion + panchang + festivals

import { getBsDay } from "@namlo/nepali-calendar";

const day = getBsDay(2083, 1, 18);

day.ad;                       // "2026-05-01"
day.weekday;                  // 5 (Friday)
day.paksha;                   // "Shukla"
day.panchang.tithiName;       // "Purnima"
day.panchang.nakshatraName;   // "Swati"
day.sunrise;                  // Date (Kathmandu sunrise, ~05:10 local)
day.isHoliday;                // true
day.holidays;                 // ["बुद्ध जयन्ती", "मजदूर दिवस"]

That's the whole surface you need for a typical calendar screen. Everything below is the full reference for going deeper (custom locations, raw panchang for any instant, festival listings, number formatting).


Framework example: React patro grid

A minimal component using only this package — no other date library needed.

import { getBsMonth, BS_MONTHS_NP, WEEKDAYS_NP, toDevanagari } from "@namlo/nepali-calendar";

function PatroGrid({ year, month }: { year: number; month: number }) {
  const { days, startWeekday, totalDays } = getBsMonth(year, month);
  const leadingBlanks = Array.from({ length: startWeekday });

  return (
    <div>
      <h2>{BS_MONTHS_NP[month - 1]} {toDevanagari(year)}</h2>
      <div className="grid grid-cols-7">
        {WEEKDAYS_NP.map((w) => <div key={w}>{w}</div>)}
        {leadingBlanks.map((_, i) => <div key={`b${i}`} />)}
        {days.map((day) => (
          <div key={day.gatey} className={day.isHoliday ? "text-red-600" : ""}>
            <strong>{toDevanagari(day.gatey)}</strong>
            {day.holidays.map((h) => <div key={h}>{h}</div>)}
          </div>
        ))}
      </div>
      <p>{totalDays} days this month</p>
    </div>
  );
}

This is exactly the pattern used to render the screenshot above.


API reference

Types

All exported as named TypeScript types — import type { BsDate, BsDay, ... } from "@namlo/nepali-calendar".

| Type | Shape | |---|---| | BsDate | { year: number; month: number /* 1-12 */; day: number } | | Paksha | "Shukla" \| "Krishna" | | GeoLocation | { latitude: number; longitude: number } | | Panchang | { tithi, tithiName, tithiNameNp, paksha, nakshatra, nakshatraName, nakshatraNameNp, yoga, yogaName, yogaNameNp, karana, karanaName, karanaNameNp, sunLongitude, moonLongitude } | | SunMoonTimes | { sunrise, sunset, moonrise, moonset } — each Date \| null | | CalendarEvent | { title: string; isHoliday: boolean } | | BsDay | conversion + panchang + events for one day — see below | | BsMonth | { year, month, totalDays, startWeekday, days: BsDay[] } |

Conversion

adToBs(date: Date): BsDate
bsToAd(bs: BsDate): Date
getToday(now?: Date): BsDate
bsDaysInMonth(year: number, month: number): number
bsDaysInYear(year: number): number
monthLengths(year: number): number[]   // the 12 month lengths for a BS year
toISODate(date: Date): string          // "YYYY-MM-DD"

MIN_BS_YEAR  // 2000
MAX_BS_YEAR  // 2090

adToBs/bsToAd are exact round-trips within [MIN_BS_YEAR, MAX_BS_YEAR], derived from a single validated anchor (BS 2083-01-01 = 2026-04-14 AD) by walking an embedded per-year month-length table. Throws a RangeError outside that range.

Calendar — getBsDay / getBsMonth

The high-level functions most apps want: conversion + computed panchang + curated events, merged into one object.

getBsDay(year: number, month: number, gatey: number, location?: GeoLocation): BsDay
getBsMonth(year: number, month: number, location?: GeoLocation): BsMonth

location defaults to Kathmandu (27.7172°N, 85.3240°E) and affects sunrise/sunset (and therefore which tithi is considered to prevail "at sunrise" for that day's panchang).

BsDay

interface BsDay {
  year: number; month: number; gatey: number;   // BS date
  ad: string;                                    // "2026-05-01" (ISO)
  adDate: Date;                                  // same, as a Date
  weekday: number;                               // 0=Sun..6=Sat
  paksha: "Shukla" | "Krishna";
  tithi: number;                                 // 1..30
  panchang: Panchang;                            // full computed panchang at sunrise
  sunrise: Date | null;
  sunset: Date | null;
  isHoliday: boolean;
  holidays: string[];                            // curated public-holiday titles (np)
  events: string[];                               // curated non-holiday event titles (np)
}

Panchang (astronomy)

For when you need panchang at an arbitrary instant rather than a calendar day (e.g. "what's the tithi right now?").

computePanchang(date: Date): Panchang
getSunMoonTimes(date: Date, location?: GeoLocation): SunMoonTimes
lahiriAyanamsa(date: Date): number   // degrees
KATHMANDU: GeoLocation

computePanchang returns sidereal (nirayana) tithi/nakshatra/yoga/karana computed from the Sun and Moon's geocentric ecliptic longitude at that exact instant — it does not apply any day-boundary or sunrise convention itself (that's what getBsDay does on top of it).

Festivals & holidays

getDayEvents(year: number, month: number, gatey: number): DayEvents
listFestivals(year: number, opts?: { month?: number }): DatedEvents[]
getHolidays(year: number): DatedEvents[]          // listFestivals(year).filter(d => d.isHoliday)
hasEventData(year: number): boolean
AVAILABLE_EVENT_YEARS: number[]
interface DayEvents {
  holidays?: string[];
  events?: string[];
  isHoliday?: boolean;
}
interface DatedEvents extends DayEvents {
  month: number;
  gatey: number;
}
import { listFestivals } from "@namlo/nepali-calendar";

listFestivals(2083, { month: 7 });
// [{ month: 7, gatey: 4, holidays: ["विजया दशमी (दशैँ टीका)"], isHoliday: true }, ...]

Formatting

toDevanagari(n: number): string     // 2083 -> "२०८३"
fromDevanagari(s: string): number   // "२०८३" -> 2083
formatBs(bs: BsDate, locale: "en" | "np"): string

BS_MONTHS_EN: string[]   // ["Baishakh", "Jestha", ..., "Chaitra"]
BS_MONTHS_NP: string[]   // ["वैशाख", "जेठ", ..., "चैत्र"]
WEEKDAYS_EN: string[]    // ["Sunday", ..., "Saturday"]
WEEKDAYS_NP: string[]    // ["आइतबार", ..., "शनिबार"]

Data coverage & accuracy

  • Conversion covers BS 2000–2090. BS 2083 is validated exactly against authoritative per-day Gregorian anchors published by the Nepal Panchanga Nirnayak Samiti (Rāṣṭriya Pañchāṅg). Other years rely on a community-sourced month-length table (cross-checked with nepali-date-converter, MIT) and may differ by ±1 day in rare edge years around a month boundary.
  • Panchang is computed at each day's Kathmandu sunrise, following the traditional Nepali day-naming convention (the tithi prevailing at sunrise names the day). Pass a location to getBsDay/getBsMonth to compute for elsewhere.
  • Festivals are curated, editorial data and currently ship for BS 2083 (2026–2027 AD). They're built from the official Rāṣṭriya Pañchāṅg and checked with automated assertions against the computed panchang (e.g. every Ekādaśī-named festival is asserted to land on tithi 11 or 26) so lunar leap-month (adhik māsa) shifts can't silently corrupt placement.
  • Event/holiday titles are Nepali (Devanagari). English romanization is on the roadmap — contributions welcome.

Contributing festival data for a new year

  1. Add a raw source file at scripts/raw/<YYYY>.json (see scripts/clean-source.ts for the exact schema: { year, months: { <MonthName>: { month_index, total_days, days: [{ gatey, date_ad, is_public_holiday, holidays_np, events_np }] } } }).
  2. Run:
    npm run clean:data
    This normalizes the raw file into src/data/events/<YYYY>.json and regenerates the year index.
  3. Add round-trip assertions for the new year's anchors in test/convert.test.ts, and run npm test.
  4. Open a PR. Please cite the source (official panchang publisher, page/date) in the PR description.

Development

git clone <this-repo>
cd nepali-calendar
npm install

npm test            # vitest — conversion round-trips, panchang sanity, festival lookups
npm run typecheck   # tsc --noEmit
npm run build        # tsup -> dist/ (ESM + CJS + .d.ts)

Project layout:

src/
  convert.ts       BS <-> AD conversion
  calendar.ts       getBsDay / getBsMonth (merges conversion + panchang + events)
  panchang.ts       astronomy-engine based panchang + sun/moon rise-set
  festivals.ts      festival/holiday lookup over bundled data
  format.ts         Devanagari numerals, month/weekday names
  data/
    months.ts        BS month-length tables
    events/<YYYY>.json  compiled festival data (generated — do not edit by hand)
scripts/
  build-2083.ts      authoritative BS 2083 festival builder (source of truth)
  clean-source.ts    raw/<YYYY>.json -> src/data/events/<YYYY>.json
test/                vitest suite

License

MIT © HamroAstrology.