Reputation: 449
To convert a string Persian date to gregorian DateTime
,
I use date time picker and it sends me a string like "۱۳۹۴/۰۲/۲۰"
PersianCalendar p = new PersianCalendar();
string[] d = start.Split('/');
DateTime dt = new DateTime(int.Parse(d[0]),
int.Parse(d[1]),
int.Parse(d[2]),
new HijriCalendar());
and my function that converts is
public static DateTime ToGregorianDate(this DateTime dt)
{
PersianCalendar pc = new PersianCalendar();
return pc.ToDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0, 0);
}
It gives DateTime
how can I send correct DateTime
when it wants to convert shows this error:
Input string was not in a correct format.
Upvotes: 8
Views: 8944
Reputation: 111860
You have two different problems:
Arabic digits aren't supported by DateTime
parsing
PersianCalendar
isn't part of any CultureInfo
, so you can't use it directly while parsing the string
to DateTime
(and you can't set it to a preexisting CultureInfo
).
Possible solution:
string date = "۱۳۹۴/۰۲/۲۰";
string date2 = Regex.Replace(date, "[۰-۹]", x => ((char)(x.Value[0] - '۰' + '0')).ToString());
Replace the digits from Arabic to decimal
DateTime dt = DateTime.ParseExact(date2, "yyyy/MM/dd", CultureInfo.InvariantCulture);
Then parse the date ignoring the calendar
PersianCalendar pc = new PersianCalendar();
DateTime dt2 = pc.ToDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
Then convert the date to the right calendar.
This solution is broken because Persian Calendar months have a different number of days than Gregorian months
Upvotes: 7
Reputation: 186688
You have to convert Persian digits into int
*manually, e.g.
private static int ParsePersianNumber(String value) {
int result = 0;
// Persian digits are Unicode characters 0x06F0-0x06F9
foreach (var ch in value)
result = result * 10 + ch - 0x06F0;
return result;
}
...
String start = "۱۳۹۴/۰۲/۲۰";
PersianCalendar p = new PersianCalendar();
string[] d = start.Split('/');
// int.Parse -> ParsePersianNumber
// dt == 14 Mar 1974
DateTime dt = new DateTime(
ParsePersianNumber(d[0]),
ParsePersianNumber(d[1]),
ParsePersianNumber(d[2]),
new HijriCalendar());
Upvotes: 3
Reputation: 98750
As I commented; Eastern Arabic numerals does not supported by DateTime
parsing methods, it only accepts Arabic numerals.
However, char
type has a GetNumericValue
method which converts any numeric Unicode character to a double
.
Let's use a combination of char.GetNumericValue
, string.Join
and Int32.Parse
methods;
string d = "۱۳۹۴/۰۲/۲۰";
int year = Int32.Parse(string.Join("",
d.Split('/')[0].Select(c => char.GetNumericValue(c)))); // 1394
int month = Int32.Parse(string.Join("",
d.Split('/')[1].Select(c => char.GetNumericValue(c)))); // 2
int day = Int32.Parse(string.Join("",
d.Split('/')[2].Select(c => char.GetNumericValue(c)))); // 20
And then you can create a DateTime
based on this values;
DateTime dt = new DateTime(year, month, day);
Then you can use;
PersianCalendar pc = new PersianCalendar();
var dt1 = pc.ToDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
// {10.05.2015 00:00:00}
Upvotes: 6
Reputation: 19111
Map to Arabic numerals first:
var mapToArabic =
new Dictionary<char, char>{
{'۰', '0'}, {'۱', '1'}, {'۲', '2'},
{'۳', '3'}, {'۴', '4'}, {'۵', '5'},
{'۶', '6'}, {'۷', '7'}, {'۸', '8'}, {'۹', '9'}};
var p = new System.Globalization.PersianCalendar();
var start = "۱۳۹۴/۰۲/۲۰";
string[] persian = start.Split('/');
The main change from your original code: Mapping from an array of Persian numbers (year, month, date), to an equivalent array containing the values in Arabic numerals:
var arabic = persian
.Select(persianWord =>
new string(persianWord
.Select(persianChar => mapToArabic[persianChar])
.ToArray()))
.ToList();
Now you can use that as you used the other one before:
DateTime dt = new DateTime(int.Parse(arabic[0]),
int.Parse(arabic[1]),
int.Parse(arabic[2]),
new System.Globalization.HijriCalendar());
var pc = new System.Globalization.PersianCalendar();
var result = pc.ToDateTime(dt.Year, dt.Month, dt.Day,
dt.Hour, dt.Minute, 0, 0);
Upvotes: 2