NepDate Documentation

Complete API reference for NepDate v2.0.5. Every public method, property, enum, and exception is documented with signatures and working code examples.

Getting Started

Installation

Install from NuGet using your preferred method:

dotnet add package NepDate
Install-Package NepDate
<PackageReference Include="NepDate" Version="2.0.5" />

NepDate has zero external runtime dependencies. Both Newtonsoft.Json and System.Text.Json references are internalized using PrivateAssets=all.

Quick Start

using NepDate;

// Create a NepaliDate from a string
var date = new NepaliDate("2081/04/15");

// Access components
Console.WriteLine(date.Year);         // 2081
Console.WriteLine(date.Month);        // 4
Console.WriteLine(date.Day);          // 15
Console.WriteLine(date.EnglishDate);  // 2024-07-30

// Convert from DateTime
var today = DateTime.Today.ToNepaliDate();
Console.WriteLine(today);             // e.g. 2083/01/07

// Arithmetic
var nextMonth = date.AddMonths(1);
var weekLater = date.AddDays(7);

// Formatting
Console.WriteLine(date.ToString("MMMM dd, yyyy"));   // Shrawan 15, 2081
Console.WriteLine(date.ToLongDateUnicodeString());    // श्रावण १५, २०८१

Creating NepaliDate Instances

// From individual components
var date1 = new NepaliDate(2081, 4, 15);

// From YYYY/MM/DD string
var date2 = new NepaliDate("2081/04/15");

// From YYYYMMDD integer
var date3 = new NepaliDate(20810415);

// From DateTime
var date4 = new NepaliDate(DateTime.Today);

// Extension method
var date5 = DateTime.Today.ToNepaliDate();

// Current date
var today = NepaliDate.Today;
var now   = NepaliDate.Now;  // same as Today

Accessing Properties

PropertyTypeDescription
YearintYear component (1901 to 2199).
MonthintMonth component (1 = Baisakh through 12 = Chaitra).
DayintDay component (1 to MonthEndDay, range 29 to 32).
EnglishDateDateTimeGregorian equivalent. Time is always midnight. Throws on default instance.
DayOfWeekDayOfWeekDay of the week. Saturday is Nepal's official weekly holiday.
DayOfYearint1-based ordinal within the BS calendar year.
MonthEndDayintNumber of days in this month/year (29 to 32).
MonthNameNepaliMonthsEnum for the month name.
IsDefaultboolTrue when the instance is uninitialized (default).
var date = new NepaliDate("2079/12/16");

int year        = date.Year;            // 2079
int month       = date.Month;           // 12
int day         = date.Day;             // 16
DateTime eng    = date.EnglishDate;     // 2023/03/30
DayOfWeek dow   = date.DayOfWeek;       // Thursday
int dayOfYear   = date.DayOfYear;       // 346
int monthEndDay = date.MonthEndDay;     // 30
NepaliDate end  = date.MonthEndDate();  // 2079/12/30
NepaliMonths mn = date.MonthName;       // Chaitra
bool isDefault  = date.IsDefault;       // false

Calendar properties:

PropertyTypeDescription
TithiNpstringTithi in Nepali Devanagari. Empty outside 2001–2089 BS.
TithiEnstringTithi transliterated to English. Empty outside 2001–2089 BS.
IsPublicHolidayboolGazetted public holiday flag based on cross-verified calendar data.
EventsNpstring[]Event names in Nepali. Empty array if none.
EventsEnstring[]Event names in English. Empty array if none.

Static properties:

PropertyTypeDescription
NepaliDate.TodayNepaliDateCurrent date per local system clock.
NepaliDate.NowNepaliDateSame as Today. Parity with DateTime.Now.
NepaliDate.MinValueNepaliDate1 Baisakh 1901 BS (approx 1844-04-13 AD).
NepaliDate.MaxValueNepaliDateLast day of Chaitra 2199 BS (approx 2143-04-12 AD).

Date Operations

Adding and Subtracting Days

var date = new NepaliDate("2081/04/32");

var later   = date.AddDays(5);   // 2081/05/05
var earlier = date.AddDays(-5);  // 2081/04/27

Signature: NepaliDate AddDays(double days). Adds the specified number of days. Performed in the Gregorian domain then converted back. Negative values move backward.

Adding and Subtracting Months

var date = new NepaliDate("2081/04/32");

var plus2  = date.AddMonths(2);   // 2081/06/30
var minus2 = date.AddMonths(-2);  // 2081/02/32

Signature: NepaliDate AddMonths(double months, bool awayFromMonthEnd = false). Adds whole or fractional months. Fractional months are converted to days using approximately 30.42 days per month. Negative values move backward.

Adding and Subtracting Years

var date = new NepaliDate("2081/04/15");
var nextYear = date.AddYears(1);   // 2082/04/15
var prevYear = date.AddYears(-1);  // 2080/04/15

Signature: NepaliDate AddYears(int years, bool awayFromMonthEnd = false). Delegates to AddMonths(years * 12).

Fractional Month Addition

var date = new NepaliDate("2081/04/32");
var frac = date.AddMonths(2.5);  // 2081/07/15

Fractional months are converted to days using the approximation of 30.42 days per month.

Away From Month End

When awayFromMonthEnd is true, the result is pulled away from the month-end boundary into the next month. Useful when you need a specific day rather than clamping.

var date = new NepaliDate("2081/04/32");

// Default: clamps to month end
var clamped = date.AddMonths(2);                           // 2081/06/30

// Away from month end: overflows into next month
var overflow = date.AddMonths(2, awayFromMonthEnd: true);  // 2081/07/02

Comparison Operators

var a = NepaliDate.Parse("2079/12/16");
var b = NepaliDate.Parse("2080/01/01");

bool eq = a == b;  // false
bool ne = a != b;  // true
bool lt = a < b;   // true
bool le = a <= b;  // true
bool gt = a > b;   // false
bool ge = a >= b;  // false

All standard comparison operators are supported through IComparable<NepaliDate> and operator overloads.

Date Difference (Subtract)

var a = NepaliDate.Parse("2079/12/16");
var b = NepaliDate.Parse("2080/06/01");

TimeSpan diff1 = b - a;           // operator overload
TimeSpan diff2 = b.Subtract(a);   // method equivalent

Signature: TimeSpan Subtract(NepaliDate nepDateTo). Returns the elapsed time between this date and another.

Conversion (BS ↔ AD)

// BS to AD
DateTime eng = NepaliDate.Parse("2079/12/16").EnglishDate;

// AD to BS
NepaliDate nep = new NepaliDate(DateTime.Now);
// or
NepaliDate nep2 = DateTime.Now.ToNepaliDate();  // extension method

string nepStr = nep.ToString();  // "2083/01/07"

Bulk Conversion

ToNepaliDates

var engDates = new List<DateTime> { DateTime.Today, DateTime.Today.AddDays(1) };
IEnumerable<NepaliDate> nepDates = NepaliDate.BulkConvert.ToNepaliDates(engDates);

Signature: static IEnumerable<NepaliDate> ToNepaliDates(IEnumerable<DateTime> engDates, bool useParallel = true). Converts a collection of DateTime values. Automatically uses parallel processing for collections exceeding 500 items.

ToEnglishDates

// From NepaliDate collection
IEnumerable<DateTime> eng1 = NepaliDate.BulkConvert.ToEnglishDates(nepDates);

// From string collection
var nepStrings = new List<string> { "2080/01/01", "2080/02/15" };
IEnumerable<DateTime> eng2 = NepaliDate.BulkConvert.ToEnglishDates(nepStrings);

Signatures:

  • static IEnumerable<DateTime> ToEnglishDates(IEnumerable<NepaliDate> nepDates, bool useParallel = true)
  • static IEnumerable<DateTime> ToEnglishDates(IEnumerable<string> nepDates, bool useParallel = true)

BatchProcessToNepaliDates

var largeDateList = Enumerable.Range(0, 10000).Select(i => DateTime.Today.AddDays(i));
IEnumerable<NepaliDate> results =
    NepaliDate.BulkConvert.BatchProcessToNepaliDates(largeDateList, batchSize: 2000);

