15

I use the function below to convert Gregorian dates to Persian dates, but I've been unable to write a function to do the reverse conversion. I want a function that converts a Persian date (a string like "1390/07/18 12:00:00") into a Georgian date.

public static string GetPdate(DateTime _EnDate)
{
    PersianCalendar pcalendar = new PersianCalendar();
    string Pdate = pcalendar.GetYear(_EnDate).ToString("0000") + "/" +
       pcalendar.GetMonth(_EnDate).ToString("00") + "/" +
       pcalendar.GetDayOfMonth(_EnDate).ToString("00") + " " +
           pcalendar.GetHour(_EnDate).ToString("00") + ":" +
           pcalendar.GetMinute(_EnDate).ToString("00") + ":" +
           pcalendar.GetSecond(_EnDate).ToString("00");

    return Pdate;
}
mjyazdani
  • 2,110
  • 6
  • 33
  • 64

9 Answers9

13

DateTime is always in the Gregorian calendar, effectively. Even if you create an instance specifying a dfferent calendar, the values returned by the Day, Month, Year etc properties are in the Gregorian calendar.

As an example, take the start of the Islamic calendar:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        DateTime epoch = new DateTime(1, 1, 1, new HijriCalendar());
        Console.WriteLine(epoch.Year);  // 622
        Console.WriteLine(epoch.Month); // 7
        Console.WriteLine(epoch.Day);   // 18
    }
}

