Link to home
Start Free TrialLog in
Avatar of askmeaks
askmeaks

asked on

Converting the International Date (AD) to Nepali Date (BS)

I'm currently developing a software in Nepali. The authorised date format for the office use in Nepal is Bikram Sambat. So, I need to have date facility in BS for the software. But it is quite tough as computer system do not accept BS dates. The main thing is that I need such a function in VB.Net that converts AD dates to BS dates and vice-versa. In a simple trend, while experimenting, I found that there is a approximate difference of 57 years, 8 months and 16 days between these dates. To obtain BS date, you need to add 57 years, 8 months and 16 days to AD date. But the main problem is that there may be a difference of +/- 3 days. I experimented with four dates and they are like below and they are in the format yyyy-mm-dd :
       AD                            BS
2004/12/02                   2061/08/17
2005/03/15                   2061/12/02
2003/04/14                   2060/01/01
2004/04/13                   2061/01/01

I tried a different approach, of storing english date and equivalent nepali date in a database and reading from it. But that made the application very bulky and it is really impossible to store all the BS dates in a database. What if someone wants to go back 120 years or forward 125 years.
       Please help me to solve this problem, because I have seen such an application which actually does the same job accuractly.
ASKER CERTIFIED SOLUTION
Avatar of arif_eqbal
arif_eqbal

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of platinumbay
platinumbay

Oops, I guess I can't read directions :)  I am researching this, let you know what I come up with.
Here is what the .NET framework supports natively, along with the conversion for November 27, 2004 in Gregorian date.

Gregorian:
        year = 2004
        month = 11
        day = 27
Hebrew:
        year = 5765
        month = 3
        day = 14
Julian:
        year = 2004
        month = 11
        day = 14
Japanese:
        year = 16
        month = 11
        day = 27
Hijri:
        year = 1425
        month = 10
        day = 15
Korean:
        year = 4337
        month = 11
        day = 27
Taiwan:
        year = 93
        month = 11
        day = 27
Thai Buddest:
        year = 2547
        month = 11
        day = 27

I doubt if any of these are correct, but I thought I would check.
I also found this, are you sure it isn't a fixed difference?

http://www.visualbasicforum.com/showthread.php?t=48624
I am still researching this, I may be getting closer to an answer.
Can you send me the database you created for the dates?  I want to test my algorithm.  mailto:platinumbay@hotmail.com?subject=Nepal Dates
Ok, I figured it out.  The problem is that the days in each month is different in Bikram Sambat.  Some months have 32 days, and the number of days per month changes every year.  Unfortunately, I could not find any calculations for the number of days per month for a given year, so I resorted to an embedded resource file with 2000 - 2080 nepali.

I also set up a baseline,
Gregorian 4/13/1997 = Nepali 1/1/2054

From that baseline, I determined the day difference between my variable date and the gregorian date.  I then set about to add the same number of days to the Nepali variable date, using a loop, and my resource xml.

The results were perfect, except for one error.  My method passed back a datetime, but give that the number of days per month exceed the Gregorian standard, some have 32, I got errors.  I am sure right off how to deal with that, other than to pass it back as a string.

Here are my results:

