Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PersianCalendar can't convert year/month/31(day) to standard date

I am trying to convert persianDate to standarddate .

public DateTime ConvertPersianToEnglish(string persianDate)
{
    string[] formats = { "yyyy/MM/dd", "yyyy/M/d", "yyyy/MM/d", "yyyy/M/dd" };
    DateTime d1 = DateTime.ParseExact(persianDate, formats,
                                      CultureInfo.CurrentCulture, DateTimeStyles.None);
    PersianCalendar persian_date = new PersianCalendar();
    DateTime dt = persian_date.ToDateTime(d1.Year, d1.Month, d1.Day, 0, 0, 0, 0, 0);
    return dt;
}

The Persiandate has formats like this: 1392/10/12(Year/month/day)

In my application i am trying to convert Year/month/31 to standard time but i got this error :

{System.FormatException: String was not recognized as a valid DateTime.
   at System.DateTimeParse.ParseExactMultiple(String s, String[] formats, DateTimeFormatInfo dtfi, DateTimeStyles style)

The exactly value that i get the error is 1393/04/31

like image 776
Ehsan Akbar Avatar asked Jul 02 '14 18:07

Ehsan Akbar


1 Answers

Sergey's solution of explicitly using a culture which uses the Persian calendar should work, but another option is to use my Noda Time library:

using System;
using System.Globalization;
using NodaTime;
using NodaTime.Text;

public class Test
{
    public static void Main()        
    {
        // Providing the sample date to the pattern tells it which
        // calendar to use.

        // Noda Time 2.0 uses a property instead of a method.
        // var calendar = CalendarSystem.Persian;           // 2.0+
        var calendar = CalendarSystem.GetPersianCalendar(); // 1.x

        LocalDate sampleDate = new LocalDate(1392, 10, 12, calendar);
        var pattern = LocalDatePattern.Create(
            "yyyy/M/d", CultureInfo.InvariantCulture, sampleDate);
        string text = "1393/04/31";
        ParseResult<LocalDate> parseResult = pattern.Parse(text);
        if (parseResult.Success)
        {
            LocalDate date = parseResult.Value;
            // Use the date
        }
    }    
}

Unlike DateTime, the LocalDate result here knows that it's just a date (so won't offer time aspects) and also knows which calendar system it's in (so you don't need to keep calling methods like calendar.GetYear(date) to get specific parts).

Note that a parse pattern of yyyy/M/d will be able to parse values with leading zeroes, so you don't need multiple patterns. If you know the format always will have two digits for the month and day, however, I'd explicitly use yyyy/MM/dd instead.

like image 139
Jon Skeet Avatar answered Oct 03 '22 01:10

Jon Skeet