How to convert Persian Calendar date string to DateTime?

Solution 1:

No need to parse the date here.

EDIT:

Originally I only wanted to point out error in OP processing with this answer. But I think a full answer would be better (despite the delay :) ) And Yes I know that intermediate date representation does not look like Persian Date. But it is not what is needed. This code gives proper difference between current date and the date that user puts in.

string userInput = "1394/02/31";
System.DateTime date = System.DateTime.Today;
System.Globalization.PersianCalendar p = new System.Globalization.PersianCalendar();

int year = p.GetYear(date);
int month = p.GetMonth(date);
int day = p.GetDayOfMonth(date);
System.DateTime currentDate = new System.DateTime(year, month, 1);
currentDate = currentDate.AddDays(day - 1);

// validation omitted
System.String[] userDateParts = userInput.Split(new[] { "/" }, System.StringSplitOptions.None);
int userYear = int.Parse(userDateParts[0]);
int userMonth = int.Parse(userDateParts[1]);
int userDay = int.Parse(userDateParts[2]);
System.DateTime userDate = new System.DateTime(userYear, userMonth, 1);
userDate = userDate.AddDays(userDay - 1);

System.TimeSpan difference = currentDate.Subtract(userDate);

Solution 2:

You actual problem seems to lie in parsing the date the user entered in Persian calendar format. So, if the user entered 1391/2/31 you want to be able to parse that. Today (May 19th 2012) is 1391/2/30 so you finally want to display something like 1 day remaining.

This question has been asked before. However, the accepted answer there just tries to use

string persianDate = "1390/02/07";
CultureInfo persianCulture = new CultureInfo("fa-IR");
DateTime persianDateTime = DateTime.ParseExact(persianDate, 
    "yyyy/MM/dd", persianCulture);

Which won't work for a date like 1391/2/31. So I think you'd have to implement the parsing yourself.

Without implementing any error checking, and assuming the user always uses the format yyyy/mm/dd you could use:

// Convert Persian Calendar date to regular DateTime
var persianDateMatch = System.Text.RegularExpressions.Regex.Match(
    persianTargetTextBox.Text, @"^(\d+)/(\d+)/(\d+)$");
var year = int.Parse(persianDateMatch.Groups[1].Value);
var month = int.Parse(persianDateMatch.Groups[2].Value);
var day = int.Parse(persianDateMatch.Groups[3].Value);
var pc = new System.Globalization.PersianCalendar();
var target = pc.ToDateTime(year, month, day, 0, 0, 0, 0);

var difference = target - DateTime.Today;
differenceLabel.Text = difference.TotalDays.ToString("0");

You would need to check if the regex acually found any matches. You'd also have to check if pc.ToDateTime doesn't throw an error. Unfortunately, there doesn't seem to exist anything like DateTime.TryParse for the Persian Calendar.

Anyway, you don't need to parse today into a Persian Calendar, you only need to parse the user input.

You might also be interested in Farsi Library - Working with Dates, Calendars, and DatePickers, even though the article is very old (2007).

Solution 3:

Just use the ToDateTime method on the PersianCalendar class:

PersianCalendar p = new PersianCalendar();
DateTime now = DateTime.Now;
DateTime dateT = p.ToDateTime(now.Year, now.Month, now.Day, 0, 0, 0, 0);

Then to get your string in that format, just do:

string str = dateT.ToShortDateString();

Solution 4:

I solved that problem. it was because of exception in some months so if you want to minus two date times from each other you should convert both to the Gregorian calendar then you can minus them and see the result.

here are the codes :

PersianCalendar p = new PersianCalendar();
        string PersianDate1 = textBox1.Text;
        string[] parts = PersianDate1.Split('/', '-');
        DateTime dta1 = p.ToDateTime(Convert.ToInt32(parts[0]), Convert.ToInt32(parts[1]), Convert.ToInt32(parts[2]), 0, 0, 0, 0);
        string PersianDate2 = textBox2.Text;
        string[] parts2 = PersianDate2.Split('/', '-');
        DateTime dta2 = p.ToDateTime(Convert.ToInt32(parts2[0]), Convert.ToInt32(parts2[1]), Convert.ToInt32(parts2[2]), 0, 0, 0, 0);
        string s = (dta2 - dta1).ToString().Replace(".00:00:00", "");
        textBox3.Text = s; // Show the result into the textbox 

Solution 5:

Here is where documentation is your friend:

PersianCalendar Class

DateTime Constructor (Int32, Int32, Int32, Calendar)

This is the exact code you'd need:

PersianCalendar p = new System.Globalization.PersianCalendar();
DateTime today = DateTime.Today;
DateTime pDate = new DateTime(p.GetYear(today), p.GetMonth(today), p.GetDayOfMonth(today), p);
DateTime d2 = DateTime.Parse(textBox9.Text);
// THIS NEEDS TO BE EXPLAINED
textBox10.Text = (d2 - pDate).ToString().Replace(".00:00:00","");

Ultimately, what are you trying to do? What are the results you're expecting in textBox10? If you want the number of days between the two dates, then just do (d2 - pDate).ToString("d") and you'll get the difference in days. Maybe if you explained a little further WHAT you're trying to do, instead of HOW you're trying to do it, we can possibly help you further.

Edit: Just realized what comecme was saying. The line that would cause the issue is here:

DateTime d2 = DateTime.Parse(textBox9.Text);

Instead, we would need to change it to also use the culture information as well:

CultureInfo persianCulture = new CultureInfo("fa-IR");
DateTime d2 = DateTime.Parse(textBox9.Text, persianCulture)

Edit: You are correct, it only allows parsing the date in the Persian format, but does not validate according to a particular calendar. In order to get this working properly, you're gonna have to manually parse out the date and instantiate a new DateTime with the PersianCalendar supplied:

DateTime d2;
if(Regex.IsMatch(textBox9.Text, "^dddd/dd/dd$"))
{
    d2 = new DateTime(
        int.Parse(textBox9.Substring(0,4)), 
        int.Parse(textBox9.Substring(5, 2)), 
        int.Parse(textBox9.Substring(8, 2)),
        p);
}

You just have to make sure that the input definitely matches the format you specify, otherwise there's no way to consistently parse out the DateTime accurately.