Персидский календарь не может преобразовать год/месяц/31 (день) в стандартную дату

Я пытаюсь преобразовать persianDate в 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;
}

Persiandate имеет такие форматы: 1392/10/12(Year/month/day)

В моем приложении я пытаюсь преобразовать Year/month/31 в стандартное время, но я получил эту ошибку:

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

Точное значение, которое я получаю при ошибке, равно 1393/04/31


person Ehsan Akbar    schedule 02.07.2014    source источник
comment
В месяце 31 день?   -  person Bit    schedule 02.07.2014
comment
Если вы имеете в виду на персидском языке, то да. В некоторых месяцах на персидском языке 31 день.   -  person Ehsan Akbar    schedule 02.07.2014
comment
Но разве месяц вы пытаетесь конвертировать? Строка не была распознана как допустимая дата и время. Действительное ключевое слово здесь.   -  person Bit    schedule 02.07.2014
comment
Да, время, когда я пытаюсь конвертировать, это 1393/04/31›, как я уже упоминал в своем вопросе.   -  person Ehsan Akbar    schedule 02.07.2014
comment
См. это, это должно помочь stackoverflow.com/questions/10655116/   -  person Bit    schedule 02.07.2014
comment
этот тоже полезен: stackoverflow.com/a/9491805/704749   -  person Ashkan Ghodrat    schedule 20.01.2015


Ответы (3)


Решение Сергея по явному использованию культуры, использующей персидский календарь, должно работать, но другой вариант — использовать мою библиотеку Noda Time:

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
        }
    }    
}

В отличие от DateTime, результат LocalDate здесь знает, что это просто дата (поэтому не будет предлагать аспекты времени), а также знает, в какой календарной системе он находится (поэтому вам не нужно продолжать вызывать такие методы, как calendar.GetYear(date), чтобы получить определенные части).

Обратите внимание, что шаблон синтаксического анализа yyyy/M/d сможет анализировать значения с ведущими нулями, поэтому вам не нужно несколько шаблонов. Если вы знаете, что формат всегда будет иметь две цифры для месяца и дня, я бы явно использовал вместо этого yyyy/MM/dd.

person Jon Skeet    schedule 28.08.2014

Объяснение

Здесь есть пара проблем:

  1. DateTime d1 = DateTime.ParseExact(persianDate, formats,
                                      CultureInfo.CurrentCulture, DateTimeStyles.None);
    

    CultureInfo.CurrentCulture зависит от компьютера. Но имя функции — ConvertPersianToEnglish, что означает, что аргумент provider функции ParseExact должен быть установлен на поставщика персидского формата даты.

  2. По какой-то причине иранские экземпляры CultureInfo имеют GregorianCalendar в качестве календаря по умолчанию. Более того, у него нет PersianCalendar в OptionalCalendars. Что странно, потому что пространство имен System.Globalization включает класс PersianCalendar.

Решения

Есть пара вариантов, которые вы можете использовать здесь.

Решение 1

В этой статье Бабак Mahmoudi предоставляет вспомогательный класс, который может исправить экземпляр CultureInfo, чтобы принять PersianCalendar. Методы внутри этого класса не очень мягкие (с точки зрения реализации). Но он содержит метод FixPersianDateTimeFormat, который совершенно невинен. Используя его, ваш код будет выглядеть так:

public static DateTime ConvertPersianToEnglish(string persianDate)
{
    string[] formats = { "yyyy/MM/dd", "yyyy/M/d", "yyyy/MM/d", "yyyy/M/dd" };
    DateTimeFormatInfo persianDateTimeFormatInfo = new CultureInfo("fa-Ir").DateTimeFormat;
    PersianCultureHelper.FixPersianDateTimeFormat(persianDateTimeFormatInfo, true);
    return DateTime.ParseExact(persianDate, formats, persianDateTimeFormatInfo, DateTimeStyles.None);
}

Решение 2

Вы можете самостоятельно проанализировать строку, а затем использовать PersianCalendar.ToDateTime. См. ответ comecme здесь: Как преобразовать строку даты персидского календаря в DateTime?

person Sergey Krusch    schedule 02.07.2014

Вот простой способ конвертировать персидскую дату в DateTime:

    public DateTime GetGregorianDate(string persianDate)
    {
        PersianCalendar persian_date = new PersianCalendar();
        var dateParts = GetDateParts(persianDate);
        DateTime dt = persian_date.ToDateTime(dateParts[0], dateParts[1], dateParts[2], 0, 0, 0, 0, 0);
        return dt;
    }

    public int[] GetDateParts(string persianDate)
    {
        return persianDate.Split('/').Select(datePart => int.Parse(datePart)).ToArray();
    }
person brz    schedule 30.08.2014