diff --git a/Persia .NET Core.sln b/Persia .NET Core.sln new file mode 100644 index 0000000..eaf5900 --- /dev/null +++ b/Persia .NET Core.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30320.27 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Persia .NET Core", "Persia .NET Core\Persia .NET Core.csproj", "{B3C508E9-A19E-4F50-922D-66CB3A74C0CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3C508E9-A19E-4F50-922D-66CB3A74C0CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3C508E9-A19E-4F50-922D-66CB3A74C0CF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3C508E9-A19E-4F50-922D-66CB3A74C0CF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3C508E9-A19E-4F50-922D-66CB3A74C0CF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BD59BD73-EC0F-47A7-858F-BCFB08BCB6D0} + EndGlobalSection +EndGlobal diff --git a/Persia .NET Core/Calendar.cs b/Persia .NET Core/Calendar.cs new file mode 100644 index 0000000..84d4065 --- /dev/null +++ b/Persia .NET Core/Calendar.cs @@ -0,0 +1,244 @@ +using System; + + +// ("`-''-/").___..--''"`-._ +// `6_ 6 ) `-. ( ).`-.__.`) +// (_Y_.)' ._ ) `._ `. ``-..-' +// _..`--'_..-_/ /--'_.' ,' +// (il),-'' (li),' ((!.-' + + +namespace Persia_.NET_Core +{ + public enum DateType { Persian, Gerigorian, Islamic }; + + public static class Calendar + { + private const float GregorianEpoch = 1721425.5f; + private const float PersianEpoch = 1948320.5f; + private const float IslamicEpoch = 1948439.5f; + private const float Tolerance = 0.00001f; + + public static SolarDate ConvertToPersian(LunarDate lunarDate) + { + return ConvertToPersian(null, lunarDate.ArrayType[0], lunarDate.ArrayType[1], lunarDate.ArrayType[2], false); + } + + public static SolarDate ConvertToPersian(DateTime date) + { + return ConvertToPersian(date, 0, 0, 0, true); + } + + public static SolarDate ConvertToPersian(int year, int month, int day, DateType dateType) + { + return ConvertToPersian(null, year, month, day, dateType == DateType.Gerigorian); + } + + private static SolarDate ConvertToPersian(DateTime? date, int year, int month, int day, bool isDateTime) + { + var solarDate = new SolarDate(); + float jd; + if (isDateTime) + { + if (date.HasValue) + { + jd = gregorian_to_jd(date.Value.Year, date.Value.Month, date.Value.Day); + solarDate.dateTime = date.Value; + } + else + throw new NullReferenceException(); + } + else + { + jd = islamic_to_jd(year, month, day); + date = ConvertToGregorian(year, month, day, DateType.Islamic); + solarDate.dateTime = date.Value; + } + + var solar = jd_to_persian(jd); + var weekday = Convert.ToInt32(date.Value.DayOfWeek); + weekday = weekday >= 6 ? weekday - 6 : weekday + 1; + solarDate.DayOfWeek = weekday; + solarDate.ArrayType = isDateTime ? new[] { solar[0], solar[1], solar[2], date.Value.Hour, date.Value.Minute, date.Value.Second } : new[] { solar[0], solar[1], solar[2], 0, 0, 0 }; + return solarDate; + } + + public static LunarDate ConvertToIslamic(DateTime date) + { + return ConvertToIslamic(date, 0, 0, 0, true); + } + + public static LunarDate ConvertToIslamic(int year, int month, int day, DateType dateType) + { + return ConvertToIslamic(DateTime.Now, year, month, day, dateType != DateType.Persian); + } + + public static LunarDate ConvertToIslamic(SolarDate solarDate) + { + return ConvertToIslamic(DateTime.Now, solarDate.ArrayType[0], solarDate.ArrayType[1], solarDate.ArrayType[2], false); + } + + private static LunarDate ConvertToIslamic(DateTime? date, int year, int month, int day, bool isDateTime) + { + var lunarDate = new LunarDate(); + float jd; + if (isDateTime) + { + if (date.HasValue) + jd = gregorian_to_jd(date.Value.Year, date.Value.Month, date.Value.Day); + else + throw new NullReferenceException(); + } + else // Persian + { + jd = persian_to_jd(year, month, day); + date = ConvertToGregorian(year, month, day, DateType.Persian); + } + + var lunar = jd_to_islamic(jd); + var weekday = Convert.ToInt32(date.Value.DayOfWeek); + + weekday = weekday >= 6 ? weekday - 6 : weekday + 1; + lunarDate.DayOfWeek = weekday; + lunarDate.ArrayType = isDateTime ? new[] { lunar[0], lunar[1], lunar[2], date.Value.Hour, date.Value.Minute, date.Value.Second } : new[] { lunar[0], lunar[1], lunar[2], 0, 0, 0 }; + + var cal = new System.Globalization.HijriCalendar(); + lunarDate.ArrayType[2] = cal.GetDayOfMonth(date.Value.Date); + lunarDate.ArrayType[1] = cal.GetMonth(date.Value.Date); + + return lunarDate; + } + + public static DateTime ConvertToGregorian(LunarDate lunarDate) + { + return ConvertToGregorian(lunarDate.ArrayType[0], lunarDate.ArrayType[1], lunarDate.ArrayType[2], lunarDate.ArrayType[3], lunarDate.ArrayType[4], lunarDate.ArrayType[5], true); + } + + public static DateTime ConvertToGregorian(SolarDate solarDate) + { + return ConvertToGregorian(solarDate.ArrayType[0], solarDate.ArrayType[1], solarDate.ArrayType[2], solarDate.ArrayType[3], solarDate.ArrayType[4], solarDate.ArrayType[5], false); + } + + public static DateTime ConvertToGregorian(int year, int month, int day, DateType dateType) + { + return ConvertToGregorian(year, month, day, 0, 0, 0, dateType == DateType.Islamic); + } + + public static DateTime ConvertToGregorian(int year, int month, int day, int hour, int minute, int second, DateType dateType) + { + return ConvertToGregorian(year, month, day, hour, minute, second, dateType == DateType.Islamic); + } + + private static DateTime ConvertToGregorian(int year, int month, int day, int hour, int minute, int second, bool isSlamic) + { + var jd = !isSlamic ? persian_to_jd(year, month, day) : islamic_to_jd(year, month, day); + var miladi = jd_to_gregorian(jd); + var date = new DateTime(miladi[0], miladi[1], miladi[2], hour, minute, second); + return date; + } + + private static float gregorian_to_jd(int year, int month, int day) + { + return (float)(GregorianEpoch - 1 + + 365 * (year - 1) + + Math.Floor((double)((year - 1) / 4)) - Math.Floor((double)((year - 1) / 100)) + + Math.Floor((double)((year - 1) / 400)) + + Math.Floor((double)((367 * month - 362) / 12 + + (month <= 2 ? 0 : leap_gregorian(year) ? -1 : -2)) + day)); + } + + private static bool leap_gregorian(int year) + { + return year % 4 == 0 && !(year % 100 == 0 && year % 400 != 0); + } + + //private static bool leap_persian(int year) + //{ + // return ((((((year - ((year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682; + //} + + private static int[] jd_to_persian(float jd) + { + float ycycle; + + jd = (float)(Math.Floor(jd) + 0.5); + + var depoch = jd - persian_to_jd(475, 1, 1); + var cycle = (float)Math.Floor(depoch / 1029983); + var cyear = (depoch % 1029983); + if (Math.Abs(cyear - 1029982) < Tolerance) + ycycle = 2820; + else + { + var aux1 = (float)Math.Floor(cyear / 366); + var aux2 = (cyear % 366); + ycycle = (float)Math.Floor(((2134 * aux1) + (2816 * aux2) + 2815) / 1028522) + aux1 + 1; + } + + var year = (int)(ycycle + (2820 * cycle) + 474); + if (year <= 0) + year--; + + var yday = (jd - persian_to_jd(year, 1, 1)) + 1; + var month = (int)((yday <= 186) ? Math.Ceiling(yday / 31) : Math.Ceiling((yday - 6) / 30)); + var day = (int)(jd - persian_to_jd(year, month, 1)) + 1; + var res = new[] { year, month, day }; + return res; + } + + private static float persian_to_jd(int year, int month, int day) + { + float epbase = year - (year >= 0 ? 474 : 473); + var epyear = 474 + (epbase % 2820); + + return day + + (month <= 7 ? (month - 1) * 31 : (month - 1) * 30 + 6) + (float)Math.Floor((epyear * 682 - 110) / 2816) + + (epyear - 1) * 365 + (float)Math.Floor(epbase / 2820) * 1029983 + (PersianEpoch - 1); + } + + private static int[] jd_to_gregorian(float jd) + { + var wjd = (float)(Math.Floor(jd - 0.5) + 0.5); + var depoch = wjd - GregorianEpoch; + var quadricent = (float)Math.Floor(depoch / 146097); + var dqc = (depoch % 146097); + var cent = (float)Math.Floor(dqc / 36524); + var dcent = dqc % 36524; + var quad = (float)Math.Floor(dcent / 1461); + var dquad = dcent % 1461; + var yindex = (float)Math.Floor(dquad / 365); + var year = (int)(quadricent * 400 + (cent * 100) + (quad * 4) + yindex); + if (!(Math.Abs(cent - 4) < Tolerance || Math.Abs(yindex - 4) < Tolerance)) + year++; + + var yearday = wjd - gregorian_to_jd(year, 1, 1); + float leapadj = wjd < gregorian_to_jd(year, 3, 1) ? 0 : leap_gregorian(year) ? 1 : 2; + var month = (int)Math.Floor(((yearday + leapadj) * 12 + 373) / 367); + var day = (int)(wjd - gregorian_to_jd(year, month, 1) + 1); + + var res = new[] { year, month, day }; + return res; + } + + //private static bool leap_Islamic(int year) + //{ + // return ((year * 11) + 14 % 30) < 11; + //} + + private static float islamic_to_jd(int year, int month, int day) + { + return (float)(day + Math.Ceiling(29.5 * (month - 1)) + (year - 1) * 354 + + Math.Floor((double)((3 + 11 * year) / 30)) + IslamicEpoch) - 1; + } + + private static int[] jd_to_islamic(float jd) + { + jd = (float) (Math.Floor(jd) + 0.5); + var year = (int) Math.Floor((30 * (jd - IslamicEpoch) + 10646) / 10631); + var month = (int) Math.Min(12, Math.Ceiling((jd - (29 + islamic_to_jd(year, 1, 1))) / 29.5) + 1); + var day = (int) (jd - islamic_to_jd(year, month, 1) + 1); + var res = new[] { year, month, day }; + return res; + } + } +} diff --git a/Persia .NET Core/LunarDate.cs b/Persia .NET Core/LunarDate.cs new file mode 100644 index 0000000..062e07a --- /dev/null +++ b/Persia .NET Core/LunarDate.cs @@ -0,0 +1,74 @@ +namespace Persia_.NET_Core +{ + public sealed class LunarDate + { + public int[] ArrayType { set; get; } + public int DayOfWeek { set; get; } + + public bool IsLeapYear => new System.Globalization.HijriCalendar().IsLeapYear(ArrayType[0]); + + private readonly string[] _lunarMonths = { "محرم", "صفر", "ربیع الاول", "ربیع الثانی", "جمادی الاولی", "جمادی الثانیة", "رجب", "شعبان", "رمضان", "شوال", "ذی قعده", "ذی حجّه" }; + private readonly string[] _lunarWeekDays = { "اسبت", "الاحد", "الاثنین", "اثلاثا", "الاربعا", "الخمیس", "اجمعه" }; + private readonly string[] _weekDays = { "شنبه", "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنج شنبه", "جمعه" }; + + public new string ToString() + { + var str1 = ArrayType[1].ToString(); + var str2 = ArrayType[2].ToString(); + if (ArrayType[1] < 10) + str1 = ArrayType[1].ToString().Insert(0, "0"); + if (ArrayType[2] < 10) + str2 = ArrayType[2].ToString().Insert(0, "0"); + + return $"{ArrayType[0]}/{str1}/{str2}"; + } + + public string ToString(string dateFormatSpecifier) + { + string dateFormat; + switch (dateFormatSpecifier) + { + case "M": + dateFormat = ConvertToArabic(ArrayType[2]) + " " + _lunarMonths[ArrayType[1] - 1] + " " + + ConvertToArabic(ArrayType[0]); + break; + case "D": + dateFormat = _weekDays[DayOfWeek] + " " + ConvertToArabic(ArrayType[2]) + " " + + _lunarMonths[ArrayType[1] - 1] + " " + ConvertToArabic(ArrayType[0]); + break; + case "N": + dateFormat = _lunarWeekDays[DayOfWeek] + " " + ConvertToArabic(ArrayType[2]) + " " + + _lunarMonths[ArrayType[1] - 1] + " " + ConvertToArabic(ArrayType[0]); + break; + case "H": + dateFormat = + $"{ConvertToArabic(ArrayType[0])} / {ConvertToArabic(ArrayType[1])} / {ConvertToArabic(ArrayType[2])}"; + break; + default: + dateFormat = + $"{ConvertToArabic(ArrayType[0])} / {ConvertToArabic(ArrayType[1])} / {ConvertToArabic(ArrayType[2])}"; + break; + } + return dateFormat; + } + + private static string ConvertToArabic(int number) + { + var num = number.ToString(); + var strOut = string.Empty; + var nLen = num.Length; + if (nLen == 0) + return num; + for (var i = 0; i < nLen; i++) + { + var ch = num[i]; + if ((48 <= ch) && (ch <= 57)) + { + ch = (char)(ch + 1584); + } + strOut += ch; + } + return strOut; //1632 + } + } +} diff --git a/Persia .NET Core/Persia .NET Core.csproj b/Persia .NET Core/Persia .NET Core.csproj new file mode 100644 index 0000000..31d54c1 --- /dev/null +++ b/Persia .NET Core/Persia .NET Core.csproj @@ -0,0 +1,8 @@ + + + + netcoreapp3.1 + Persia_.NET_Core + + + diff --git a/Persia .NET Core/PersianWord.cs b/Persia .NET Core/PersianWord.cs new file mode 100644 index 0000000..7985352 --- /dev/null +++ b/Persia .NET Core/PersianWord.cs @@ -0,0 +1,49 @@ +namespace Persia_.NET_Core +{ + public abstract class PersianWord + { + private PersianWord() + { + } + + public static string ToPersianString(object value) + { + var str = value; + var strOut = string.Empty; + var length = str.ToString().Length; + var nLen = length; + if (nLen == 0) + return str.ToString(); + for (var i = 0; i < nLen; i++) + { + var ch = str.ToString()[i]; + if ((48 <= ch) && (ch <= 57)) + ch = (char)(ch + 1728); + if (ch == 46) + ch = (char)47; + strOut += ch; + } + return strOut.Replace("ي", "ی").Replace("ك", "ک"); + } + + + public static string ConvertToLatinNumber(string num) + { + var strOut = ""; + var nLen = num.Length; + if (nLen == 0) + return num; + for (var i = 0; i < nLen; i++) + { + var ch = num[i]; + if ((1776 <= ch) && (ch <= 1785)) + { + ch = (char)(ch - 1728); + } + strOut += ch; + } + return strOut; + } + + } +} diff --git a/Persia .NET Core/SolarDate.cs b/Persia .NET Core/SolarDate.cs new file mode 100644 index 0000000..a413cc0 --- /dev/null +++ b/Persia .NET Core/SolarDate.cs @@ -0,0 +1,354 @@ +using System; + +namespace Persia_.NET_Core +{ + public sealed class SolarDate + { + public int[] ArrayType { set; get; } + internal DateTime dateTime { set; get; } + public int DayOfWeek { set; get; } + public int DaysPast + { + get + { + var date = Calendar.ConvertToGregorian(ArrayType[0], 1, 1, DateType.Persian); + var span = dateTime - date; + return span.Days; + } + } + public int DaysRemain + { + get + { + var date = Calendar.ConvertToGregorian(ArrayType[0]+1, 1, 1, DateType.Persian); + var span = date - dateTime; + return span.Days; + } + } + + readonly string[] _solarMonths = { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند" }; + + readonly string[] _days = {"یکم","دوم","سوم","چهارم","پنجم","ششم","هفتم","هشتم","نهم","دهم","یازدهم","دوازدهم","سیزدهم", + "چهاردهم","پانزدهم","شانزدهم","هفدهم","هجدهم","نوزدهم","بیستم","بیست و یکم","بیست و دوم", + "بیست و سوم","بیست و چهارم","بیست و پنجم","بیست و ششم","بیست و هفتم","بیست و هشتم","بیست و نهم","سی ام","سی و یکم"}; + + readonly string[] _weekDays = { "شنبه", "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنج شنبه", "جمعه" }; + + public bool IsLeapYear => ((ArrayType[0] - (ArrayType[0] > 0 ? 474 : 473)) % 2820 + 474 + 38) * 682 % 2816 < 682; + + public new string ToString() + { + var str1 = ArrayType[1].ToString(); + var str2 = ArrayType[2].ToString(); + if (ArrayType[1] < 10) + str1 = ArrayType[1].ToString().Insert(0, "0"); + if (ArrayType[2] < 10) + str2 = ArrayType[2].ToString().Insert(0, "0"); + + return $"{ArrayType[0]}/{str1}/{str2}"; + } + + public string ToString(string dateTimeFormatSpecifier) + { + string dateFormat; + var str = dateTimeFormatSpecifier.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + if (str.Length == 2) + dateFormat = ToString(str[0]) + " " + ToString(str[1]); + else + { + switch (dateTimeFormatSpecifier) + { + case "D": + dateFormat = PersianWord.ToPersianString(ArrayType[0]) + "/" + + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "d": + dateFormat = PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)) + "/" + + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "F": + dateFormat = PersianWord.ToPersianString(ArrayType[0]) + " " + _days[ArrayType[2] - 1] + " " + + _solarMonths[ArrayType[1] - 1]; + break; + case "f": + dateFormat = PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)) + " " + + _days[ArrayType[2] - 1] + " " + _solarMonths[ArrayType[1] - 1]; + break; + case "W": + dateFormat = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + + "/" + PersianWord.ToPersianString(ArrayType[2]) + " " + _weekDays[DayOfWeek]; + break; + case "w": + dateFormat = PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)) + "/" + + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]) + + " " + _weekDays[DayOfWeek]; + break; + case "S": + dateFormat = _weekDays[DayOfWeek] + " " + _days[ArrayType[2] - 1] + " " + + _solarMonths[ArrayType[1] - 1] + " " + PersianWord.ToPersianString(ArrayType[0]) + " "; + break; + case "s": + dateFormat = _weekDays[DayOfWeek] + " " + _days[ArrayType[2] - 1] + " " + + _solarMonths[ArrayType[1] - 1] + " " + + PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)) + " "; + break; + case "M": + dateFormat = PersianWord.ToPersianString(ArrayType[2]) + " " + _solarMonths[ArrayType[1] - 1] + " " + + PersianWord.ToPersianString(ArrayType[0]); + break; + case "m": + dateFormat = PersianWord.ToPersianString(ArrayType[2]) + " " + _solarMonths[ArrayType[1] - 1] + " " + + PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)); + break; + case "N": + dateFormat = _weekDays[DayOfWeek] + " " + PersianWord.ToPersianString(ArrayType[2]) + " " + + _solarMonths[ArrayType[1] - 1] + " " + PersianWord.ToPersianString(ArrayType[0]); + break; + case "n": + dateFormat = _weekDays[DayOfWeek] + " " + PersianWord.ToPersianString(ArrayType[2]) + " " + + _solarMonths[ArrayType[1] - 1] + " " + + PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)); + break; + case "g": + dateFormat = _weekDays[DayOfWeek] + " " + PersianWord.ToPersianString(ArrayType[2]) + " " + + _solarMonths[ArrayType[1] - 1]; + break; + case "E": + dateFormat = _solarMonths[ArrayType[1] - 1] + " " + PersianWord.ToPersianString(ArrayType[0]); + break; + case "e": + dateFormat = _solarMonths[ArrayType[1] - 1] + " " + + PersianWord.ToPersianString(ArrayType[0].ToString().Remove(0, 2)); + break; + case "Q": + dateFormat = PersianWord.ToPersianString(ArrayType[2]) + " " + _solarMonths[ArrayType[1] - 1]; + break; + case "q": + dateFormat = _days[ArrayType[2] - 1] + " " + _solarMonths[ArrayType[1] - 1]; + break; + case "L": + dateFormat = ToString().Remove(0, 2); + break; + case "H": + dateFormat = PersianWord.ToPersianString(ArrayType[3]) + ":" + PersianWord.ToPersianString(ArrayType[4]) + + ":" + PersianWord.ToPersianString(ArrayType[5]); + break; + case "R": + dateFormat = PersianWord.ToPersianString(ArrayType[3]) + ":" + PersianWord.ToPersianString(ArrayType[4]) + + ":" + PersianWord.ToPersianString(ArrayType[5]) + " " + "ساعت"; + break; + case "HH": + string noon; + if (ArrayType[3] > 12) + { + ArrayType[3] = ArrayType[3] - 12; + noon = "بعد از ظهر"; + } + else if (ArrayType[3] == 12) + noon = "بعد از ظهر"; + else + noon = "قبل از ظهر"; + dateFormat = PersianWord.ToPersianString(ArrayType[3]) + ":" + PersianWord.ToPersianString(ArrayType[4]) + + ":" + PersianWord.ToPersianString(ArrayType[5]) + " " + noon; + break; + case "hh": + if (ArrayType[3] > 12) + { + ArrayType[3] = ArrayType[3] - 12; + noon = "ب ظ"; + } + else if (ArrayType[3] == 12) + noon = "ب ظ"; + else + noon = "ق ظ"; + dateFormat = PersianWord.ToPersianString(ArrayType[3]) + ":" + PersianWord.ToPersianString(ArrayType[4]) + + ":" + PersianWord.ToPersianString(ArrayType[5]) + " " + noon; + break; + case "T": + if (ArrayType[3] > 12) + { + ArrayType[3] = ArrayType[3] - 12; + noon = "بعد از ظهر"; + } + else if (ArrayType[3] == 12) + noon = "بعد از ظهر"; + else + noon = "قبل از ظهر"; + dateFormat = "ساعت" + " " + PersianWord.ToPersianString(ArrayType[3]) + ":" + + PersianWord.ToPersianString(ArrayType[4]) + ":" + PersianWord.ToPersianString(ArrayType[5]) + + " " + noon; + break; + case "t": + if (ArrayType[3] > 12) + { + ArrayType[3] = ArrayType[3] - 12; + noon = "ب ظ"; + } + else if (ArrayType[3] == 12) + noon = "ب ظ"; + else + noon = "ق ظ"; + dateFormat = "ساعت" + " " + PersianWord.ToPersianString(ArrayType[3]) + ":" + + PersianWord.ToPersianString(ArrayType[4]) + ":" + PersianWord.ToPersianString(ArrayType[5]) + + " " + noon; + break; + default: + dateFormat = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + } + } + return dateFormat; + } + + public string ToRelativeDateString(string specifier) + { + string format; + var n = 0; + var m = 0; + var d = 0; + + var str = specifier.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + switch (str.Length) + { + case 1: + specifier = str[0]; + break; + case 2: + specifier = str[0]; + n = int.Parse(str[1]); + break; + case 3: + specifier = str[0]; + n = int.Parse(str[1]); + m = int.Parse(str[2]); + break; + case 4: + specifier = str[0]; + n = int.Parse(str[1]); + m = int.Parse(str[2]); + d = int.Parse(str[3]); + break; + } + + switch (specifier) + { + case "D": + var span = DateTime.Now - dateTime; + n = n == 0 ? 30 : n; + if (span.Days <= n && span.Days > 0) + format = $"{PersianWord.ToPersianString(span.Days)} روز پیش"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "T": + if (dateTime.Date == DateTime.Now.Date) + format = "امروز"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "Y": + if (dateTime.Date == DateTime.Now.Date) + format = "امروز"; + else if(dateTime.Date.AddDays(1) == DateTime.Now.Date) + format = "دیروز"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "TY": + if (dateTime.Date == DateTime.Now.Date) + format = "امروز"; + else if (dateTime.Date.AddDays(1) == DateTime.Now.Date) + format = "دیروز"; + else + { + n = n == 0 ? 7 : n; + format = ToRelativeDateString($"D,{n}"); + } + break; + case "N": + span = DateTime.Now - dateTime; + n = n == 0 ? 5 : n > 5 ? 5 : n; + if (span.TotalMinutes <= n && span.TotalMinutes > 0) + format = "اکنون"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "M": + span = DateTime.Now - dateTime; + n = n == 0 ? 60 : n > 60 ? 60 : n; + if (span.TotalMinutes <= n && span.TotalMinutes > 0) + format = string.Format("{0} دقیقه پیش", PersianWord.ToPersianString(span.Minutes)); + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "H": + span = DateTime.Now - dateTime; + n = n == 0 ? 24 : n > 24 ? 24 : n; + if (span.TotalHours <= n && span.TotalHours > 0) + format = string.Format("{0} ساعت پیش", PersianWord.ToPersianString(span.Hours)); + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "h": + span = DateTime.Now - dateTime; + if (span.TotalHours <= 1 && span.TotalHours > 0) + format = "کمتر از یک ساعت پیش"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "m": + span = DateTime.Now - dateTime; + if (span.TotalMinutes <= 1 && span.TotalMinutes > 0) + format = "کمتر از یک دقیقه پیش"; + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "n": + span = DateTime.Now - dateTime; + n = n == 0 ? 5 : n > 5 ? 5 : n; + m = m == 0 ? 60 : m > 60 ? 60 : m; + if (span.TotalMinutes <= n && span.TotalMinutes > 0) + format = "اکنون"; + else if (span.TotalMinutes <= m && span.TotalMinutes > 0) + format = ToRelativeDateString(string.Format("M,{0}",m)); + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "p": + span = DateTime.Now - dateTime; + n = n == 0 ? 5 : n > 5 ? 5 : n; + m = m == 0 ? 60 : m > 60 ? 60 : m; + d = d == 0 ? 24 : d > 24 ? 24 : d; + if (span.TotalMinutes <= n && span.TotalMinutes > 0) + format = "اکنون"; + else if (span.TotalMinutes <= m && span.TotalMinutes > 0) + format = ToRelativeDateString(string.Format("M,{0}", m)); + else if (span.TotalHours <= d && span.TotalHours > 0) + format = ToRelativeDateString(string.Format("H,{0}", d)); + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + case "t": + span = DateTime.Now - dateTime; + n = n == 0 ? 5 : n > 5 ? 5 : n; + m = m == 0 ? 60 : m > 60 ? 60 : m; + if (span.TotalMinutes <= n && span.TotalMinutes > 0) + format = "اکنون"; + else if (span.TotalMinutes <= m && span.TotalMinutes > 0) + format = ToRelativeDateString(string.Format("M,{0}", m)); + else if (DateTime.Now.Date == dateTime.Date) + format = ToRelativeDateString("Y"); + else + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + default: + format = PersianWord.ToPersianString(ArrayType[0]) + "/" + PersianWord.ToPersianString(ArrayType[1]) + "/" + PersianWord.ToPersianString(ArrayType[2]); + break; + } + + return format; + } + + } +}