21

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

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Ali Vojdanian
  • 2,067
  • 2
  • 31
  • 47
  • 5
    Why are you formatting DateTime.Now then parsing it again? Why are you assigning a value to `date` and then immediately assigning it a different value? Why are you parsing a Persian year/month/day as if it weren't in the Persian calendar? It's *very* unclear what you're trying to do, and where the Persian calendar fits in. – Jon Skeet May 18 '12 at 15:09
  • You don't do anything with your `string s`. – comecme May 18 '12 at 15:13
  • Is the date format of your currentculture set to Persian? – comecme May 18 '12 at 15:15
  • @Tejs String was not recognized as a valid DateTime. – Ali Vojdanian May 18 '12 at 15:17
  • Is your current culture set to use that format? Typically, it will expect `mm/dd/yyyy` format, which will obviously fail with your `str` construction. Different cultures will change the formatting required. – Tejs May 18 '12 at 15:18
  • So, basically you want the user to enter a date according to Persian calendar, then subtract that date from today, and then what? You want to show the difference between those two dates also in Persian calendar format? – comecme May 18 '12 at 15:41
  • @comecme Yes. for eaxmple 4 days remains or something like that ... – Ali Vojdanian May 18 '12 at 15:48
  • If any of the answers answers your question, would you please accept it? – comecme May 29 '12 at 20:37
  • this will help : http://stackoverflow.com/a/9491805/704749 – Ashkan Ghodrat Jan 20 '15 at 12:36

14 Answers14

17

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

Community
  • 1
  • 1
comecme
  • 6,086
  • 10
  • 39
  • 67
16

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);
Grzegorz W
  • 3,487
  • 1
  • 21
  • 21
  • That still is the same as `DateTime d1 = DateTime.Now.Date`. – comecme May 18 '12 at 15:17
  • @GrzegorzWilczura It said : Year, Month, and Day parameters describe an un-representable DateTime. – Ali Vojdanian May 18 '12 at 15:22
  • @Grzegorz: I'm sorry, you are right. I didn't know anything about the PersianCalendar. I assumed it just used a different format, didn't know it is a completely different calendar. – comecme May 18 '12 at 15:24
  • 1
    The last line tries to create a gregorian date with the year, month and day of the persian equivalent of today. I don't think every persian date is also a valid gregorian date. For instance, the 2nd month has 31 days in the persian calendar, but february doesn't have 31 days. – comecme May 18 '12 at 15:30
  • @aliboy38: Of course You get the exception. Since its 1391/02/29 in Persian calendar. And such date has no representation in 'en' culture (or whatever you are using) – Grzegorz W May 18 '12 at 15:32
  • 2
    @GrzegorzWilczura So what should i Do? – Ali Vojdanian May 18 '12 at 15:44
  • @GrzegorzW I think this code is error-prone. I am Persian, in PersianCalendar or Jalali Date we have yyyy/04/31 but in Gregorian Date, April (4th month) does not have 31 days, so the date will be invalid. – Mahdi Tahsildari Mar 08 '14 at 11:04
  • All is good up until the very last line. Values passed into the `DateTime` constructor need to be Gregorian unless you use the overload that includes a `Calendar` parameter. Additionally, `DateTime` is always Gregorian internally. It only works with other calendars during formatting, or with the constructor I described. – Matt Johnson-Pint Sep 20 '15 at 18:48
  • @MattJohnson Sure. You are right. That code was incorrect. I updated the code to display my original intention. – Grzegorz W Sep 21 '15 at 09:24
  • @GrzegorzW - I've seen a LOT of DateTime code, and your update looks highly suspect... I'd put it through a lot of unit tests. You may find edge cases you hadn't considered. Also, you'll find this a lot easier with [Noda Time](http://nodatime.org). See [my answer](http://stackoverflow.com/a/32683586/634824). – Matt Johnson-Pint Sep 21 '15 at 13:33
12

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();
Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
  • 4
    This methods converts from persian calendar to our date. So actually, you will get something in distant future. I doubt that is what he wants. – Grzegorz W May 18 '12 at 15:34
  • @GrzegorzWilczura It converts to our day, using the Persian calendar, how would that give you something in the future? – Mathew Thompson May 21 '12 at 14:19
9

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 
Ali Vojdanian
  • 2,067
  • 2
  • 31
  • 47
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.

Ali Vojdanian
  • 2,067
  • 2
  • 31
  • 47
SPFiredrake
  • 3,852
  • 18
  • 26
  • I don't think you can create a DateTime from every possible Persian date. The Persian 2nd month has 31 days, but the Gregorian date doesn't. So it will fail on something like `new DateTime(1391,2,31);`. – comecme May 18 '12 at 15:33
  • @comecme: This is valid because you're supplying the calendar as well, meaning it validates the date based on the specific calendar. @aliboy38: Of course it does, because the timespan is negative (meaning the date the user inputted comes before today's date). If the date the user supplies is going to be less than today's date, then reverse the order of datetime subtraction (`(pDate-d2).ToString("d")`). Again though, it just depends on what you're trying to accomplish. If you only ever want the days part (absolute value), then just do `Math.Abs((pDate - d2).TotalDays)`. – SPFiredrake May 18 '12 at 15:51
  • @SPFiredrake: I'm sorry, I had to scroll your code in order to see you supply `p` as the last argument. But parsing would be another problem, which you've solved now. – comecme May 18 '12 at 16:21
  • your `pDate` is exactly the same as `today`. Also, using `CultureInfo("fa-IR")` only defines the format `yyyy/mm/dd`, but won't allow Persian calendar dates (like 1391/2/30, which is today). – comecme May 19 '12 at 08:45
2

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

Persian Calendar(PersianDateTime) in C#

var persianDateTime = PersianDateTime.Now;
Console.Write(persianDateTime.ToString());
Mohammad Dayyan
  • 21,578
  • 41
  • 164
  • 232
1

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

Community
  • 1
  • 1
JotaBe
  • 38,030
  • 8
  • 98
  • 117
1

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;
        }
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
1

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();
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
0

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);
hojjat.mi
  • 1,414
  • 16
  • 22
0

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

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();
Ali Mahmoodi
  • 858
  • 10
  • 14
0
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:

Date output

gurkan
  • 884
  • 4
  • 16
  • 25
0

for my case this solution help me: i create Tools Folder in my project then i put class ExtensionsHelper.cs and HijriDateTime.cs and PersianDateTime.cs and PersianDayOfWeek.cs in it in this link you can find above classes: <https://github.com/Mds92/MD.PersianDateTime> then i use PersianDateTime instead using DateTime:

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