Gregorian       Nepali          Calculated      isMatch Month
---------------------------------------------------------------
4/15/2002       1/2/2059        2059/1/2        True    Baisakh
5/15/2002       2/1/2059        2059/2/1        True    Jestha
6/15/2002       3/1/2059        2059/3/1        True    Ashadh
7/15/2002       3/31/2059       2059/3/31       True    Ashadh
8/15/2002       4/30/2059       2059/4/30       True    Shrawan
9/15/2002       5/30/2059       2059/5/30       True    Bhadra
10/15/2002      6/29/2059       2059/6/29       True    Asoj
11/15/2002      7/29/2059       2059/7/29       True    Kartik
12/15/2002      8/29/2059       2059/8/29       True    Mangsir
1/15/2003       10/1/2059       2059/10/1       True    Magh
2/15/2003       11/3/2059       2059/11/3       True    Falgun
3/15/2003       12/1/2059       2059/12/1       True    Chaitra
4/15/2003       1/2/2060        2060/1/2        True    Baisakh
5/15/2003       2/1/2060        2060/2/1        True    Jestha
6/15/2003       3/1/2060        2060/3/1        True    Ashadh
7/15/2003       3/31/2060       2060/3/31       True    Ashadh
8/15/2003       4/30/2060       2060/4/30       True    Shrawan
9/15/2003       5/29/2060       2060/5/29       True    Bhadra
10/15/2003      6/28/2060       2060/6/28       True    Asoj
11/15/2003      7/29/2060       2060/7/29       True    Kartik
12/15/2003      8/29/2060       2060/8/29       True    Mangsir
1/15/2004       10/1/2060       2060/10/1       True    Magh
2/15/2004       11/3/2060       2060/11/3       True    Falgun
3/15/2004       12/2/2060       2060/12/2       True    Chaitra
4/15/2004       1/3/2061        2061/1/3        True    Baisakh
5/15/2004       2/2/2061        2061/2/2        True    Jestha
6/15/2004       3/1/2061        2061/3/1        True    Ashadh
7/15/2004       3/31/2061       2061/3/31       True    Ashadh
8/15/2004       error
9/15/2004       5/29/2061       2061/5/30       False   Bhadra
10/15/2004      6/29/2061       2061/6/29       True    Asoj
11/15/2004      7/30/2061       2061/7/30       True    Kartik
12/15/2004      8/30/2061       2061/8/30       True    Mangsir
1/15/2005       10/2/2061       2061/10/2       True    Magh
2/15/2005       11/4/2061       2061/11/4       True    Falgun
3/15/2005       12/2/2061       2061/12/2       True    Chaitra

I have one more error there as well (9/15/2004), but you can take a look at how to fix it.  It is probably just a typo in my string arrays.  Here is the code, it is rather long.

The XML file is set up like this:

     <Years>
         <Year ID="2000">30,32,31,32,31,30,30,30,29,30,29,31</Year>
         <Year ID="2001">31,31,32,31,31,31,30,29,30,29,30,30</Year>
         .... etc.