Signature: static IEnumerable<NepaliDate> BatchProcessToNepaliDates(IEnumerable<DateTime> engDates, int batchSize = 1000). Processes in explicit batches. Throws ArgumentOutOfRangeException if batchSize < 1.

BatchProcessToEnglishDates

IEnumerable<DateTime> results =
    NepaliDate.BulkConvert.BatchProcessToEnglishDates(nepDates, batchSize: 2000);

Signature: static IEnumerable<DateTime> BatchProcessToEnglishDates(IEnumerable<NepaliDate> nepDates, int batchSize = 1000).

Date Range Operations

Creating Ranges

var start = new NepaliDate(2080, 1, 1);
var end   = new NepaliDate(2080, 3, 15);
var range = new NepaliDateRange(start, end);

Constructor: NepaliDateRange(NepaliDate start, NepaliDate end). Both inclusive. If end < start, creates an empty range.

Factory Methods

MethodReturnsDescription
SingleDay(NepaliDate date)NepaliDateRangeSingle day range.
FromDayCount(NepaliDate start, int days)NepaliDateRangeRange spanning specified days. Throws if days < 1.
ForMonth(int year, int month)NepaliDateRangeComplete Nepali month.
ForFiscalYear(int fiscalYear)NepaliDateRange1 Shrawan to last day of Ashadh.
ForCalendarYear(int year)NepaliDateRange1 Baisakh to last day of Chaitra.
CurrentMonth()NepaliDateRangeCurrent Nepali month.
CurrentFiscalYear()NepaliDateRangeCurrent Nepali fiscal year.
CurrentCalendarYear()NepaliDateRangeCurrent Nepali calendar year.
var single   = NepaliDateRange.SingleDay(start);
var tenDays  = NepaliDateRange.FromDayCount(start, 10);
var month    = NepaliDateRange.ForMonth(2080, 1);
var fy       = NepaliDateRange.ForFiscalYear(2080);
var calYear  = NepaliDateRange.ForCalendarYear(2080);
var curMonth = NepaliDateRange.CurrentMonth();
var curFY    = NepaliDateRange.CurrentFiscalYear();
var curYear  = NepaliDateRange.CurrentCalendarYear();

Properties and Containment

MemberTypeDescription
StartNepaliDateStart date (inclusive).
EndNepaliDateEnd date (inclusive).
IsEmptyboolTrue when Start > End.
LengthintNumber of days in the range. 0 if empty.
Contains(NepaliDate)boolWhether the range contains the date.
Contains(NepaliDateRange)boolWhether this range fully contains another.
Overlaps(NepaliDateRange)boolWhether ranges share at least one date.
IsAdjacentTo(NepaliDateRange)boolWhether ranges are adjacent (no overlap, 1 day gap).
var range = new NepaliDateRange(start, end);

bool empty    = range.IsEmpty;           // false
int  days     = range.Length;            // total days
bool hasDate  = range.Contains(someDate);
bool hasRange = range.Contains(otherRange);
bool overlaps = range.Overlaps(otherRange);
bool adjacent = range.IsAdjacentTo(otherRange);

Set Operations (Intersect, Union, Except)

NepaliDateRange intersection = range.Intersect(otherRange);  // dates in both
NepaliDateRange union        = range.Union(otherRange);       // all dates from both
NepaliDateRange[] remaining  = range.Except(otherRange);      // 0, 1, or 2 ranges
MethodReturnsDescription
Intersect(NepaliDateRange)NepaliDateRangeDates present in both ranges. Empty if no overlap.
Union(NepaliDateRange)NepaliDateRangeAll dates from both ranges. May span the gap.
Except(NepaliDateRange)NepaliDateRange[]Remaining range(s) after excluding the other. Returns 0, 1, or 2 segments.

Splitting (By Month, By Fiscal Quarter)

NepaliDateRange[] byMonth   = range.SplitByMonth();
NepaliDateRange[] byQuarter = range.SplitByFiscalQuarter();

Iteration and Filtering

// Enumerate every date in the range
foreach (NepaliDate date in range) { }

// Dates at regular intervals
IEnumerable<NepaliDate> weekly = range.DatesWithInterval(7);

