String format to convert datetime causes an error

I try to convert persiandate to standard date.So my persian date has these formats (it means the user can enter these formats :

1392/1/1
1392/01/01
1392/01/1
1392/1/01

So i write a function to convert my persian date to standard date like this :

 public DateTime ConvertPeersianToEnglish(string persianDate)
        {
            string[] formats = { "yyyy/MM/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;
        }

But these function just can handle this formats 1392/01/01 and of the users enter other formats i got this error:

String was not recognized as a valid DateTime

Best regards

Jon Skeet
people
quotationmark

You're specifying MM and dd in your format, which require two digits. Just specify "yyyy/M/d" as the format - that should handle both 1 and 2-digit day/month values. (You can specify multiple formats instead, but in this case you don't need to. You might want to consider doing that just to be clear, but M and d will both handle two digit values with a leading zero with no problems.

Note that if you're just specifying a single format, you don't need to put it in an array. You can just use:

string format = "yyyy/M/d";
DateTime d1 = DateTime.ParseExact(persianDate, format,
                                  CultureInfo.CurrentCulture,
                                  DateTimeStyles.None);

However:

  • I suspect you want to specify the invariant culture, given that you don't want this value to affected by the culture
  • Your current approach of converting a date to the Persian calendar will simply not work.

Currently you're implicitly validating that the date given is in the Gregorian calendar, but then you're treating it as a Persian date. For example, 1392/02/30 is a valid Persian date, but not a valid Gregorian date.

Instead, you should use a culture which already uses the Persian calendar, and then specify that as the culture in your DateTime.ParseExact call. Then you don't need to do anything else afterwards.

You might alternatively want to consider using my Noda Time library - version 1.3 which includes the Persian calendar should be released in the next day or two.

Sample code using Noda Time:

var persian = CalendarSystem.GetPersianCalendar();
// The pattern takes the calendar system from the default value
var sampleDate = new LocalDate(1392, 1, 1, persian);
var pattern = LocalDatePattern.CreateWithInvariantCulture("yyyy/M/d")
                              .WithTemplateValue(sampleDate);
var date = pattern.Parse("1392/02/30").Value;
Console.WriteLine(LocalDatePattern.IsoPattern.Format(date));

people

See more on this question at Stackoverflow