It's not clear how you're creating the input to this method, or whether you should really be converting it to a string format. (Or why you're not using the built-in string formatters.)

It could be that you can just use:

public static string FormatDateTimeAsGregorian(DateTime input)
{
    return input.ToString("yyyy'/'MM'/'dd' 'HH':'mm':'ss",
                          CultureInfo.InvariantCulture);
}

That will work for any DateTime which has been created appropriately - but we don't know what you've done before this.

Sample:

using System;
using System.Globalization;

class Test
{
    static void Main()
    {
        DateTime epoch = new DateTime(1, 1, 1, new PersianCalendar());
        // Prints 0622/03/21 00:00:00
        Console.WriteLine(FormatDateTimeAsGregorian(epoch));
    }

    public static string FormatDateTimeAsGregorian(DateTime input)
    {
        return input.ToString("yyyy'/'MM'/'dd' 'HH':'mm':'ss",
                              CultureInfo.InvariantCulture);
    }
}

Now if you're not specifying the calendar when you create the DateTime, then you're not really creating a Persian date at all.

If you want dates that keep track of their calendar system, you can use my Noda Time project, which now supports the Persian calendar:

// In Noda Time 2.0 you'd just use CalendarSystem.Persian
var persianDate = new LocalDate(1390, 7, 18, CalendarSystem.GetPersianCalendar());
var gregorianDate = persianDate.WithCalendar(CalendarSystem.Iso);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I have a persian date(or hijri date or any thig else) and i want to convert it to Gregorian date ... your code doesn't do it, dose it? – mjyazdani Nov 11 '12 at 08:31
  • @mj-y: It does if you've created it properly - but I suspect you haven't. Given that you haven't shown us any of the code you've used to create the `DateTime`, it's hard to say. – Jon Skeet Nov 11 '12 at 08:32
  • @mj-y: See my edit for an example of how to create a `DateTime` *correctly* within a different calendar. Now, what does your code do? – Jon Skeet Nov 11 '12 at 08:34
  • in GetPdate function i have a simple datetime (DateTime.Now) and for the reverce function I should use a string like the output of GetPDate... – mjyazdani Nov 11 '12 at 08:38
  • @mj-y: So you want to convert a `String` to a `DateTime`? That's a completely different request. I really wish you'd been clearer to start with. Please make your question *much* clearer, and I'll see if I have time later on. – Jon Skeet Nov 11 '12 at 08:41
  • yes the input of the function should be a string ...I edited my question. I will appriciate for your help – mjyazdani Nov 11 '12 at 08:48
  • @mj-y: Unfortunately it looks like .NET makes it relatively tricky to parse values for a calendar which isn't the native calendar for any specific known culture... hmm... – Jon Skeet Nov 11 '12 at 09:04
  • you mean that I should convert it manually ... I mean I should compute it myself? – mjyazdani Nov 11 '12 at 09:08
  • @mj-y: Ideally not. I'll need to look a bit further. It's unfortunate that this isn't a calendar that Noda Time supports, otherwise that would be a simple answer. – Jon Skeet Nov 11 '12 at 09:10
  • 1
    @mj-y: Will now update the answer, as Noda Time supports the Persian calendar these days. – Jon Skeet Apr 23 '16 at 06:28
7

Thanks guys,I used below code and my problem solved:

public static DateTime GetEdate(string _Fdate)
{
    DateTime fdate = Convert.ToDateTime(_Fdate);
    GregorianCalendar gcalendar = new GregorianCalendar();
    DateTime eDate = pcalendar.ToDateTime(
           gcalendar.GetYear(fdate),
           gcalendar.GetMonth(fdate),
           gcalendar.GetDayOfMonth(fdate),
           gcalendar.GetHour(fdate),
           gcalendar.GetMinute(fdate),
           gcalendar.GetSecond(fdate), 0);
    return eDate;
}
Nima Derakhshanjan
  • 1,380
  • 9
  • 24
  • 37
mjyazdani
  • 2,110
  • 6
  • 33
  • 64
5

Use this code to convert Persian to Gregorian date and vice versa.

public static class PersainDate
{
    public static DateTime ConvertToGregorian(this DateTime obj)
    {
        DateTime dt = new DateTime(obj.Year, obj.Month, obj.Day, new PersianCalendar());
        return dt;
    }
    public static DateTime ConvertToPersian(this DateTime obj)
    {
        var persian = new PersianCalendar();
        var year = persian.GetYear(obj);
        var month = persian.GetMonth(obj);
        var day = persian.GetDayOfMonth(obj);
        DateTime persiandate = new DateTime(year, month, day);
        return persianDate;
    }
}

Use the code this way

        var time = DateTime.Now;
        var persianDate = time.ConverToPersian();
        var gregorianDate = persianDate.ConverToGregorian();
Arash
  • 889
  • 7
  • 18
4

1- first install Persiandate NuGet package (17KB)

Install-Package PersianDate

2- use ToFa and toEn static methods of PersianDate class like(do not worry about the seperators and directions which will be handled by library itself as you can see in the following samples .also you can find the Usage Console project inside in GitHub to test it yourself easily):

   //default format 
    string dts=ConvertDate.ToFa(DateTime.Now);//1393/08/01
    //date only (short and D for Long)
    dts=ConvertDate.ToFa(DateTime.Now, "d");//93/08/01 
    dts=ConvertDate.ToFa(DateTime.Now, "D");//پنج شنبه, 01 آبان 1393
    //time only 
    dts=ConvertDate.ToFa(DateTime.Now, "t");//21:53 
    dts=ConvertDate.ToFa(DateTime.Now, "T");//21:53:26
    //general short date + time
    dts=ConvertDate.ToFa(DateTime.Now, "g");//93/08/01 21:53 
    dts=ConvertDate.ToFa(DateTime.Now, "G");//93/08/01 21:53:26
    //general full date + time
    dts=ConvertDate.ToFa(DateTime.Now, "f");//پنج شنبه, 01 آبان 1393 21:53 
    dts=ConvertDate.ToFa(DateTime.Now, "F");//پنج شنبه, 01 آبان 1393 21:53:26
    //only month and year
    dts=ConvertDate.ToFa(DateTime.Now, "m");//آبان 1 
    dts=ConvertDate.ToFa(DateTime.Now, "y");//1393 آبان

    dts=ConvertDate.ToFa(DateTime.Now);//1393/08/01
    // converting back to Gregorian date 
    Datetime dt= ConvertDate.ToEn(dts);//2014/10/23 00:00:00

3- Source code available in GitHub for any modifications and supporting new formats.

look for the following functions source code to see how it is generally working

    public static DateTime ToEn(string fadate)
    {
        if (fadate.Trim() == "") return DateTime.MinValue;
        int[] farsiPartArray = SplitRoozMahSalNew(fadate);

        return new PersianCalendar().ToDateTime(farsiPartArray[0], farsiPartArray[1], farsiPartArray[2], 0, 0, 0, 0);

    }

    private static int[] SplitRoozMahSalNew(string farsiDate)
    {
        int pYear = 0;
        int pMonth = 0;
        int pDay = 0;


        //normalize with one character
        farsiDate = farsiDate.Trim().Replace(@"\", "/").Replace(@"-", "/").Replace(@"_", "/").
            Replace(@",", "/").Replace(@".", "/").Replace(@" ", "/");


        string[] rawValues = farsiDate.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);


        if (!farsiDate.Contains("/"))
        {
            if (rawValues.Length != 2)
                throw new Exception("usually there should be 2 seperator for a complete date");
        }
        else //mostly given in all numeric format like 13930316
        {
            // detect year side and add slashes in right places and continue
        }
        //new simple method which emcompass below methods too
        try
        {
            pYear = int.Parse(rawValues[0].TrimStart(new[] { '0' }).Trim());
            pMonth = int.Parse(rawValues[1].TrimStart(new[] { '0' }).Trim());
            pDay = int.Parse(rawValues[2].TrimStart(new[] { '0' }).Trim());

            // the year usually must be larger than 90
            //or for historic values rarely lower than 33 if 2 digit is given
            if (pYear < 33 && pYear > 0)
            {
                //swap year and day
                pYear = pDay;
                pDay = int.Parse(rawValues[0]); //convert again
            }
            //fix 2 digits of persian strings
            if (pYear.ToString(CultureInfo.InvariantCulture).Length == 2)
                pYear = pYear + 1300;
            //
            if (pMonth <= 0 || pMonth >= 13)
                throw new Exception("mahe shamsi must be under 12 ");
        }
        catch (Exception ex)
        {
            throw new Exception(
                "invalid Persian date format: maybe all 3 numric Sal, Mah,rooz parts are not present. \r\n" + ex);
        }

        return new[] { pYear, pMonth, pDay };
    }
Iman
  • 17,932
  • 6
  • 80
  • 90
3
You may try with this: 

using System.Globalization // namespace
GregorianCalendar greg = new GregorianCalendar();
DateTime DayYearMonth = new DateTime(1433, 10, 11, greg );

Console.WriteLine(greg .GetDayOfMonth(DayYearMonth )); // 11
Console.WriteLine(greg .GetYear(DayYearMonth )); // 1433
Console.WriteLine(greg .GetMonth(DayYearMonth )); // 10
Rashedul.Rubel
  • 3,446
  • 25
  • 36
2

This method converts a string which represents a shamsi date to System.DateTime :

    public DateTime milady(string shamsiDate)
    {
        DateTime dt = new DateTime();
        PersianCalendar pc = new PersianCalendar();

        int pYear = Convert.ToInt32(shamsiDate.Substring(0, 4));
        int pMonth =Convert.ToInt32(shamsiDate.Substring(5, 2));
        int pDay =  Convert.ToInt32( shamsiDate.Substring(8));


        dt = pc.ToDateTime(pYear, pMonth, pDay,0,0,0,0);
        return dt;
    }
Kia Boluki
  • 315
  • 3
  • 15
1

You can use PersianDateTime, using Nuget:

PM> Install-Package PersianDateTime

and how you can use:

DateTime miladiDate = new DateTime(2013, 5, 31);
PersianDateTime persianDate = new PersianDateTime(miladiDate);

and:

PersianDateTime persianDate = PersianDateTime.Parse("1392/03/02");
DateTime miladiDate = persianDate.ToDateTime(); 

for : more info about PersianDateTime

Elnaz
  • 2,854
  • 3
  • 29
  • 41
1

This method check leap years.

private static DateTime JalaliToGregorianDate(string jalaliDate)
{
    string[] JalaliDateArray = jalaliDate.Split(new Char[] { '/' });
    int Year, Mounth, Day;
    DateTime GregorianDate;
    PersianCalendar persianCalendar = new PersianCalendar();
    //
    Year = int.Parse(JalaliDateArray[2]);
    if (Year < 100)
    {
        Year = 1300 + Year;
    }
    Mounth = int.Parse(JalaliDateArray[1]);
    Day = int.Parse(JalaliDateArray[0]);
    if (Day > 29 && Mounth == 12)
    {
        if (!persianCalendar.IsLeapYear(Year))
        {
            throw (new Exception(string.Format("IsNotLeapYear&{0}", Year)));
        }
    }
    GregorianDate = persianCalendar.ToDateTime(Year, Mounth, Day, 0, 0, 0, 0);
    //
    return GregorianDate;
}
0

Using Persia.NET Core can be of help to you:

Converting Gregorian to Shamsi

Persia.SolarDate solarDate = Persia.Calendar.ConvertToPersian(DateTime.Now);
// getting the simple format of persian date
string str = solarDate.ToString();

Converting Shamsi to Gregorian

DateTime ConvertToGregorian(SolarDate solarDate)
DateTime ConvertToGregorian(LunarDate lunarDate)
DateTime ConvertToGregorian(int year, int month, int day, DateType dateType)
DateTime ConvertToGregorian(int year, int month, int day, int hour, int minute, int
second, DateType dateType)

You can download it here If your application is not supported .NET Core you can find the older version of this from NuGet.

Majid Shahabfar
  • 4,010
  • 2
  • 28
  • 36