# How Bikram Sambat Calendar Math Works in .NET

Author: Raju Prasai
Published: 2026-06-01
URL: https://rajuprasai.com.np/blog/bikram-sambat-calendar-math.html
Tags: Bikram Sambat, nepali calendar, nepali date converter, bs to ad, NepDate, .NET, C#
Read time: 10 min

---

## Summary

The Bikram Sambat (BS) calendar cannot be converted to Gregorian with a simple formula. Month lengths are 29 to 32 days, determined by solar transits, and vary year by year. This post explains why, how lookup tables solve it, and how the NepDate library handles it in .NET with O(1) performance and zero heap allocations.

---

## Why Nepali Developers Encounter This Problem Daily

If you write software in Nepal, you live in two calendars simultaneously. The government issues notifications in Bikram Sambat. Salary slips, land documents, court filings, and the national budget all use BS dates. But your database stores `DateTime`, your APIs exchange ISO 8601, and your .NET runtime knows nothing about BS.

Every Nepali developer eventually writes a date conversion utility. Most do it badly the first time: a hardcoded lookup array, an off-by-one at the year boundary, and a different epoch offset than the one used by the government Patro. Understanding the actual math is the difference between using a library correctly and debugging a conversion mismatch in production.

---

## What is Bikram Sambat?

Bikram Sambat (also written Vikram Samvat) is a lunisolar calendar originating in the Indian subcontinent. Nepal officially adopted it as the national calendar. All government processes, school calendars, and public holidays are defined in BS.

The 12 BS months and their approximate Gregorian equivalents:

| # | BS Month | Nepali | Approx. Gregorian |
|---|---|---|---|
| 1 | Baishakh | बैशाख | Mid-April to Mid-May |
| 2 | Jestha | जेठ | Mid-May to Mid-June |
| 3 | Ashadh | असार | Mid-June to Mid-July |
| 4 | Shrawan | श्रावण | Mid-July to Mid-August |
| 5 | Bhadra | भाद्र | Mid-August to Mid-September |
| 6 | Ashwin | आश्विन | Mid-September to Mid-October |
| 7 | Kartik | कार्तिक | Mid-October to Mid-November |
| 8 | Mangsir | मंसिर | Mid-November to Mid-December |
| 9 | Poush | पौष | Mid-December to Mid-January |
| 10 | Magh | माघ | Mid-January to Mid-February |
| 11 | Falgun | फाल्गुण | Mid-February to Mid-March |
| 12 | Chaitra | चैत्र | Mid-March to Mid-April |

BS is currently about 56 to 57 years ahead of the Gregorian calendar. The offset is not constant: from January 1 to around mid-April the BS year is AD + 56; from mid-April to December 31 it is AD + 57.

---

## The Month Length Problem

BS months do not follow a fixed pattern. Each month's length is determined by when the sun transits from one zodiac sign (Rashi) to the next. Because the sun moves at non-uniform angular velocity along its elliptical orbit, the time between successive transits is not constant. Some transits take about 29 days, others take about 32 days.

Month lengths cannot be computed from a formula. The same month in different BS years may have a different number of days. A library that does not embed a pre-computed table for each supported year will produce wrong results.

Example: BS 2082 month lengths:

| Month | Days | Month | Days |
|---|---|---|---|
| Baishakh | 31 | Shrawan | 31 |
| Jestha | 31 | Bhadra | 31 |
| Ashadh | 32 | Ashwin | 31 |
| Kartik | 30 | Magh | 29 |
| Mangsir | 29 | Falgun | 30 |
| Poush | 30 | Chaitra | 30 |

Ashadh has 32 days. Kartik has 30. These values are not computable from arithmetic - they are empirical. The total for the year is 365 days. Compare that with BS 2084, where four individual months have different lengths even though the annual total is the same.

---

## The Lookup Table Approach

Every correct BS/AD conversion library uses a pre-computed data table recording, for each BS year: the Gregorian date of Baishakh 1, and the day count of each of the 12 months.