Signature: IEnumerable<NepaliDate> DatesWithInterval(int interval). Throws ArgumentOutOfRangeException if interval < 1.

Working and Weekend Days

// Working days (excludes Saturdays)
IEnumerable<NepaliDate> working       = range.WorkingDays();

// Working days (excludes Saturdays and Sundays)
IEnumerable<NepaliDate> workingNoSun  = range.WorkingDays(excludeSunday: true);

// Weekend days (Saturdays only)
IEnumerable<NepaliDate> weekends      = range.WeekendDays();

// Weekend days (Saturdays and Sundays)
IEnumerable<NepaliDate> weekendsBoth  = range.WeekendDays(includeSunday: true);

Range Formatting

string basic     = range.ToString();
// "2080/01/01 - 2080/03/15"

string formatted = range.ToString(DateFormats.DayMonthYear, Separators.Dash);
// "01-01-2080 - 15-03-2080"

Formatting and Display

Default Format

var date = new NepaliDate("2079/02/06");
date.ToString()   // "2079/02/06"

Default format is YYYY/MM/DD with leading zeros.

Custom Format and Separator

date.ToString(DateFormats.DayMonthYear, Separators.Dash, leadingZeros: false)
// "6-2-2079"

Signature: string ToString(DateFormats dateFormat, Separators separator = ForwardSlash, bool leadingZeros = true).

Long Date String

date.ToLongDateString()
// "Jestha 06, 2079"

date.ToLongDateString(leadingZeros: false, displayDayName: true, displayYear: false)
// "Friday, Jestha 6"

Signature: string ToLongDateString(bool leadingZeros = true, bool displayDayName = false, bool displayYear = true).

Unicode String

date.ToUnicodeString(DateFormats.DayMonthYear, Separators.Dot, leadingZeros: true)
// "०६.०२.२०७९"

Signature: string ToUnicodeString(DateFormats dateFormat = YearMonthDay, Separators separator = ForwardSlash, bool leadingZeros = true).

Long Date Unicode String

date.ToLongDateUnicodeString(leadingZeros: false, displayDayName: true, displayYear: false)
// "शुक्रबार, जेठ ६"

Signature: string ToLongDateUnicodeString(bool leadingZeros = true, bool displayDayName = false, bool displayYear = true).

IFormattable Format Specifiers

NepaliDate implements IFormattable (and ISpanFormattable on .NET 6+). Format strings work in string interpolation, string.Format, and any IFormattable context.

SpecifierOutputNotes
"d" or "G"2079/02/06Same as ToString().
"D"Jestha 06, 2079Long date with leading zeros.
"s"2079-02-06Sortable, dash separated.
custom patternvariesSee custom tokens below.
date.ToString("d")                     // 2079/02/06
date.ToString("D")                     // Jestha 06, 2079
date.ToString("s")                     // 2079-02-06
date.ToString("dd-MM-yyyy")            // 06-02-2079
date.ToString("MMMM dd, yyyy")         // Jestha 06, 2079
date.ToString("MMM yyyy")              // Jes 2079
date.ToString("dd 'of' MMMM")          // 06 of Jestha
$"{date:s}"                            // 2079-02-06
string.Format("{0:yyyy/MM/dd}", date)  // 2079/02/06

Custom Format Tokens

TokenDescriptionExample
yyyy4 digit year2079
yy2 digit year79
MMMMFull month nameJestha
MMM3 letter abbreviationJes
MMZero padded month02
MMonth number2
ddZero padded day06
dDay number6
'...'Literal text'of' renders as "of"
\Escape next character

ISpanFormattable

On .NET 6+, NepaliDate implements ISpanFormattable for allocation-free formatting into Span<char>.

Span<char> buffer = stackalloc char[32];
bool success = date.TryFormat(buffer, out int charsWritten, "yyyy-MM-dd", null);

Smart Date Parsing

SmartDateParser.Parse

NepaliDate d1 = SmartDateParser.Parse("15 Shrawan 2080");
NepaliDate d2 = SmartDateParser.Parse("Shrawan 15, 2080");
NepaliDate d3 = SmartDateParser.Parse("15 Saun 2080");        // alternate spelling
NepaliDate d4 = SmartDateParser.Parse("२०८०/०४/१५");          // Nepali digits
NepaliDate d5 = SmartDateParser.Parse("१५ श्रावण २०८०");      // full Nepali

Signature: static NepaliDate Parse(string input). Parses using all strategies: standard numeric, Nepali Unicode digits, month name detection, ambiguous permutation. Throws ArgumentNullException for null input, FormatException for unparseable input.

SmartDateParser.TryParse

if (SmartDateParser.TryParse("15 Shrawan 2080", out NepaliDate result))
    Console.WriteLine(result);

Signature: static bool TryParse(string input, out NepaliDate result). Same heuristics without throwing.

String Extension Methods

NepaliDate d1 = "15 Shrawan 2080".ToNepaliDate();

if ("15 Shrawan 2080".TryToNepaliDate(out NepaliDate d2))
    Console.WriteLine(d2);
MethodSignatureDescription
ToNepaliDate()static NepaliDate ToNepaliDate(this string input)Smart parses any supported format. Throws FormatException.
TryToNepaliDate()static bool TryToNepaliDate(this string input, out NepaliDate result)Non-throwing variant.

Auto Adjust Parsing

NepaliDate p1 = NepaliDate.Parse("2077_05_25", autoAdjust: true);
// 2077/05/25

NepaliDate p2 = NepaliDate.Parse("25-05-077", autoAdjust: true);
// 2077/05/25 (year < 1000 expanded, day > 32 swapped)

NepaliDate p3 = NepaliDate.Parse("05/06/2077", autoAdjust: true);
// 2077/06/05 (month in middle)

NepaliDate p4 = NepaliDate.Parse("05/06/2077", autoAdjust: true, monthInMiddle: false);
// 2077/05/06

Auto adjust rules (applied in order):

  1. day > 32: swap year and day
  2. monthInMiddle: false: swap month and day first
  3. month > 12 and day < 13: swap month and day
  4. year < 1000: prepend current millennium (2000)
bool ok = NepaliDate.TryParse("05/06/2077", out NepaliDate result,
                              autoAdjust: true, monthInMiddle: true);

Supported Formats and Spellings

SmartDateParser recognizes:

  • Standard numeric: 2080/04/15, 2080-04-15, 2080.04.15, etc.
  • Nepali Unicode digits: २०८०/०४/१५
  • Month names (100+ spellings): Shrawan, Sawan, Saun, Srawan, श्रावण, साउन, etc. for all 12 months.
  • Mixed formats: 15 Shrawan 2080, Shrawan 15, 2080, 2080 Shrawan 15
  • Optional suffixes: B.S., V.S., गते, मिति (stripped before parsing)
  • 2 digit year expansion: 80 becomes 2080
  • Common separators: /, -, ., _, \, space, pipe, Nepali pipe

Fiscal Year Operations

Nepal's fiscal year runs from 1 Shrawan (month 4) to the last day of Ashadh (month 3) of the following year.

Instance Methods

MethodReturnsDescription
FiscalYearStartDate(int yearOffset = 0)NepaliDateStart date (1 Shrawan) of the containing fiscal year.
FiscalYearEndDate(int yearOffset = 0)NepaliDateEnd date (last day of Ashadh) of the containing fiscal year.
FiscalYearStartAndEndDate(int yearOffset = 0)(NepaliDate, NepaliDate)Both start and end dates.
FiscalYearQuarterStartDate(FiscalYearQuarters q = Current, int yearOffset = 0)NepaliDateStart of specified fiscal quarter.
FiscalYearQuarterEndDate(FiscalYearQuarters q = Current, int yearOffset = 0)NepaliDateEnd of specified fiscal quarter.
FiscalYearQuarterStartAndEndDate(FiscalYearQuarters q = Current, int yearOffset = 0)(NepaliDate, NepaliDate)Both quarter dates.
var date = new NepaliDate("2081/04/15");  // Q1 of FY 2081

NepaliDate fyStart = date.FiscalYearStartDate();         // 2081/04/01
NepaliDate fyEnd   = date.FiscalYearEndDate();           // 2082/03/last
var (s, e)         = date.FiscalYearStartAndEndDate();

NepaliDate qStart  = date.FiscalYearQuarterStartDate();  // 2081/04/01
NepaliDate qEnd    = date.FiscalYearQuarterEndDate();    // 2081/06/30
var (qs, qe)       = date.FiscalYearQuarterStartAndEndDate();

// Next fiscal year
NepaliDate nextFyStart = date.FiscalYearStartDate(yearOffset: 1);  // 2082/04/01

Static Methods

MethodReturnsDescription
GetFiscalYearStartDate(int fiscalYear)NepaliDate1 Shrawan of specified FY.
GetFiscalYearEndDate(int fiscalYear)NepaliDateLast day of Ashadh of FY+1.
GetFiscalYearStartAndEndDate(int fiscalYear)(NepaliDate, NepaliDate)Both dates.
GetFiscalYearQuarterStartDate(int fiscalYear, int month)NepaliDateQuarter start. Month determines which quarter.
GetFiscalYearQuarterEndDate(int fiscalYear, int month)NepaliDateQuarter end.
GetFiscalYearQuarterStartAndEndDate(int fiscalYear, int month)(NepaliDate, NepaliDate)Both quarter dates.
NepaliDate start = NepaliDate.GetFiscalYearStartDate(2080);  // 2080/04/01
NepaliDate end   = NepaliDate.GetFiscalYearEndDate(2080);    // 2081/03/last
var (s, e)       = NepaliDate.GetFiscalYearStartAndEndDate(2080);

NepaliDate qS = NepaliDate.GetFiscalYearQuarterStartDate(2080, 4);  // 2080/04/01
NepaliDate qE = NepaliDate.GetFiscalYearQuarterEndDate(2080, 4);    // 2080/06/30

// Q4: month 1 of FY 2080 falls in calendar year 2081
var (q4s, q4e) = NepaliDate.GetFiscalYearQuarterStartAndEndDate(2080, 1);
// (2081/01/01, 2081/03/last)

Quarters

QuarterMonthsMonth Range
Q1 (First)Shrawan to Ashoj4 to 6
Q2 (Second)Kartik to Poush7 to 9
Q3 (Third)Magh to Chaitra10 to 12
Q4 (Fourth)Baishakh to Ashadh1 to 3
public enum FiscalYearQuarters
{
    Current = 0,    // resolved at runtime from the date's month
    First   = 4,    // Shrawan to Ashoj
    Second  = 7,    // Kartik to Poush
    Third   = 10,   // Magh to Chaitra
    Fourth  = 1,    // Baishakh to Ashadh
}

Year Offset

The yearOffset parameter shifts the result relative to the containing fiscal year. 0 means current, 1 means next FY, -1 means previous FY.

var date = new NepaliDate("2081/04/15");

date.FiscalYearStartDate(yearOffset:  0);  // 2081/04/01 (current)
date.FiscalYearStartDate(yearOffset:  1);  // 2082/04/01 (next)
date.FiscalYearStartDate(yearOffset: -1);  // 2080/04/01 (previous)

Calendar Data

Tithi

var date = new NepaliDate(2081, 4, 15);
string tithiNp = date.TithiNp;  // Nepali Devanagari tithi name
string tithiEn = date.TithiEn;  // English transliterated tithi name

Returns the lunar day (Tithi) for the date. Empty string for dates outside 2001–2089 BS.

Public Holidays

bool isHoliday = date.IsPublicHoliday;  // true if gazetted holiday

Based on cross-verified Bikram Sambat calendar data. Returns false for dates outside the data range.

Events

string[] eventsNp = date.EventsNp;  // event names in Nepali
string[] eventsEn = date.EventsEn;  // event names in English

Returns an empty (non-null) array when there are no events.

GetCalendarInfo

CalendarInfo info = date.GetCalendarInfo();
// info.TithiNp, info.TithiEn, info.IsPublicHoliday, info.EventsNp, info.EventsEn

Signature: CalendarInfo GetCalendarInfo(). Returns all calendar metadata in a single lookup. Prefer this over accessing individual properties when you need multiple pieces of calendar data.

CalendarInfo struct:

