简体   繁体   中英

"String was not recognized as a valid DateTime.” error occurs for some exact dates

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:

  1. 22/07/(any year)
  2. 22/09/(any year)
  3. 19/05/(any year)
  4. 20/05/(any year)
  5. 21/05/(any year)

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.

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.)

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 PM, December 31, 9999 AD (CE) 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM