PersianCalendar无法将年/月/ 31(日)转换为标准日期

时间:2014-07-02 18:16:35

标签: c# datetime datetime-format persian datetime-conversion

我正在尝试将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

3 个答案:

答案 0 :(得分:6)

谢尔盖明确使用使用波斯日历的文化的解决方案应该有效,但另一个选择是使用我的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

答案 1 :(得分:2)

解释

这里有几个问题:

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

    CultureInfo.CurrentCulture与机器有关。但函数名称为ConvertPersianToEnglish,这意味着provider的{​​{1}}参数应设置为波斯日期格式提供者。

  2. 出于某种原因,伊朗CultureInfo实例将GregorianCalendar作为默认日历。此外,ParseExact中没有PersianCalendar。这很奇怪,因为OptionalCalendars命名空间包含System.Globalization类。

  3. 解决方案

    您可以在此处使用几种选项。

    解决方案1 ​​

    this article中,Babak Mahmoudi提供了一个帮助类,可以修复PersianCalendar个实例以接受CultureInfo。这个类里面的方法不是很温和(在实现方面)。但它包含PersianCalendar方法,这是非常无辜的。使用它,您的代码将如下所示:

    FixPersianDateTimeFormat

    解决方案2

    您可以自己解析字符串,然后使用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); } 。请参阅comecme的答案:How to convert Persian Calendar date string to DateTime?

答案 2 :(得分:1)

以下是将波斯日期转换为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();
    }