简体   繁体   中英

How to convert Persian Calendar date string to DateTime?

I use these codes for converting current datetime and minus it with the date time which users type in a textbox. But it gives an error while converting.

PersianCalendar p = new System.Globalization.PersianCalendar();
DateTime date = new DateTime();
date = DateTime.Parse(DateTime.Now.ToShortDateString());
int year = p.GetYear(date);
int month = p.GetMonth(date);
int day = p.GetDayOfMonth(date);
string str = string.Format("{0}/{1}/{2}", year, month, day);
DateTime d1 = DateTime.Parse(str);
DateTime d2 = DateTime.Parse(textBox9.Text);
string s = (d2 - d1).ToString().Replace(".00:00:00", "");
textBox10.Text = (d2 - d1).ToString().Replace(".00:00:00","");

This line will accord an error while converting datetime from string to date time : DateTime d1 = DateTime.Parse(str);

Please help me to solve this problem.

Thanks in advance

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);

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).

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();

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 

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.

You can also use the following .net library to use PersianCalendar as easy as DateTime:

Persian Calendar(PersianDateTime) in C#

var persianDateTime = PersianDateTime.Now;
persianDateTime.EnglishNumber = true;
Console.Write(persianDateTime.ToString());

You can use this code:

  DateTime today = DateTime.Today; // excludes h/m/s

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

If you substract one from the other you get a TimeSpan.

  TimeSpan diff = today - userDate;

You can use this time span's properties to show them the way you like.

To manage the conversion form/to Persian calendar, you have a good solution here:

.NET How to parse a date string for Persian (Jalali calendar) into a DateTime object?

References:

DateTime.Today

TimeSpan

Here is a code that i am using :

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

This can be done a lot easier using Noda Time :

using System.Globalization;
using NodaTime;
using NodaTime.Text;

...

CultureInfo culture = CultureInfo.CreateSpecificCulture("fa-IR");
CalendarSystem calendar = CalendarSystem.GetPersianCalendar();
LocalDate template = new LocalDate(1, 1, 1, calendar);
LocalDatePattern pattern = LocalDatePattern.Create("yyyy/M/d", culture, template);
LocalDate result = pattern.Parse("1391/2/30").Value;

// if you need a DateTime, then:
DateTime dt = result.AtMidnight().ToDateTimeUnspecified();

try this code: this code is edited code that posted by "grzegorz W" but his code generate Error for example when user input date="1394/06/31" and error is "Year, Month, and Day parameters describe an un-representable DateTime"

below code is ok:

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, day,p);


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, userDay,p);


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

You can use this simple code to convert persian calendar values to Datetime object in C# and make your calculations.

DateTime dateTime 
      = new DateTime(persianYear, persianMonth, persianDay, new PersianCalendar());

Hello You can use this EXTENTION METHODE :

public static class PersainDateTime
{

    public static DateTime PersianDateToMiladi(this string value)
        {
            string[] d = value.Split('/');
            return new DateTime(int.Parse(d[0]), int.Parse(d[1]), int.Parse(d[2]), new System.Globalization.PersianCalendar());
        }
}

Now where ever you want you can use it like this:

var date=("1395/10/5").PersianDateToMiladi();

or

var date= textbox1.text.PersianDateToMiladi();
private void timer1_Tick(object sender, EventArgs e)
{
    labelDataAD.Text = DateTime.Now.ToString("dd/MM/yyyy");
    PersianCalendar persianCalendar = new PersianCalendar();
    string Full = persianCalendar.GetYear(DateTime.Now) + "/" + 
    persianCalendar.GetMonth(DateTime.Now)+"/"+ 
    persianCalendar.GetDayOfMonth(DateTime.Now);
    labelDataSolar.Text = string.Format("{0:yyyy\\:MM\\:dd}", Full);
}

private void FormCalendar_Load(object sender, EventArgs e)
{           
    timer1.Start();
}

The output is:

日期输出

对于我的情况,这个解决方案对我有帮助:我在我的项目中创建工具文件夹然后我把类 ExtensionsHelper.cs 和 HijriDateTime.cs 和 PersianDateTime.cs 和 PersianDayOfWeek.cs 放在这个链接中你可以找到上面的类:< https:// github.com/Mds92/MD.PersianDateTime > 然后我使用 PersianDateTime 而不是 DateTime:

DateTime datetime = new DateTime(PersianDateTime.Now.Year, PersianDateTime.Now.Month, PersianDateTime.Now.Day, 0, 0, 0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM