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
| Property | Type | Description |
|---|---|---|
Year | int | Year component (1901 to 2199). |
Month | int | Month component (1 = Baisakh through 12 = Chaitra). |
Day | int | Day component (1 to MonthEndDay, range 29 to 32). |
EnglishDate | DateTime | Gregorian equivalent. Time is always midnight. Throws on default instance. |
DayOfWeek | DayOfWeek | Day of the week. Saturday is Nepal's official weekly holiday. |
DayOfYear | int | 1-based ordinal within the BS calendar year. |
MonthEndDay | int | Number of days in this month/year (29 to 32). |
MonthName | NepaliMonths | Enum for the month name. |
IsDefault | bool | True 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:
| Property | Type | Description |
|---|---|---|
TithiNp | string | Tithi in Nepali Devanagari. Empty outside 2001–2089 BS. |
TithiEn | string | Tithi transliterated to English. Empty outside 2001–2089 BS. |
IsPublicHoliday | bool | Gazetted public holiday flag based on cross-verified calendar data. |
EventsNp | string[] | Event names in Nepali. Empty array if none. |
EventsEn | string[] | Event names in English. Empty array if none. |
Static properties:
| Property | Type | Description |
|---|---|---|
NepaliDate.Today | NepaliDate | Current date per local system clock. |
NepaliDate.Now | NepaliDate | Same as Today. Parity with DateTime.Now. |
NepaliDate.MinValue | NepaliDate | 1 Baisakh 1901 BS (approx 1844-04-13 AD). |
NepaliDate.MaxValue | NepaliDate | Last 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
| Method | Returns | Description |
|---|---|---|
SingleDay(NepaliDate date) | NepaliDateRange | Single day range. |
FromDayCount(NepaliDate start, int days) | NepaliDateRange | Range spanning specified days. Throws if days < 1. |
ForMonth(int year, int month) | NepaliDateRange | Complete Nepali month. |
ForFiscalYear(int fiscalYear) | NepaliDateRange | 1 Shrawan to last day of Ashadh. |
ForCalendarYear(int year) | NepaliDateRange | 1 Baisakh to last day of Chaitra. |
CurrentMonth() | NepaliDateRange | Current Nepali month. |
CurrentFiscalYear() | NepaliDateRange | Current Nepali fiscal year. |
CurrentCalendarYear() | NepaliDateRange | Current 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
| Member | Type | Description |
|---|---|---|
Start | NepaliDate | Start date (inclusive). |
End | NepaliDate | End date (inclusive). |
IsEmpty | bool | True when Start > End. |
Length | int | Number of days in the range. 0 if empty. |
Contains(NepaliDate) | bool | Whether the range contains the date. |
Contains(NepaliDateRange) | bool | Whether this range fully contains another. |
Overlaps(NepaliDateRange) | bool | Whether ranges share at least one date. |
IsAdjacentTo(NepaliDateRange) | bool | Whether 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
| Method | Returns | Description |
|---|---|---|
Intersect(NepaliDateRange) | NepaliDateRange | Dates present in both ranges. Empty if no overlap. |
Union(NepaliDateRange) | NepaliDateRange | All 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.
| Specifier | Output | Notes |
|---|---|---|
"d" or "G" | 2079/02/06 | Same as ToString(). |
"D" | Jestha 06, 2079 | Long date with leading zeros. |
"s" | 2079-02-06 | Sortable, dash separated. |
| custom pattern | varies | See 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
| Token | Description | Example |
|---|---|---|
yyyy | 4 digit year | 2079 |
yy | 2 digit year | 79 |
MMMM | Full month name | Jestha |
MMM | 3 letter abbreviation | Jes |
MM | Zero padded month | 02 |
M | Month number | 2 |
dd | Zero padded day | 06 |
d | Day number | 6 |
'...' | 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);
| Method | Signature | Description |
|---|---|---|
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):
day > 32: swap year and daymonthInMiddle: false: swap month and day firstmonth > 12andday < 13: swap month and dayyear < 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:
80becomes2080 - 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
| Method | Returns | Description |
|---|---|---|
FiscalYearStartDate(int yearOffset = 0) | NepaliDate | Start date (1 Shrawan) of the containing fiscal year. |
FiscalYearEndDate(int yearOffset = 0) | NepaliDate | End 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) | NepaliDate | Start of specified fiscal quarter. |
FiscalYearQuarterEndDate(FiscalYearQuarters q = Current, int yearOffset = 0) | NepaliDate | End 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
| Method | Returns | Description |
|---|---|---|
GetFiscalYearStartDate(int fiscalYear) | NepaliDate | 1 Shrawan of specified FY. |
GetFiscalYearEndDate(int fiscalYear) | NepaliDate | Last day of Ashadh of FY+1. |
GetFiscalYearStartAndEndDate(int fiscalYear) | (NepaliDate, NepaliDate) | Both dates. |
GetFiscalYearQuarterStartDate(int fiscalYear, int month) | NepaliDate | Quarter start. Month determines which quarter. |
GetFiscalYearQuarterEndDate(int fiscalYear, int month) | NepaliDate | Quarter 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
| Quarter | Months | Month Range |
|---|---|---|
| Q1 (First) | Shrawan to Ashoj | 4 to 6 |
| Q2 (Second) | Kartik to Poush | 7 to 9 |
| Q3 (Third) | Magh to Chaitra | 10 to 12 |
| Q4 (Fourth) | Baishakh to Ashadh | 1 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:
| Property | Type | Description |
|---|---|---|
TithiNp | string | Tithi in Nepali Devanagari. |
TithiEn | string | Tithi in English. |
IsPublicHoliday | bool | Public holiday flag. |
EventsNp | string[] | Event names in Nepali. |
EventsEn | string[] | 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
| Mode | JSON Output | When 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
| Method | Target | Description |
|---|---|---|
ConfigureForNepaliDate(this JsonSerializerOptions, bool useObjectFormat = false) | System.Text.Json | Registers converter. Returns the options for chaining. |
ConfigureForNepaliDate(this JsonSerializerSettings, bool useObjectFormat = false) | Newtonsoft.Json | Registers 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.
GetHashCodereturns 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
| Range | Coverage |
|---|---|
| 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 operations | Same 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