The worker class is:
#####################################################
Imports System.Globalization
Imports System.Xml
Imports System.Xml.XPath
Imports System.Reflection

    <Serializable()> _
    Public Class EE_NepaliCalendar
        Inherits Calendar

        <Serializable()> _
        Public Enum NepaliCalendarTypes
            Localized = 1
            USEnglish = 2
        End Enum

        ' Methods
        Shared Sub New()
            MonthNames = New String(11) {"Baisakh", "Jestha", "Ashadh", "Shrawan", "Bhadra", "Asoj", "Kartik", "Mangsir", "Poush", "Magh", "Falgun", "Chaitra"}
            m_defaultInstance = Nothing
        End Sub

        Public Sub New()
            Me.New(NepaliCalendarTypes.Localized)
        End Sub

        Public Sub New(ByVal type As NepaliCalendarTypes)
            Me.m_type = type
        End Sub

        Public Overrides Function AddMonths(ByVal time As DateTime, ByVal months As Integer) As DateTime
            If ((months < -120000) OrElse (months > 120000)) Then
                Throw New ArgumentOutOfRangeException("months", String.Format("Valid values are between {0} and {1}, inclusive.", -120000, 120000))
            End If
            Dim num1 As Integer = Me.GetDatePart(time.Ticks, 0)
            Dim num2 As Integer = Me.GetDatePart(time.Ticks, 2)
            Dim num3 As Integer = Me.GetDatePart(time.Ticks, 3)
            Dim num4 As Integer = ((num2 - 1) + months)
            If (num4 >= 0) Then
                num2 = ((num4 Mod 12) + 1)
                num1 = CInt(num1 + (num4 / 12))
            Else
                num2 = (12 + ((num4 + 1) Mod 12))
                num1 = CInt(num1 + ((num4 - 11) / 12))
            End If
            Dim numArray1 As Integer()
            'If ((((num1 Mod 4) = 0) AndAlso (((num1 Mod 100) <> 0) OrElse ((num1 Mod 400) = 0)))) Then
            '    numArray1 = DaysToMonth366
            'Else
            numArray1 = Me.DaysToMonth(time.Year)
            'End If
            Dim num5 As Integer = (numArray1(num2) - numArray1((num2 - 1)))
            If (num3 > num5) Then
                num3 = num5
            End If
            Return New DateTime((Me.DateToTicks(num1, num2, num3) + (time.Ticks Mod 864000000000)))
        End Function

        Public Overrides Function AddWeeks(ByVal time As DateTime, ByVal weeks As Integer) As DateTime
            Return Me.AddDays(time, (weeks * 7))
        End Function

        Public Overrides Function AddYears(ByVal time As DateTime, ByVal years As Integer) As DateTime
            Return Me.AddMonths(time, (years * 12))
        End Function

        Friend Overridable Function DateToTicks(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer) As Long
            Return (GetAbsoluteDate(year, month, day) * 864000000000)
        End Function

        Shared Function GetMonthName(ByVal month As Integer) As String
            If ((month < 1) OrElse (month > 12)) Then
                Throw New ArgumentOutOfRangeException("month", "Month must be between one and twelve.")
            End If
            Return MonthNames(month - 1)
        End Function

        Friend Shared Function GetAbsoluteDate(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer) As Long
            If (((year >= 1) AndAlso (year <= 9999)) AndAlso ((month >= 1) AndAlso (month <= 12))) Then
                Dim numArray1 As Integer()
                'If ((((year Mod 4) = 0) AndAlso (((year Mod 100) <> 0) OrElse ((year Mod 400) = 0)))) Then
                'numArray1 = DaysToMonth
                'Else
                numArray1 = DaysToMonth(year)
                'End If
                If ((day >= 1) AndAlso (day <= (numArray1(month) - numArray1((month - 1))))) Then
                    Dim num1 As Integer = (year - 1)
                    Dim num2 As Integer = CInt(((((((num1 * 365) + (num1 / 4)) - (num1 / 100)) + (num1 / 400)) + numArray1((month - 1))) + day) - 1)
                    Return CType(num2, Long)
                End If
            End If
            Throw New ArgumentOutOfRangeException("Year, Month, and Day parameters describe an unrepresentable DateTime.")
        End Function

        Friend Overridable Function GetDatePart(ByVal ticks As Long, ByVal part As Integer) As Integer
            Dim num1 As Integer = CType((ticks / 864000000000), Integer)
            Dim num2 As Integer = CInt(num1 / 146097)
            num1 = (num1 - (num2 * 146097))
            Dim num3 As Integer = CInt(num1 / 36524)
            If (num3 = 4) Then
                num3 = 3
            End If
            num1 = (num1 - (num3 * 36524))
            Dim num4 As Integer = CInt(num1 / 1461)
            num1 = (num1 - (num4 * 1461))
            Dim num5 As Integer = CInt(num1 / 365)
            If (num5 = 4) Then
                num5 = 3
            End If
            If (part = 0) Then
                Return (((((num2 * 400) + (num3 * 100)) + (num4 * 4)) + num5) + 1)
            End If
            num1 = (num1 - (num5 * 365))
            If (part = 1) Then
                Return (num1 + 1)
            End If
            Dim flag1 As Boolean = ((num5 = 3) AndAlso ((num4 <> 24) OrElse (num3 = 3)))
            Dim numArray1 As Integer()
            'If flag1 Then
            '    numArray1 = DaysToMonth366
            'Else
            numArray1 = Me.DaysToMonth(New DateTime(ticks).Year) '(New TimeSpan(ticks).TotalDays / 265)
            'End If
            Dim num6 As Integer = (num1 >> 6)
            Do While (num1 >= numArray1(num6))
                num6 += 1
            Loop
            If (part = 2) Then
                Return num6
            End If
            Return ((num1 - numArray1((num6 - 1))) + 1)
        End Function

        Public Overrides Function GetDayOfMonth(ByVal time As DateTime) As Integer
            Return Me.GetDatePart(time.Ticks, 3)
        End Function

        Public Overrides Function GetDayOfWeek(ByVal time As DateTime) As DayOfWeek
            Return CType(((CType((time.Ticks / 864000000000), Integer) + 1) Mod 7), DayOfWeek)
        End Function

        Public Overrides Function GetDayOfYear(ByVal time As DateTime) As Integer
            Return Me.GetDatePart(time.Ticks, 1)
        End Function

        Public Overloads Overrides Function GetDaysInMonth(ByVal year As Integer, ByVal month As Integer) As Integer ', ByVal era As Integer) As Integer
            'If ((era <> 0) AndAlso (era <> 1)) Then
            'Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((month < 1) OrElse (month > 12)) Then
                Throw New ArgumentOutOfRangeException("month", "Month must be between one and twelve.")
            End If
            Dim numArray1 As Integer()
            'If ((((year Mod 4) = 0) AndAlso (((year Mod 100) <> 0) OrElse ((year Mod 400) = 0)))) Then
            numArray1 = Me.DaysToMonth(year)
            'Else
            '    numArray1 = DaysToMonth365
            'End If
            Return (numArray1(month) - numArray1((month - 1)))
        End Function

        Public Overloads Overrides Function GetDaysInYear(ByVal year As Integer) As Integer ', ByVal era As Integer) As Integer
            'If ((era <> 0) AndAlso (era <> 1)) Then
            'Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((year >= 1) AndAlso (year <= 9999)) Then
                If (((year Mod 4) = 0) AndAlso (((year Mod 100) <> 0) OrElse ((year Mod 400) = 0))) Then
                    Return 366
                End If
                Return 365
            End If
            Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
        End Function

        Friend Shared Function GetDefaultInstance() As Calendar
            If (m_defaultInstance Is Nothing) Then
                m_defaultInstance = New NepaliCalendar
            End If
            Return m_defaultInstance
        End Function

        'Public Overrides Function GetEra(ByVal time As DateTime) As Integer
        '    Return 1
        'End Function

        Public Overrides Function GetMonth(ByVal time As DateTime) As Integer
            Return Me.GetDatePart(time.Ticks, 2)
        End Function

        Public Overloads Overrides Function GetMonthsInYear(ByVal year As Integer) As Integer ', ByVal era As Integer) As Integer
            'If ((era <> 0) AndAlso (era <> 1)) Then
            '    Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((year < 1) OrElse (year > 9999)) Then
                Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
            End If
            Return 12
        End Function

        Public Overrides Function GetYear(ByVal time As DateTime) As Integer
            Return Me.GetDatePart(time.Ticks, 0)
        End Function

        Public Overloads Overrides Function IsLeapDay(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer) As Boolean ', ByVal era As Integer) As Boolean
            'If ((era <> 0) AndAlso (era <> 1)) Then
            '    Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((year < 1) OrElse (year > 9999)) Then
                Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
            End If
            If ((month < 1) OrElse (month > 12)) Then
                Throw New ArgumentOutOfRangeException("month", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 12))
            End If
            If ((day < 1) OrElse (day > Me.GetDaysInMonth(year, month))) Then
                Throw New ArgumentOutOfRangeException("day", String.Format("Valid values are between {0} and {1}, inclusive.", 1, Me.GetDaysInMonth(year, month)))
            End If
            If (Me.IsLeapYear(year) AndAlso ((month = 12) AndAlso (day = 31))) Then
                Return True
            End If
            Return False
        End Function

        Public Overloads Overrides Function IsLeapMonth(ByVal year As Integer, ByVal month As Integer) As Boolean ', ByVal era As Integer) As Boolean
            'If ((era <> 0) AndAlso (era <> 1)) Then
            '    Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((year < 1) OrElse (year > 9999)) Then
                Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
            End If
            If ((month < 1) OrElse (month > 12)) Then
                Throw New ArgumentOutOfRangeException("month", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 12))
            End If
            Return False
        End Function

        Public Overloads Overrides Function IsLeapYear(ByVal year As Integer) As Boolean ', ByVal era As Integer) As Boolean
            'If ((era <> 0) AndAlso (era <> 1)) Then
            '    Throw New ArgumentException("Era value was not valid.")
            'End If
            If ((year >= 1) AndAlso (year <= 9999)) Then
                If ((year Mod 4) <> 0) Then
                    Return False
                End If
                If ((year Mod 100) = 0) Then
                    Return ((year Mod 400) = 0)
                End If
                Return True
            End If
            Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
        End Function

        Public Overloads Overrides Function ToDateTime(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer, ByVal hour As Integer, ByVal minute As Integer, ByVal second As Integer, ByVal millisecond As Integer) As DateTime ', ByVal era As Integer) As DateTime
            'If ((era <> 0) AndAlso (era <> 1)) Then
            '    Throw New ArgumentException("Era value was not valid.")
            'End If
            Return New DateTime(year, month, day, hour, minute, second, millisecond)
        End Function

        Public Overrides Function ToFourDigitYear(ByVal year As Integer) As Integer
            If (year > 9999) Then
                Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 1, 9999))
            End If
            Return MyBase.ToFourDigitYear(year)
        End Function

        Public Function ConvertFromGregorian(ByVal time As Date) As String
            Dim enteredDiff As Integer = CInt(DateDiff(DateInterval.Day, sgDate, time))

            Dim nYear As Integer = snDate.Year
            Dim nMonth As Integer = snDate.Month
            Dim nDay As Integer = snDate.Day

            If enteredDiff >= 0 Then
                Do While enteredDiff > 0
                    If nDay <> DaysInMonth(nYear, nMonth - 1) Then
                        Dim daySub As Integer = DaysInMonth(nYear, nMonth - 1) - nDay
                        If daySub > enteredDiff Then
                            nDay += enteredDiff
                            enteredDiff = 0
                        Else
                            nDay += daySub
                            enteredDiff -= daySub
                        End If
                    Else ' is last day of month
                        If enteredDiff >= 1 Then
                            If nMonth = 12 Then
                                nYear += 1
                                nMonth = 1
                                nDay = 1
                                enteredDiff -= 1
                            Else
                                nMonth += 1
                                nDay = 1
                                enteredDiff -= 1
                            End If
                        End If
                    End If
                Loop
            Else ' need to go back in time
                Throw New Exception("Year must be between 2000 and 2080 Nepali inclusive.")
            End If

            Return Convert.ToString(nYear & "/" & nMonth & "/" & nDay)
        End Function

        ' Properties
        Public Overridable Property CalendarType() As NepaliCalendarTypes
            Get
                Return Me.m_type
            End Get
            Set(ByVal value As NepaliCalendarTypes)
                Me.m_type = value
            End Set
        End Property

        'Public Overrides ReadOnly Property Eras() As Integer()
        '    Get
        '        Return New Integer() {1}
        '    End Get
        'End Property

        Friend ReadOnly Property ID() As Integer
            Get
                Return CType(Me.m_type, Integer)
            End Get
        End Property

        Public ReadOnly Property sgDate() As Date
            Get
                Return New Date(1997, 4, 13)
            End Get
        End Property

        Public ReadOnly Property snDate() As Date
            Get
                Return New Date(2054, 1, 1)
            End Get
        End Property

        Public Overrides Property TwoDigitYearMax() As Integer
            Get
                If (Me.TwoDigitYearMax = -1) Then
                    Me.TwoDigitYearMax = DEFAULT_TWO_DIGIT_YEAR_MAX '2084 'GetSystemTwoDigitYearSetting(Me.ID, 2029)
                End If
                Return Me.TwoDigitYearMax
            End Get
            Set(ByVal value As Integer)
                If ((value < 100) OrElse (value > 9999)) Then
                    Throw New ArgumentOutOfRangeException("year", String.Format("Valid values are between {0} and {1}, inclusive.", 100, 9999))
                End If
                Me.TwoDigitYearMax = value
            End Set
        End Property

        Public Shared ReadOnly Property DaysInMonth(ByVal year As Integer, ByVal i As Integer) As Integer
            Get
                Dim xmlNI As XmlNode = GetXML(year)

                Dim rowValues As String() = (xmlNI.InnerText).Split(","c)
                'Dim intRowValues As Integer() = New Integer(rowValue.Length - 1) {}
                'For x As Integer = 0 To rowValue.Length - 1
                'intRowValues(x) = CInt(rowValue(x))
                'Next

                'Dim objReturn As Integer
                'Dim prev As Integer = 0
                'objReturn(0) = 0
                'For x As Integer = 1 To intRowValues.Length - 1
                '    objReturn(x) = intRowValues(x) + prev
                '    prev = objReturn(x)
                'Next

                Return CInt(rowValues(i))
            End Get
        End Property

        Public Shared ReadOnly Property DaysToMonth(ByVal year As Integer, ByVal month As Integer) As Integer
            Get
                Return DaysToMonth(year)(month)
            End Get
        End Property

        Public Shared ReadOnly Property DaysToMonth(ByVal year As Integer) As Integer()
            Get
                Dim xmlNI As XmlNode = GetXML(year)

                Dim rowValue As String() = ("0," & xmlNI.InnerText).Split(","c)
                Dim intRowValues As Integer() = New Integer(rowValue.Length - 1) {}
                For x As Integer = 0 To rowValue.Length - 1
                    intRowValues(x) = CInt(rowValue(x))
                Next

                Dim objReturn As Integer()
                Dim prev As Integer = 0
                objReturn(0) = 0
                For x As Integer = 1 To intRowValues.Length - 1
                    objReturn(x) = intRowValues(x) + prev
                    prev = objReturn(x)
                Next

                Return objReturn
            End Get
        End Property

        Private Shared Function GetXML(ByVal year As Integer) As XmlNode
            Dim res As String = "ESMEngine.NepaliMonthDays.xml"
            Dim sel As String = "/Years/Year[@ID=" & year & "]"

            Dim xmlDoc As New XmlDocument

            Dim objAs As [Assembly] = [Assembly].GetExecutingAssembly
            xmlDoc.Load(objAs.GetManifestResourceStream(res))

            Dim root As XmlElement = xmlDoc.DocumentElement
            Dim ret As XmlNode = root.SelectSingleNode(sel)
            Return ret
        End Function

        ' Fields
        Friend Const DatePartDay As Integer = 3
        Friend Const DatePartDayOfYear As Integer = 1
        Friend Const DatePartMonth As Integer = 2
        Friend Const DatePartYear As Integer = 0
        Friend Const DaysDiff As Integer = 20348
        Friend Shared ReadOnly MonthNames As String()
        Private Const DEFAULT_TWO_DIGIT_YEAR_MIN As Integer = 2000
        Private Const DEFAULT_TWO_DIGIT_YEAR_MAX As Integer = 2080
        Friend Shared m_defaultInstance As Calendar
        Friend m_type As NepaliCalendarTypes
        Friend Const MaxYear As Integer = 9999

        <Obsolete("Era is not used in this class")> _
        Public Overrides ReadOnly Property Eras() As Integer()
            Get

            End Get
        End Property

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function GetDaysInMonth(ByVal year As Integer, ByVal month As Integer, ByVal era As Integer) As Integer

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function GetDaysInYear(ByVal year As Integer, ByVal era As Integer) As Integer

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overrides Function GetEra(ByVal time As Date) As Integer

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function GetMonthsInYear(ByVal year As Integer, ByVal era As Integer) As Integer

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function IsLeapDay(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer, ByVal era As Integer) As Boolean

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function IsLeapMonth(ByVal year As Integer, ByVal month As Integer, ByVal era As Integer) As Boolean

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function IsLeapYear(ByVal year As Integer, ByVal era As Integer) As Boolean

        End Function

        <Obsolete("Era is not used in this class")> _
        Public Overloads Overrides Function ToDateTime(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer, ByVal hour As Integer, ByVal minute As Integer, ByVal second As Integer, ByVal millisecond As Integer, ByVal era As Integer) As Date

        End Function
    End Class