**AD to BS:** Find which BS year the Gregorian date falls in by comparing to Baishakh 1 dates. Subtract Baishakh 1 to get day-of-year offset. Accumulate month lengths until offset is consumed.

**BS to AD:** Look up the Gregorian date of Baishakh 1 for the target BS year. Sum day counts of all months before the target month. Add target day minus one.

NepDate uses a compact binary encoding with a flat array index: `year - 1901`. A single array access with no tree traversal, no hash lookup, no iteration. This is why NepDate runs at approximately 4.55 nanoseconds per conversion.

---

## Nepal's Fiscal Year

The Government of Nepal defines the fiscal year as running from Shrawan 1 to Ashadh end - month 4 to the last day of month 3 in the following year. Shrawan 1 typically falls around July 16-17 in the Gregorian calendar. The fiscal year is labeled by the BS year in which Shrawan falls: FY 2082/83 runs from Shrawan 1, 2082 to Ashadh end, 2083.

Key edge case: Ashadh has 31 or 32 days depending on the year. A query that hardcodes Ashadh 31 as the fiscal year end silently truncates data. Always use the library to get the actual day count.

---

## Working with NepDate in .NET

NepDate is available on NuGet: https://www.nuget.org/packages/NepDate/
Documentation: https://nepdate.rajuprasai.com.np/
Source: https://github.com/RajuPrasai/NepDate

Installation:
```
dotnet add package NepDate
```

Basic conversion:
```csharp
using NepDate;

// Gregorian to Bikram Sambat
var adDate = new DateTime(2025, 10, 18);
var bsDate = new NepaliDate(adDate);
// bsDate → 2082-07-01 (Kartik 1, 2082)

// Bikram Sambat to Gregorian
var bs = new NepaliDate(2082, 3, 15);  // Ashadh 15, 2082
DateTime ad = bs.EnglishDate;
// ad → 2025-06-29
```

Days in a month:
```csharp
int days = new NepaliDate(2083, 3, 1).MonthEndDay;
// Never hardcode month lengths - always ask the library.
```

Fiscal year range for database queries:
```csharp
var today = NepaliDate.Now;
var (fyStartBs, fyEndBs) = today.FiscalYearStartAndEndDate();
DateTime adStart = fyStartBs.EnglishDate;
DateTime adEnd   = fyEndBs.EnglishDate.AddDays(1).AddSeconds(-1);
// Use adStart and adEnd in your EF Core or Dapper query
```

---

## Common Mistakes to Avoid

- **Hardcoding month lengths** - there is no standard year; every year's month lengths are different.
- **Assuming a fixed BS-to-AD offset** - the offset is 56 for part of the year and 57 for the rest; arithmetic is wrong.
- **Assuming fiscal year ends on Ashadh 31** - Ashadh has 32 days in many years; use `MonthEndDay`.
- **Different libraries, different epochs** - a one-day epoch difference silently corrupts every date in the system.

---

## Conclusion

Bikram Sambat is a solar calendar where month lengths are determined by astronomical observation, not arithmetic. The only correct implementation is a lookup table validated against the official Patro.

For .NET developers: NepDate provides a correctly validated table covering BS 1901 to 2199, a `readonly struct` value type with zero heap allocations, O(1) lookup performance, and fiscal year helpers built in.

Library: https://nepdate.rajuprasai.com.np/
NuGet: https://www.nuget.org/packages/NepDate/
GitHub: https://github.com/RajuPrasai/NepDate

---

## About the Author

Raju Prasai is a Project Manager and Senior .NET Engineer from Jhapa, Nepal. 10+ years delivering production systems across banking, e-commerce, and cloud. Author of NepDate (28,000+ NuGet downloads) and NepDate Widget.

Portfolio: https://rajuprasai.com.np/
GitHub: https://github.com/RajuPrasai
Twitter: https://x.com/CrossLegCoder