PropertyTypeDescription
TithiNpstringTithi in Nepali Devanagari.
TithiEnstringTithi in English.
IsPublicHolidayboolPublic holiday flag.
EventsNpstring[]Event names in Nepali.
EventsEnstring[]Event names in English.

Data Coverage

Calendar data (Tithi, holidays, events) is compiled from authoritative Bikram Sambat calendar references and cross-verified for accuracy, covering 2001 to 2089 BS. All properties gracefully return empty or default values for dates outside this range without throwing exceptions.

Serialization

System.Text.Json

On .NET 5+, a [JsonConverter] is auto-registered on NepaliDate, so basic serialization works without setup.

using System.Text.Json;
using NepDate.Serialization;

// String format (default): "2080-04-15"
var opts = new JsonSerializerOptions().ConfigureForNepaliDate();

// Object format: {"Year":2080,"Month":4,"Day":15}
var optsObj = new JsonSerializerOptions().ConfigureForNepaliDate(useObjectFormat: true);

var date = new NepaliDate(2080, 4, 15);
string json  = JsonSerializer.Serialize(date, opts);         // "2080-04-15"
var restored = JsonSerializer.Deserialize<NepaliDate>(json, opts);

Newtonsoft.Json

using Newtonsoft.Json;
using NepDate.Serialization;

var settings    = new JsonSerializerSettings().ConfigureForNepaliDate();
var settingsObj = new JsonSerializerSettings().ConfigureForNepaliDate(useObjectFormat: true);

var date = new NepaliDate(2080, 4, 15);
string json = JsonConvert.SerializeObject(date, settings);         // "2080-04-15"
var back    = JsonConvert.DeserializeObject<NepaliDate>(json, settings);

XML Serialization

using System.Xml.Serialization;
using NepDate.Serialization;

public class PersonRecord
{
    public string Name { get; set; }
    public NepaliDateXmlSerializer BirthDate { get; set; }

    [XmlIgnore]
    public NepaliDate ActualBirthDate
    {
        get => BirthDate?.Value ?? default;
        set => BirthDate = new NepaliDateXmlSerializer(value);
    }
}

var p = new PersonRecord
{
    Name = "Ram Sharma",
    ActualBirthDate = new NepaliDate(2040, 2, 15)
};
var serializer = new XmlSerializer(typeof(PersonRecord));

NepaliDateXmlSerializer implements IXmlSerializable. Required because NepaliDate is a struct without a parameterless constructor.

String vs Object Format

ModeJSON OutputWhen to Use
String (default)"2080-04-15"APIs, compact payloads, human readable.
Object{"Year":2080,"Month":4,"Day":15}When consumers need individual components.

Both modes accept either format on deserialization (string or object JSON), regardless of which mode was used for serialization.

Configuration Extensions

MethodTargetDescription
ConfigureForNepaliDate(this JsonSerializerOptions, bool useObjectFormat = false)System.Text.JsonRegisters converter. Returns the options for chaining.
ConfigureForNepaliDate(this JsonSerializerSettings, bool useObjectFormat = false)Newtonsoft.JsonRegisters converter. Returns the settings for chaining.

Type System Integration

IComparable

int cmp = date1.CompareTo(date2);  // negative, zero, or positive

Implements IComparable<NepaliDate> and IComparable. Compares using the internal integer representation (YYYYMMDD).

IEquatable

bool eq = date1.Equals(date2);
int hash = date1.GetHashCode();

Implements IEquatable<NepaliDate>. Hash code is the internal YYYYMMDD integer.

IFormattable

string s = string.Format("{0:yyyy-MM-dd}", date);
string t = $"{date:MMMM dd, yyyy}";

Enables format string support in interpolation, string.Format, and any IFormattable consumer.

ISpanFormattable

Available on .NET 6+. Enables allocation-free formatting.

Span<char> buf = stackalloc char[32];
date.TryFormat(buf, out int written, "yyyy-MM-dd", null);

IParsable and ISpanParsable

Available on .NET 7+. Enables generic parsing in contexts that accept IParsable<T>.

var d = NepaliDate.Parse("2080/04/15", null);  // IParsable<NepaliDate>.Parse
bool ok = NepaliDate.TryParse("2080/04/15", null, out var result);