############################################

And the worker class is here:
############################################
Imports System.Globalization
Imports System.Globalization.Calendar

Module Module1
    Sub Main()
        Dim objNCal As New NepaliCalendar

        Console.WriteLine("Gregorian" & vbTab & "Nepali" & vbTab & vbTab & "Calculated" & vbTab & "isMatch" & vbTab & "Month")
        Console.WriteLine("--------------------------------------------------------------------------------")

        Dim objGregDates As String() = New String(35) _
            {"4/15/2002", "5/15/2002", "6/15/2002", "7/15/2002", "8/15/2002", "9/15/2002", _
            "10/15/2002", "11/15/2002", "12/15/2002", "1/15/2003", "2/15/2003", "3/15/2003", _
            "4/15/2003", "5/15/2003", "6/15/2003", "7/15/2003", "8/15/2003", "9/15/2003", _
            "10/15/2003", "11/15/2003", "12/15/2003", "1/15/2004", "2/15/2004", "3/15/2004", _
            "4/15/2004", "5/15/2004", "6/15/2004", "7/15/2004", "8/15/2004", "9/15/2004", _
            "10/15/2004", "11/15/2004", "12/15/2004", "1/15/2005", "2/15/2005", "3/15/2005"}
        Dim objNepaDates As String() = New String(35) _
            {"1/2/2059", "2/1/2059", "3/1/2059", "3/31/2059", "4/30/2059", "5/30/2059", _
            "6/29/2059", "7/29/2059", "8/29/2059", "10/1/2059", "11/3/2059", "12/1/2059", _
            "1/2/2060", "2/1/2060", "3/1/2060", "3/31/2060", "4/30/2060", "5/29/2060", _
            "6/28/2060", "7/29/2060", "8/29/2060", "10/1/2060", "11/3/2060", "12/2/2060", _
            "1/3/2061", "2/2/2061", "3/1/2061", "3/31/2061", "4/31/2061", "5/29/2061", _
            "6/29/2061", "7/30/2061", "8/30/2061", "10/2/2061", "11/4/2061", "12/2/2061"}

        For x As Integer = 0 To objGregDates.Length - 1
            Dim d20713 As Date = CType(objGregDates(x), Date).AddDays(20713)
            Dim dMonthCur As Integer = d20713.Month
            Dim dMonthPre As Integer = d20713.AddMonths(-1).Month
            Dim gDate As Date = CType(objGregDates(x), Date)
            Dim gMonthCur As Integer = gDate.Month
            Dim gMonthPre As Integer = gDate.AddMonths(-1).Month

            Try
                Dim dDiff As String = DateDiff(DateInterval.Day, gDate, CType(objNepaDates(x), Date)).ToString
                Dim nepDate As String = objNCal.ConvertFromGregorian(Convert.ToDateTime(objGregDates(x)))
                Dim gregDate As DateTime = Convert.ToDateTime(objNepaDates(x))

                Console.WriteLine(objGregDates(x) & _
                    vbTab & objNepaDates(x) & _
                    vbTab & nepDate & _
                    vbTab & Convert.ToString(IIf(gregDate = Convert.ToDateTime(objNCal.ConvertFromGregorian(Convert.ToDateTime(objGregDates(x)))), True, False)) & _
                    vbTab & objNCal.GetMonthName(Convert.ToInt32(nepDate.Split("/"c).GetValue(1))))
            Catch
                Console.WriteLine(objGregDates(x) & vbTab & _
                    "error")
            End Try
        Next

        Console.WriteLine()
        Console.WriteLine("--------------------------------------------------------------------------------")
        Console.WriteLine()
        Console.WriteLine("Press <enter> to exit...")
        Console.ReadLine()
    End Sub
###################################

btw, IS there a way to calculate how many days per given month there are in a given year?
The .NET framework doesn't support this type of calendar.  I don't think arif_eqbal's answer would be helpful in this situation.  Also, the comment you had linked to for me is not the correct answer, I would use {https://www.experts-exchange.com/questions/21215404/Converting-the-International-Date-AD-to-Nepali-Date-BS.html#12813364} as that is my correct answer.
btw - How did you do that link?  {http:#12813364}  Maybe this will work.
Haha, cool.  I was thinking about it too much.
Just try

http://blog.kiranpantha.com.np/2016/07/12/ad-to-bs-coverter-nepali-to-english-date-conveter-vb-net/

100% Accurate conversion till 2090 BS

And for PHP as well at

http://blog.kiranpantha.com.np/2016/07/11/ad-to-bs-coverter-nepali-to-english-date-conveter-php/

Hope this helps you

or download .dll library by us and import in other apps