Reputation: 144
I have a problem converting Gregorian calendar dates to Persian(Hijri calendar) using default system "en-GB" culture in my ASP.NET MVC Application. I used the globalization tag in my web.config so the default culture would be "en-GB":
<system.web>
...
<globalization uiCulture="en-GB" culture="en-GB" />
...
</system.web>
The conversion will happen for any date except for these exact dates that I listed them below and will throw "String was not recognized as a valid DateTime.” error.
The exact dates that will throw exception are:
A part of my sample code:
using System.Globalization;
...
...
public static PersianCalendar PC = new PersianCalendar();
...
//I'm using this method for conversion
public static DateTime GregorianToPersian(DateTime date)
{
...
string stringDate = string.Format("{0}/{1}/{2} {3}:{4}:{5}"
, PC.GetDayOfMonth(date), PC.GetMonth(date), PC.GetYear(date)
, PC.GetHour(date), PC.GetMinute(date), PC.GetSecond(date));
return DateTime.Parse(stringDate); //error!
}
Hope you guys can help me out with. Thanks.
Upvotes: 0
Views: 967
Reputation: 1502556
Leaving the parsing error aside, this isn't going to achieve what you want to achieve. A DateTime
value is always in the Gregorian calendar - trying to parse 31/04/1396 as a DateTime
is never going to work because it's not a valid date in the Gregorian calendar.
I would advise using my Noda Time library for this instead, where appropriate types "know" which calendar system they're part of, and you can explicitly convert between them. For example:
// The Gregorian calendar is used implicitly
LocalDate gregorian = new LocalDate(2017, 7, 22);
LocalDate persian = gregorian.WithCalendar(CalendarSystem.PersianArithmetic);
Console.WriteLine($"{persian:yyyy-MM-dd}");
Output:
1396-04-31
You can then do sensible arithmetic with persian
such as adding a month etc, which would give the wrong answer if you tried doing it with DateTime
naively. (You could use Calendar.AddMonths
etc, but you'd need to remember to do so everywhere.)
Upvotes: 8
Reputation: 21
DateTime
object is in Gregorian calendar (from MSDN DateTime specification ) :
The DateTime value type represents dates and times with values ranging from 00:00:00 (midnight), January 1, 0001 Anno Domini (Common Era) through 11:59:59 P.M., December 31, 9999 A.D. (C.E.) in the Gregorian calendar.
Your solution is valid until target days are in range of target month in Gregorian Calendar.
(Un)fortunely DateTime
struct is sealed which mean, you can't override it.
Because of this limits, I suggest make some kind of PersianDateTimeUtility
class, where would be logic of parsing object as DateTime
to specified type (for example String
), comparing dates etc.
There are some frameworks for this purpose, but i haven't tested them so I will not describe them.
Upvotes: 1