TypeConverter

NepaliDateTypeConverter is auto-registered via the [TypeConverter] attribute. It enables:

  • ASP.NET MVC / Web API model binding
  • WPF and WinForms data binding and property grids
  • Generic TypeDescriptor.GetConverter() usage

Supports conversion to/from string, int (YYYYMMDD format), and DateTime.

JsonConverter Auto Registration

On .NET 5+, the System.Text.Json converter is registered via a [JsonConverter] attribute on the type, so basic JsonSerializer.Serialize/Deserialize calls work without any options configuration. Use ConfigureForNepaliDate() to opt into object-mode serialization or to support Newtonsoft.Json.

Enums

NepaliMonths

public enum NepaliMonths
{
    Baisakh = 1,
    Jestha  = 2,
    Ashadh  = 3,
    Shrawan = 4,
    Bhadra  = 5,
    Ashoj   = 6,
    Kartik  = 7,
    Mangsir = 8,
    Poush   = 9,
    Magh    = 10,
    Falgun  = 11,
    Chaitra = 12,
}

DateFormats

public enum DateFormats
{
    YearMonthDay,
    YearDayMonth,
    MonthYearDay,
    MonthDayYear,
    DayYearMonth,
    DayMonthYear,
}

Separators

public enum Separators
{
    ForwardSlash,
    BackwardSlash,
    Dash,
    Dot,
    Underscore,
    Space,
}

FiscalYearQuarters

public enum FiscalYearQuarters
{
    Current = 0,    // resolved at runtime from the date's month
    First   = 4,    // Shrawan to Ashoj
    Second  = 7,    // Kartik to Poush
    Third   = 10,   // Magh to Chaitra
    Fourth  = 1,    // Baishakh to Ashadh
}

Exceptions

InvalidNepaliDateFormatException

Thrown by constructors and Parse when input cannot be interpreted as a valid NepaliDate. Derives from FormatException. Contains the offending input string for diagnostics.

try
{
    var bad = new NepaliDate("2080/13/45");
}
catch (InvalidNepaliDateFormatException ex)
{
    Console.WriteLine(ex.Message);
}

ArgumentOutOfRangeException

Thrown when numeric arguments fall outside valid ranges: day not in 1..MonthEndDay, month not in 1..12, year not in 1901..2199, batchSize < 1 in bulk operations, interval < 1 in DatesWithInterval, days < 1 in FromDayCount.

ArgumentNullException

Thrown by SmartDateParser.Parse and string-based constructors when input is null. Use TryParse or TryToNepaliDate variants to avoid throws.

FormatException

Thrown by SmartDateParser.Parse when input is non-null but unparseable. InvalidNepaliDateFormatException derives from this type, so a single catch (FormatException) handles both.

Advanced

Struct Design

NepaliDate is a readonly partial struct with a single integer backing field encoding the date as YYYYMMDD. This means:

  • Zero heap allocations when values are passed around locally.
  • Inherently immutable and thread-safe.
  • Trivial to store in arrays, spans, and high-density collections.
  • GetHashCode returns the encoded integer directly for extremely cheap dictionary keys.

Thread Safety

All public types are immutable. NepaliDate, NepaliDateRange, and CalendarInfo are readonly structs. BulkConvert operations are safe to invoke concurrently and use thread-safe parallel processing internally.

Internalized Dependencies

NepDate depends on Newtonsoft.Json and System.Text.Json at build time only. Both are referenced with PrivateAssets=all so they never surface in your consuming project's dependency graph. NepDate has zero external runtime dependencies from the consumer's perspective.

Supported Range

RangeCoverage
Conversion (BS ↔ AD)1901/01/01 BS (approx 1844-04-13 AD) through 2199/12/last BS (approx 2143-04-12 AD).
Calendar metadata (Tithi, holidays, events)2001 BS through 2089 BS. Outside this range, properties return empty defaults without throwing.
Fiscal year operationsSame as conversion range.

Something missing?

Spot a typo, unclear section, or want a new example? Open an issue or PR on GitHub.

Open an issue on GitHub