├── MD.PersianDateTime.Standard ├── Icon │ └── PersianDateTime.png ├── MD.PersianDateTime.Standard.csproj.DotSettings ├── HijriDateTime.cs ├── PersianDayOfWeek.cs ├── MD.PersianDateTime.Standard.csproj ├── Helpers │ └── ExtensionsHelper.cs └── PersianDateTime.cs ├── MD.PersianDateTime ├── MD.PersianDateTime.csproj.DotSettings ├── HijriDateTime.cs ├── PersianDayOfWeek.cs ├── Properties │ └── AssemblyInfo.cs ├── Helpers │ └── ExtensionsHelper.cs ├── MD.PersianDateTime.csproj └── PersianDateTime.cs ├── MD.PersianDateTime.Standard.Test ├── MD.PersianDateTime.Standard.Test.csproj ├── CultureScope.cs ├── UseCultureAttribute.cs └── UnitTest1.cs ├── Properties └── AssemblyInfo.cs ├── .gitattributes ├── .gitignore ├── MD.PersianDateTime.sln └── README.md /MD.PersianDateTime.Standard/Icon/PersianDateTime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mds92/MD.PersianDateTime/HEAD/MD.PersianDateTime.Standard/Icon/PersianDateTime.png -------------------------------------------------------------------------------- /MD.PersianDateTime/MD.PersianDateTime.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/MD.PersianDateTime.Standard.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/HijriDateTime.cs: -------------------------------------------------------------------------------- 1 | namespace MD.PersianDateTime.Standard; 2 | 3 | /// 4 | /// تاریخ هجری قمری 5 | /// 6 | public struct HijriDateTime 7 | { 8 | /// 9 | /// سال قمری 10 | /// 11 | public int Year { get; set; } 12 | 13 | /// 14 | /// ماه قمری 15 | /// 16 | public int Month { get; set; } 17 | 18 | /// 19 | /// نام ماه قمری 20 | /// 21 | public string MonthName { get; set; } 22 | 23 | /// 24 | /// روز ماه قمری 25 | /// 26 | public int Day { get; set; } 27 | } -------------------------------------------------------------------------------- /MD.PersianDateTime/HijriDateTime.cs: -------------------------------------------------------------------------------- 1 | namespace MD.PersianDateTime 2 | { 3 | /// 4 | /// تاریخ هجری قمری 5 | /// 6 | public struct HijriDateTime 7 | { 8 | /// 9 | /// سال قمری 10 | /// 11 | public int Year { get; set; } 12 | 13 | /// 14 | /// ماه قمری 15 | /// 16 | public int Month { get; set; } 17 | 18 | /// 19 | /// نام ماه قمری 20 | /// 21 | public string MonthName { get; set; } 22 | 23 | /// 24 | /// روز ماه قمری 25 | /// 26 | public int Day { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard.Test/MD.PersianDateTime.Standard.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | preview 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/PersianDayOfWeek.cs: -------------------------------------------------------------------------------- 1 | namespace MD.PersianDateTime.Standard; 2 | 3 | /// 4 | /// روزهای شمسی هفته 5 | /// 6 | public enum PersianDayOfWeek 7 | { 8 | /// 9 | /// شنبه 10 | /// 11 | Saturday = 0, 12 | 13 | /// 14 | /// یکشنبه 15 | /// 16 | Sunday = 1, 17 | 18 | /// 19 | /// دو شنبه 20 | /// 21 | Monday = 2, 22 | 23 | /// 24 | /// سه شنبه 25 | /// 26 | Tuesday = 3, 27 | 28 | /// 29 | /// چهار شنبه 30 | /// 31 | Wednesday = 4, 32 | 33 | /// 34 | /// پنج شنبه 35 | /// 36 | Thursday = 5, 37 | 38 | /// 39 | /// جمعه 40 | /// 41 | Friday = 6 42 | } -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard.Test/CultureScope.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace MD.PersianDateTime.Standard.Test; 5 | 6 | public sealed class CultureScope : IDisposable 7 | { 8 | private readonly CultureInfo _originalCulture; 9 | private readonly CultureInfo _originalUiCulture; 10 | 11 | public CultureScope(string cultureName) 12 | { 13 | _originalCulture = CultureInfo.CurrentCulture; 14 | _originalUiCulture = CultureInfo.CurrentUICulture; 15 | 16 | var newCulture = new CultureInfo(cultureName); 17 | CultureInfo.CurrentCulture = newCulture; 18 | CultureInfo.CurrentUICulture = newCulture; 19 | } 20 | 21 | public void Dispose() 22 | { 23 | CultureInfo.CurrentCulture = _originalCulture; 24 | CultureInfo.CurrentUICulture = _originalUiCulture; 25 | } 26 | } -------------------------------------------------------------------------------- /MD.PersianDateTime/PersianDayOfWeek.cs: -------------------------------------------------------------------------------- 1 | namespace MD.PersianDateTime 2 | { 3 | /// 4 | /// روزهای شمسی هفته 5 | /// 6 | public enum PersianDayOfWeek 7 | { 8 | /// 9 | /// شنبه 10 | /// 11 | Saturday = 0, 12 | 13 | /// 14 | /// یکشنبه 15 | /// 16 | Sunday = 1, 17 | 18 | /// 19 | /// دو شنبه 20 | /// 21 | Monday = 2, 22 | 23 | /// 24 | /// سه شنبه 25 | /// 26 | Tuesday = 3, 27 | 28 | /// 29 | /// چهار شنبه 30 | /// 31 | Wednesday = 4, 32 | 33 | /// 34 | /// پنج شنبه 35 | /// 36 | Thursday = 5, 37 | 38 | /// 39 | /// جمعه 40 | /// 41 | Friday = 6 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard.Test/UseCultureAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Reflection; 4 | using Xunit.Sdk; 5 | 6 | namespace MD.PersianDateTime.Standard.Test; 7 | 8 | [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] 9 | public class UseCultureAttribute(string cultureName) : BeforeAfterTestAttribute 10 | { 11 | private readonly CultureInfo _testCulture = new(cultureName); 12 | private CultureInfo _originalCulture; 13 | private CultureInfo _originalUiCulture; 14 | 15 | public override void Before(MethodInfo methodUnderTest) 16 | { 17 | // ذخیره Culture فعلی 18 | _originalCulture = CultureInfo.CurrentCulture; 19 | _originalUiCulture = CultureInfo.CurrentUICulture; 20 | 21 | // تنظیم Culture جدید برای Thread جاری 22 | CultureInfo.CurrentCulture = _testCulture; 23 | CultureInfo.CurrentUICulture = _testCulture; 24 | } 25 | 26 | public override void After(MethodInfo methodUnderTest) 27 | { 28 | // بازگردانی به Culture قبلی 29 | if (_originalCulture != null) 30 | CultureInfo.CurrentCulture = _originalCulture; 31 | if (_originalUiCulture != null) 32 | CultureInfo.CurrentUICulture = _originalUiCulture; 33 | } 34 | } -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MD.PersianDateTime")] 8 | [assembly: AssemblyDescription("Created By Mohammad Dayyan, 1393-1394")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Written By Mohammad Dayyan, mds_soft@yahoo.com")] 11 | [assembly: AssemblyProduct("MD.PersianDateTime")] 12 | [assembly: AssemblyCopyright("Copyright © Mohammad Dayyan (mds_soft@yahoo.com) 2014-2015")] 13 | [assembly: AssemblyTrademark("Mohammad Dayyan")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("85ad36ff-1baf-4f41-aaa9-afc5989a7e10")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("3.3.0.0")] 35 | [assembly: AssemblyFileVersion("3.3.0.0")] 36 | -------------------------------------------------------------------------------- /MD.PersianDateTime/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("MD.PersianDateTime")] 8 | [assembly: AssemblyDescription("Created By Mohammad Dayyan, 1393-1394")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Written By Mohammad Dayyan, mds_soft@yahoo.com")] 11 | [assembly: AssemblyProduct("MD.PersianDateTime")] 12 | [assembly: AssemblyCopyright("Copyright © Mohammad Dayyan (mds_soft@yahoo.com) 2014-2015")] 13 | [assembly: AssemblyTrademark("Mohammad Dayyan")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("85ad36ff-1baf-4f41-aaa9-afc5989a7e10")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("4.6.0.0")] 35 | [assembly: AssemblyFileVersion("4.6.0.0")] 36 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/MD.PersianDateTime.Standard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | A C# library to use PersianCalendar as easy as DateTime 6 | Mohammad Dayyan - @mds1401 7 | https://licenses.nuget.org/MIT 8 | https://github.com/Mds92/MD.PersianDateTime 9 | https://github.com/Mds92/MD.PersianDateTime 10 | c# .net-standard persiandatetime datetime calendar 11 | true 12 | 2.6.0 13 | 2.6.0 14 | 2.6.0 15 | PersianDateTime.png 16 | 17 | Mohammad Dayyan 18 | Mohammad Dayyan 19 | Culture Improvements 20 | MD.PersianDateTime.Standard 21 | preview 22 | Apache-2.0 23 | 24 | 25 | 26 | bin\Release\netstandard2.0\MD.PersianDateTime.Standard.xml 27 | 28 | 29 | 30 | 31 | Code 32 | 33 | 34 | 35 | 36 | 37 | True 38 | \ 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/Helpers/ExtensionsHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace MD.PersianDateTime.Standard.Helpers; 4 | 5 | internal static class ExtensionsHelper 6 | { 7 | /// 8 | /// Convert all persian and arabic digit to english in any string 9 | /// 10 | /// 11 | /// input string that maybe contain persian or arabic digit 12 | /// a string with english digit 13 | internal static string ConvertDigitsToLatin(string inputString) 14 | { 15 | var sb = new StringBuilder(); 16 | 17 | foreach (var c in inputString) 18 | { 19 | switch (c) 20 | { 21 | case '\u06f0': //Persian digit 22 | case '\u0660': //Arabic digit 23 | sb.Append('0'); 24 | break; 25 | case '\u06f1': 26 | case '\u0661': 27 | sb.Append('1'); 28 | break; 29 | case '\u06f2': 30 | case '\u0662': 31 | sb.Append('2'); 32 | break; 33 | case '\u06f3': 34 | case '\u0663': 35 | sb.Append('3'); 36 | break; 37 | case '\u06f4': 38 | case '\u0664': 39 | sb.Append('4'); 40 | break; 41 | case '\u06f5': 42 | case '\u0665': 43 | sb.Append('5'); 44 | break; 45 | case '\u06f6': 46 | case '\u0666': 47 | sb.Append('6'); 48 | break; 49 | case '\u06f7': 50 | case '\u0667': 51 | sb.Append('7'); 52 | break; 53 | case '\u06f8': 54 | case '\u0668': 55 | sb.Append('8'); 56 | break; 57 | case '\u06f9': 58 | case '\u0669': 59 | sb.Append('9'); 60 | break; 61 | 62 | default: 63 | sb.Append(c); 64 | break; 65 | } 66 | } 67 | 68 | return sb.ToString(); 69 | } 70 | } -------------------------------------------------------------------------------- /MD.PersianDateTime/Helpers/ExtensionsHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace MD.PersianDateTime 4 | { 5 | internal static class ExtensionsHelper 6 | { 7 | /// 8 | /// Convert all persian and arabic digit to english in any string 9 | /// 10 | /// 11 | /// input string that maybe contain persian or arabic digit 12 | /// a string with english digit 13 | internal static string ConvertDigitsToLatin(string inputString) 14 | { 15 | var sb = new StringBuilder(); 16 | 17 | foreach (var c in inputString) 18 | { 19 | switch (c) 20 | { 21 | case '\u06f0': //Persian digit 22 | case '\u0660': //Arabic digit 23 | sb.Append('0'); 24 | break; 25 | case '\u06f1': 26 | case '\u0661': 27 | sb.Append('1'); 28 | break; 29 | case '\u06f2': 30 | case '\u0662': 31 | sb.Append('2'); 32 | break; 33 | case '\u06f3': 34 | case '\u0663': 35 | sb.Append('3'); 36 | break; 37 | case '\u06f4': 38 | case '\u0664': 39 | sb.Append('4'); 40 | break; 41 | case '\u06f5': 42 | case '\u0665': 43 | sb.Append('5'); 44 | break; 45 | case '\u06f6': 46 | case '\u0666': 47 | sb.Append('6'); 48 | break; 49 | case '\u06f7': 50 | case '\u0667': 51 | sb.Append('7'); 52 | break; 53 | case '\u06f8': 54 | case '\u0668': 55 | sb.Append('8'); 56 | break; 57 | case '\u06f9': 58 | case '\u0669': 59 | sb.Append('9'); 60 | break; 61 | 62 | default: 63 | sb.Append(c); 64 | break; 65 | } 66 | } 67 | 68 | return sb.ToString(); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /MD.PersianDateTime/MD.PersianDateTime.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | AnyCPU 7 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C} 8 | Library 9 | Properties 10 | MD.PersianDateTime 11 | MD.PersianDateTime 12 | v2.0 13 | 512 14 | SAK 15 | SAK 16 | SAK 17 | SAK 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 2 28 | false 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | bin\Release\MD.PersianDateTime.XML 38 | false 39 | 40 | 41 | false 42 | 43 | 44 | 45 | 46 | C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Core.dll 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Code 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | *.git/ 9 | *.nuget/ 10 | *.vs/ 11 | 12 | # Build results 13 | [Dd]ebug/ 14 | [Dd]ebugPublic/ 15 | [Rr]elease/ 16 | x64/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | ## TODO: Comment the next line if you want to checkin your 130 | ## web deploy settings but do note that will include unencrypted 131 | ## passwords 132 | #*.pubxml 133 | 134 | # NuGet Packages Directory 135 | packages/* 136 | ## TODO: If the tool you use requires repositories.config 137 | ## uncomment the next line 138 | #!packages/repositories.config 139 | 140 | # Enable "build/" folder in the NuGet Packages folder since 141 | # NuGet packages use it for MSBuild targets. 142 | # This line needs to be after the ignore of the build folder 143 | # (and the packages folder if the line above has been uncommented) 144 | !packages/build/ 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | sql/ 155 | *.Cache 156 | ClientBin/ 157 | [Ss]tyle[Cc]op.* 158 | ~$* 159 | *~ 160 | *.dbmdl 161 | *.dbproj.schemaview 162 | *.pfx 163 | *.publishsettings 164 | node_modules/ 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file 170 | # to a newer Visual Studio version. Backup files are not needed, 171 | # because we have git ;-) 172 | _UpgradeReport_Files/ 173 | Backup*/ 174 | UpgradeLog*.XML 175 | UpgradeLog*.htm 176 | 177 | # SQL Server files 178 | *.mdf 179 | *.ldf 180 | 181 | # Business Intelligence projects 182 | *.rdl.data 183 | *.bim.layout 184 | *.bim_*.settings 185 | 186 | # Microsoft Fakes 187 | FakesAssemblies/ 188 | 189 | # LightSwitch generated files 190 | GeneratedArtifacts/ 191 | _Pvt_Extensions/ 192 | ModelManifest.xml -------------------------------------------------------------------------------- /MD.PersianDateTime.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30330.147 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{A53E45BD-6B6E-4603-8EC4-723CBABA9B60}" 7 | ProjectSection(SolutionItems) = preProject 8 | .nuget\NuGet.Config = .nuget\NuGet.Config 9 | .nuget\NuGet.exe = .nuget\NuGet.exe 10 | .nuget\NuGet.targets = .nuget\NuGet.targets 11 | EndProjectSection 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MD.PersianDateTime", "MD.PersianDateTime\MD.PersianDateTime.csproj", "{21DB3B69-D93B-4E7F-9F52-672546F0F15C}" 14 | EndProject 15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MD.PersianDateTime.Standard", "MD.PersianDateTime.Standard\MD.PersianDateTime.Standard.csproj", "{A1061D11-41DF-4AD1-896B-9AEC48DF984A}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MD.PersianDateTime.Standard.Test", "MD.PersianDateTime.Standard.Test\MD.PersianDateTime.Standard.Test.csproj", "{7E3FBFB6-1E76-4252-8383-88326714D358}" 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Debug|x64 = Debug|x64 23 | Debug|x86 = Debug|x86 24 | Release|Any CPU = Release|Any CPU 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|x64.ActiveCfg = Debug|Any CPU 32 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|x64.Build.0 = Debug|Any CPU 33 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|x86.ActiveCfg = Debug|Any CPU 34 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Debug|x86.Build.0 = Debug|Any CPU 35 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|Any CPU.ActiveCfg = Release|Any CPU 36 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|Any CPU.Build.0 = Release|Any CPU 37 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|x64.ActiveCfg = Release|Any CPU 38 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|x64.Build.0 = Release|Any CPU 39 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|x86.ActiveCfg = Release|Any CPU 40 | {21DB3B69-D93B-4E7F-9F52-672546F0F15C}.Release|x86.Build.0 = Release|Any CPU 41 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|x64.ActiveCfg = Debug|Any CPU 44 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|x64.Build.0 = Debug|Any CPU 45 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|x86.ActiveCfg = Debug|Any CPU 46 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Debug|x86.Build.0 = Debug|Any CPU 47 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|Any CPU.ActiveCfg = Release|Any CPU 48 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|Any CPU.Build.0 = Release|Any CPU 49 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|x64.ActiveCfg = Release|Any CPU 50 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|x64.Build.0 = Release|Any CPU 51 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|x86.ActiveCfg = Release|Any CPU 52 | {A1061D11-41DF-4AD1-896B-9AEC48DF984A}.Release|x86.Build.0 = Release|Any CPU 53 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|x64.ActiveCfg = Debug|Any CPU 56 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|x64.Build.0 = Debug|Any CPU 57 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|x86.ActiveCfg = Debug|Any CPU 58 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Debug|x86.Build.0 = Debug|Any CPU 59 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|Any CPU.ActiveCfg = Release|Any CPU 60 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|Any CPU.Build.0 = Release|Any CPU 61 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|x64.ActiveCfg = Release|Any CPU 62 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|x64.Build.0 = Release|Any CPU 63 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|x86.ActiveCfg = Release|Any CPU 64 | {7E3FBFB6-1E76-4252-8383-88326714D358}.Release|x86.Build.0 = Release|Any CPU 65 | EndGlobalSection 66 | GlobalSection(SolutionProperties) = preSolution 67 | HideSolutionNode = FALSE 68 | EndGlobalSection 69 | GlobalSection(ExtensibilityGlobals) = postSolution 70 | SolutionGuid = {E451A89F-A93C-4FC4-8E0D-3A5B54983DBF} 71 | EndGlobalSection 72 | EndGlobal 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MD.PersianDateTime 2 | A C# library to use PersianCalendar as easy as DateTime 3 | تقویم شمسی و هجری قمری در C# 4 | 5 | ### Installing: 6 | 7 | .Net Framework 2+ 8 | ``` 9 | Install-Package MD.PersianDateTime 10 | ``` 11 | 12 | .Net Standard 2+ (.Net Core) 13 | ``` 14 | Install-Package MD.PersianDateTime.Standard 15 | ``` 16 | 17 | 18 | ### Coding: 19 | 20 | Creating new object: 21 | 1. New with DateTime object 22 | ```C# 23 | var persianDateTime = new PersianDateTime(DateTime.Now); 24 | ``` 25 | 26 | 2. New with persian date 27 | ```C# 28 | var persianDateTime = new PersianDateTime(1394, 5, 9); 29 | var persianDateTime = new PersianDateTime(1394, 5, 9, 10, 5, 3); 30 | var persianDateTime = new PersianDateTime(1394, 5, 9, 10, 5, 3, 103); 31 | ``` 32 | 33 | 3. Parse 34 | ```C# 35 | var persianDateTime1 = PersianDateTime.Parse("دوشنبه 05 مرداد 1395 ساعت 04:03"); 36 | var persianDateTime2 = PersianDateTime.Parse(13901229); // تاریخ 37 | var persianDateTime2 = PersianDateTime.Parse(13901229231232102); // تاریخ به همراه زمان تا دقت میلی ثانیه 38 | var persianDateTime3 = PersianDateTime.Parse("چهارشنبه، ۱۰ دی ۱۳۹۳ ۱۲:۳۸"); 39 | var persianDateTime4 = PersianDateTime.Parse("24 آذر 1393"); 40 | var persianDateTime5 = PersianDateTime.Parse("د 24 آذر 1393 4:2:5:5 ب.ظ"); 41 | var persianDateTime6 = PersianDateTime.Parse("1393/02/01"); 42 | var persianDateTime7 = PersianDateTime.Parse("1393/02/01 02:03"); 43 | var persianDateTime8 = PersianDateTime.Parse("1393-02-01 02:03:10:30"); 44 | var persianDateTime9 = PersianDateTime.Parse("93-1-1 3:15 ب.ظ"); 45 | var persianDateTime10 = PersianDateTime.Parse("جمعه 93/2/1 ساعت 3:2 ب.ظ"); 46 | ``` 47 | 48 | 4. Today, Now 49 | ```C# 50 | var persianDateTime1 = PersianDateTime.Now; 51 | var persianDateTime2 = PersianDateTime.Today; // without time 52 | ``` 53 | 54 | ------------------------------------------ 55 | ### Enable persian numbers 56 | ```C# 57 | var persianDateTime = PersianDateTime.Parse("چهارشنبه 5 آذر 58"); 58 | persianDateTime.PersianNumber = true; 59 | Console.Write(PersianDateTime.Now.ToString("yyyy/MM/dd")); 60 | // ۱۳۹۹/۱۰/۰۳ 61 | ``` 62 | ------------------------------------------ 63 | ### Convert to DateTime 64 | PersianDateTime object can convert automatically to datetime without any redundant code 65 | ```C# 66 | DateTime dateTime = PersianDateTime.Now 67 | ``` 68 | Also you can use `ToDateTime` method 69 | ```C# 70 | DateTime datetime = persianDateTime.ToDateTime(); 71 | ``` 72 | ------------------------------------------ 73 | ### Get HijriDate 74 | ```C# 75 | var persianDateTimeNow = PersianDateTime.Now; 76 | var hijriDateTime = persianDateTimeNow.ToHijri(-1); 77 | Console.WriteLine($"{hijriDateTime.Year}-{hijriDateTime.Month}-{hijriDateTime.Day}"); 78 | ``` 79 | 80 | ------------------------------------------ 81 | ### Formats 82 | you can use the following formats in `ToString` method. 83 | ```C# 84 | yyyy: سال چهار رقمی 85 | yy: سال دو رقمی 86 | MMMM: نام فارسی ماه 87 | MM: عدد دو رقمی ماه 88 | M: عدد یک رقمی ماه 89 | dddd: نام فارسی روز هفته 90 | dd: عدد دو رقمی روز ماه 91 | d: عدد یک رقمی روز ماه 92 | HH: ساعت دو رقمی با فرمت 00 تا 24 93 | H: ساعت یک رقمی با فرمت 0 تا 24 94 | hh: ساعت دو رقمی با فرمت 00 تا 12 95 | h: ساعت یک رقمی با فرمت 0 تا 12 96 | mm: عدد دو رقمی دقیقه 97 | m: عدد یک رقمی دقیقه 98 | ss: ثانیه دو رقمی 99 | s: ثانیه یک رقمی 100 | fff: میلی ثانیه 3 رقمی 101 | ff: میلی ثانیه 2 رقمی 102 | f: میلی ثانیه یک رقمی 103 | tt: ب.ظ یا ق.ظ 104 | t: حرف اول از ب.ظ یا ق.ظ 105 | ``` 106 | ------------------------------------------ 107 | ### Some useful methods 108 | ``` 109 | IsSqlDateTime \\ Check datetime and return a boolean if it is valid for SQL 110 | IsChristianDate \\ Check if the input string is a christian datetime 111 | ElapsedTime \\ Get past time until now e.g: ۱ روز قبل 112 | Add*** \\ add day, month, year, ... to persian datetime 113 | Subtract*** \\ Subtract a datetime from current object 114 | GetDifferenceQuarter \\ Date Difference base on seasons 115 | ``` 116 | ------------------------------------------ 117 | ### Comparing 118 | You can compare two PersianDateTime object together with C# operators 119 | ```C# 120 | var persianDateTime1 = new PersianDateTime(1396, 03, 28); 121 | var persianDateTime2 = new PersianDateTime(1396, 03, 29); 122 | var persianDateTime3 = new PersianDateTime(1396, 03, 28); 123 | 124 | persianDateTime1 > persianDateTime2; // false 125 | persianDateTime1 < persianDateTime2; // true 126 | persianDateTime1 == persianDateTime3; // true 127 | persianDateTime1 != persianDateTime3; // false 128 | ``` 129 | 130 | ------------------------------------------ 131 | ### Add and Subtract with operator 132 | You can use + - operators 133 | ```C# 134 | var persianDateTime1 = new PersianDateTime(1396, 03, 28); 135 | 136 | persianDateTime1 = persianDateTime1 + new TimeSpan(0, 0, 12); // add 12 minutes 137 | persianDateTime1 = persianDateTime1 - new TimeSpan(0, 0, 1); // subtract 1 minutes 138 | persianDateTime1 = persianDateTime1.AddDays(1); // add one day 139 | persianDateTime1 = persianDateTime1.AddMonth(-1); // subtract 1 month 140 | . 141 | . 142 | . 143 | 144 | ``` 145 | -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xunit; 4 | 5 | namespace MD.PersianDateTime.Standard.Test; 6 | 7 | public class UnitTest1 8 | { 9 | [Fact] 10 | public void GetPersianDateOfLastDayOfMonth1() 11 | { 12 | var date = new PersianDateTime(1399, 5, 1); 13 | Assert.Equal(new PersianDateTime(date.Year, date.Month, date.GetMonthDays), date.GetPersianDateOfLastDayOfMonth()); 14 | } 15 | 16 | [Fact] 17 | public void GetPersianDateOfLastDayOfMonth2() 18 | { 19 | var date = new PersianDateTime(1399, 10, 1); 20 | Assert.Equal(new PersianDateTime(date.Year, date.Month, date.GetMonthDays), date.GetPersianDateOfLastDayOfMonth()); 21 | } 22 | 23 | [Fact] 24 | public void GetPersianDateOfLastDayOfMonth3() 25 | { 26 | var date = new PersianDateTime(1399, 12, 1); 27 | Assert.Equal(new PersianDateTime(date.Year, date.Month, date.GetMonthDays), date.GetPersianDateOfLastDayOfMonth()); 28 | } 29 | 30 | [Fact] 31 | public void GetPersianDateOfLastDayOfYear1() 32 | { 33 | var date1 = new PersianDateTime(1400, 1, 1); 34 | var date2 = new PersianDateTime(1400, 12, 29); 35 | Assert.Equal(date1.GetPersianDateOfLastDayOfYear(), date2); 36 | } 37 | 38 | [Fact] 39 | public void GetPersianWeekend() 40 | { 41 | var persianDateFriday1 = new PersianDateTime(1401, 7, 22); // جمعه 42 | var persianDateFriday2 = new PersianDateTime(1401, 7, 29); // جمعه 43 | var persianDateFriday3 = new PersianDateTime(1401, 8, 6); // جمعه 44 | var persianDateFriday4 = new PersianDateTime(1401, 8, 13); // جمعه 45 | 46 | Assert.Equal(persianDateFriday1.AddDays(-1).GetPersianWeekend(), persianDateFriday1); 47 | Assert.Equal(persianDateFriday1.AddDays(-5).GetPersianWeekend(), persianDateFriday1); 48 | Assert.Equal(persianDateFriday2.AddDays(-4).GetPersianWeekend(), persianDateFriday2); 49 | Assert.Equal(persianDateFriday2.AddDays(-6).GetPersianWeekend(), persianDateFriday2); 50 | Assert.Equal(persianDateFriday3.AddDays(-3).GetPersianWeekend(), persianDateFriday3); 51 | Assert.Equal(persianDateFriday4.AddDays(-6).GetPersianWeekend(), persianDateFriday4); 52 | Assert.Equal(persianDateFriday4.GetPersianWeekend(), persianDateFriday4); 53 | } 54 | 55 | [Fact] 56 | public void GetFirstDayOfWeek() 57 | { 58 | var persianDateSaturday1 = new PersianDateTime(1401, 7, 23); // شنبه 59 | var persianDateSaturday2 = new PersianDateTime(1401, 7, 30); // شنبه 60 | var persianDateSaturday3 = new PersianDateTime(1401, 8, 7); // شنبه 61 | var persianDateSaturday4 = new PersianDateTime(1401, 8, 14); // شنبه 62 | 63 | Assert.Equal(persianDateSaturday1.AddDays(1).GetFirstDayOfWeek(), persianDateSaturday1); 64 | Assert.Equal(persianDateSaturday1.AddDays(5).GetFirstDayOfWeek(), persianDateSaturday1); 65 | Assert.Equal(persianDateSaturday2.AddDays(4).GetFirstDayOfWeek(), persianDateSaturday2); 66 | Assert.Equal(persianDateSaturday2.AddDays(6).GetFirstDayOfWeek(), persianDateSaturday2); 67 | Assert.Equal(persianDateSaturday3.AddDays(3).GetFirstDayOfWeek(), persianDateSaturday3); 68 | Assert.Equal(persianDateSaturday4.AddDays(6).GetFirstDayOfWeek(), persianDateSaturday4); 69 | Assert.Equal(persianDateSaturday4.GetFirstDayOfWeek(), persianDateSaturday4); 70 | } 71 | 72 | [Fact] 73 | public void ToTimeShort1() 74 | { 75 | var date = new PersianDateTime(1399, 5, 1, 12, 20, 33); 76 | Assert.Equal(1220, date.ToTimeShort()); 77 | } 78 | 79 | [Fact] 80 | public void ToTimeShort2() 81 | { 82 | var date = new PersianDateTime(1402, 3, 22, 9, 8, 5); 83 | Assert.Equal(908, date.ToTimeShort()); 84 | } 85 | 86 | [Fact] 87 | public void ToTimeShort3() 88 | { 89 | var date = new PersianDateTime(1402, 3, 22, 9, 22, 15); 90 | Assert.Equal(922, date.ToTimeShort()); 91 | } 92 | 93 | [Theory] 94 | [InlineData("fr-CA")] 95 | [InlineData("fa-IR")] 96 | [InlineData("en-US")] 97 | [InlineData("ar-SA")] 98 | [InlineData("ar-LB")] 99 | public void TestPersianCulture1(string cultureName) 100 | { 101 | using (new CultureScope(cultureName)) 102 | { 103 | var persianDate = PersianDateTime.Parse("1404/07/20"); 104 | Assert.Equal("1404", persianDate.ToString("yyyy")); 105 | Assert.Equal("7", persianDate.ToString("M")); 106 | Assert.Equal("07", persianDate.ToString("MM")); 107 | Assert.Equal("20", persianDate.ToString("dd")); 108 | } 109 | } 110 | 111 | [Theory] 112 | [InlineData("fr-CA")] 113 | [InlineData("fa-IR")] 114 | [InlineData("en-US")] 115 | [InlineData("ar-SA")] 116 | [InlineData("ar-LB")] 117 | public void TestPersianCulture2(string cultureName) 118 | { 119 | using (new CultureScope(cultureName)) 120 | { 121 | var persianDate = new PersianDateTime(1404, 07, 20, 1, 1, 1, 123); 122 | var result = persianDate.ToString("fff"); 123 | Assert.Contains("123", result); 124 | } 125 | } 126 | 127 | [Theory] 128 | [InlineData("fr-CA")] 129 | [InlineData("fa-IR")] 130 | [InlineData("en-US")] 131 | [InlineData("ar-SA")] 132 | [InlineData("ar-LB")] 133 | public void TestPersianCulture3(string cultureName) 134 | { 135 | using (new CultureScope(cultureName)) 136 | { 137 | var persianDate = new PersianDateTime(new DateTime(2025, 10, 09)); 138 | Assert.Equal(1404, persianDate.Year); 139 | Assert.Equal(7, persianDate.Month); 140 | Assert.Equal(17, persianDate.Day); 141 | } 142 | } 143 | 144 | [Theory] 145 | [InlineData("fr-CA")] 146 | [InlineData("fa-IR")] 147 | [InlineData("en-US")] 148 | [InlineData("ar-SA")] 149 | [InlineData("ar-LB")] 150 | public void TestPersianCulture4(string cultureName) 151 | { 152 | using (new CultureScope(cultureName)) 153 | { 154 | var dateTime = DateTime.Parse("2025-10-09", CultureInfo.InvariantCulture); 155 | var persianDate = new PersianDateTime(dateTime); 156 | Assert.Equal(1404, persianDate.Year); 157 | Assert.Equal(7, persianDate.Month); 158 | Assert.Equal(17, persianDate.Day); 159 | } 160 | } 161 | 162 | [Theory] 163 | [InlineData("fr-CA")] 164 | [InlineData("fa-IR")] 165 | [InlineData("en-US")] 166 | [InlineData("ar-SA")] 167 | [InlineData("ar-LB")] 168 | public void TestPersianCulture5(string cultureName) 169 | { 170 | using (new CultureScope(cultureName)) 171 | { 172 | var dateTime = DateTime.Parse("2025-10-09", CultureInfo.InvariantCulture); 173 | Assert.Equal(2025, dateTime.Year); 174 | Assert.Equal(10, dateTime.Month); 175 | Assert.Equal(09, dateTime.Day); 176 | } 177 | } 178 | 179 | [Theory] 180 | [InlineData("fr-CA")] 181 | [InlineData("fa-IR")] 182 | [InlineData("en-US")] 183 | [InlineData("ar-SA")] 184 | [InlineData("ar-LB")] 185 | public void TestPersianCulture6(string cultureName) 186 | { 187 | using (new CultureScope(cultureName)) 188 | { 189 | var persianDate = new PersianDateTime(1404, 07, 20, 1, 1, 1, 123); 190 | var result1 = persianDate.ToString("yyyy", CultureInfo.GetCultureInfo(cultureName)); 191 | var result2 = persianDate.ToString("yyyy", CultureInfo.InvariantCulture); 192 | var result3 = persianDate.ToString("yyyy"); 193 | Assert.Equal("1404", result1); 194 | Assert.Equal("1404", result2); 195 | Assert.Equal("1404", result3); 196 | } 197 | } 198 | 199 | [Theory] 200 | [InlineData("fr-CA")] 201 | [InlineData("fa-IR")] 202 | [InlineData("en-US")] 203 | [InlineData("ar-SA")] 204 | [InlineData("ar-LB")] 205 | public void TestPersianCulture7(string cultureName) 206 | { 207 | using (new CultureScope(cultureName)) 208 | { 209 | var persianDate = new PersianDateTime(1404, 07, 20, 1, 1, 1, 123); 210 | Assert.Equal(1404, persianDate.Year); 211 | Assert.Equal(7, persianDate.Month); 212 | Assert.Equal(20, persianDate.Day); 213 | } 214 | } 215 | 216 | [Theory] 217 | [InlineData("fr-CA")] 218 | [InlineData("fa-IR")] 219 | [InlineData("en-US")] 220 | [InlineData("ar-SA")] 221 | [InlineData("ar-LB")] 222 | public void TestPersianCulture8(string cultureName) 223 | { 224 | using (new CultureScope(cultureName)) 225 | { 226 | var persianDate = PersianDateTime.Parse("1404-07-20"); 227 | Assert.Equal("1404", persianDate.ToString("yyyy")); 228 | Assert.Equal("7", persianDate.ToString("M")); 229 | Assert.Equal("07", persianDate.ToString("MM")); 230 | Assert.Equal("20", persianDate.ToString("dd")); 231 | } 232 | } 233 | 234 | } -------------------------------------------------------------------------------- /MD.PersianDateTime.Standard/PersianDateTime.cs: -------------------------------------------------------------------------------- 1 | using MD.PersianDateTime.Standard.Helpers; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Runtime.Serialization; 7 | using System.Text.RegularExpressions; 8 | 9 | // ReSharper disable UnusedMember.Local 10 | 11 | namespace MD.PersianDateTime.Standard; 12 | 13 | /// 14 | /// Created By Mohammad Dayyan, @mdssoft 15 | /// 1397/01/10 16 | /// 17 | [Serializable] 18 | public struct PersianDateTime : 19 | ISerializable, IFormattable, IConvertible, 20 | IComparable, IComparable, 21 | IEquatable, IEquatable 22 | { 23 | #region properties and fields 24 | 25 | private static PersianCalendar _persianCalendar; 26 | private static PersianCalendar PersianCalendar 27 | { 28 | get 29 | { 30 | if (_persianCalendar != null) return _persianCalendar; 31 | _persianCalendar = new PersianCalendar(); 32 | return _persianCalendar; 33 | } 34 | } 35 | private readonly DateTime _dateTime; 36 | 37 | /// 38 | /// آیا اعداد در خروجی به صورت انگلیسی نمایش داده شوند؟ 39 | /// 40 | public bool PersianNumber { get; set; } 41 | 42 | /// 43 | /// سال شمسی 44 | /// 45 | public int Year 46 | { 47 | get 48 | { 49 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Year; 50 | return PersianCalendar.GetYear(_dateTime); 51 | } 52 | } 53 | 54 | /// 55 | /// ماه شمسی 56 | /// 57 | public int Month 58 | { 59 | get 60 | { 61 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Month; 62 | return PersianCalendar.GetMonth(_dateTime); 63 | } 64 | } 65 | 66 | /// 67 | /// نام فارسی ماه 68 | /// 69 | public string MonthName => ((PersianDateTimeMonthEnum)Month).ToString(); 70 | 71 | /// 72 | /// روز ماه 73 | /// 74 | public int Day 75 | { 76 | get 77 | { 78 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Day; 79 | return PersianCalendar.GetDayOfMonth(_dateTime); 80 | } 81 | } 82 | 83 | /// 84 | /// روز هفته 85 | /// 86 | public DayOfWeek DayOfWeek 87 | { 88 | get 89 | { 90 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.DayOfWeek; 91 | return PersianCalendar.GetDayOfWeek(_dateTime); 92 | } 93 | } 94 | 95 | /// 96 | /// روز هفته یا ایندکس شمسی 97 | /// 98 | /// شنبه دارای ایندکس صفر است 99 | /// 100 | public PersianDayOfWeek PersianDayOfWeek 101 | { 102 | get 103 | { 104 | var dayOfWeek = PersianCalendar.GetDayOfWeek(_dateTime); 105 | // ReSharper disable once InconsistentNaming 106 | PersianDayOfWeek persianDayOfWeek; 107 | switch (dayOfWeek) 108 | { 109 | case DayOfWeek.Sunday: 110 | persianDayOfWeek = PersianDayOfWeek.Sunday; 111 | break; 112 | case DayOfWeek.Monday: 113 | persianDayOfWeek = PersianDayOfWeek.Monday; 114 | break; 115 | case DayOfWeek.Tuesday: 116 | persianDayOfWeek = PersianDayOfWeek.Tuesday; 117 | break; 118 | case DayOfWeek.Wednesday: 119 | persianDayOfWeek = PersianDayOfWeek.Wednesday; 120 | break; 121 | case DayOfWeek.Thursday: 122 | persianDayOfWeek = PersianDayOfWeek.Thursday; 123 | break; 124 | case DayOfWeek.Friday: 125 | persianDayOfWeek = PersianDayOfWeek.Friday; 126 | break; 127 | case DayOfWeek.Saturday: 128 | persianDayOfWeek = PersianDayOfWeek.Saturday; 129 | break; 130 | default: 131 | throw new ArgumentOutOfRangeException(); 132 | } 133 | return persianDayOfWeek; 134 | } 135 | } 136 | 137 | /// 138 | /// ساعت 139 | /// 140 | public int Hour 141 | { 142 | get 143 | { 144 | if (_dateTime <= DateTime.MinValue) return 12; 145 | return PersianCalendar.GetHour(_dateTime); 146 | } 147 | } 148 | 149 | /// 150 | /// ساعت دو رقمی 151 | /// 152 | public int ShortHour 153 | { 154 | get 155 | { 156 | int shortHour; 157 | if (Hour > 12) 158 | shortHour = Hour - 12; 159 | else 160 | shortHour = Hour; 161 | return shortHour; 162 | } 163 | } 164 | 165 | /// 166 | /// دقیقه 167 | /// 168 | public int Minute 169 | { 170 | get 171 | { 172 | if (_dateTime <= DateTime.MinValue) return 0; 173 | return PersianCalendar.GetMinute(_dateTime); 174 | } 175 | } 176 | 177 | /// 178 | /// ثانیه 179 | /// 180 | public int Second 181 | { 182 | get 183 | { 184 | if (_dateTime <= DateTime.MinValue) return 0; 185 | return PersianCalendar.GetSecond(_dateTime); 186 | } 187 | } 188 | 189 | /// 190 | /// میلی ثانیه 191 | /// 192 | public int Millisecond 193 | { 194 | get 195 | { 196 | if (_dateTime <= DateTime.MinValue) return 0; 197 | return (int)PersianCalendar.GetMilliseconds(_dateTime); 198 | } 199 | } 200 | 201 | /// 202 | /// تعداد روز در ماه 203 | /// 204 | public int GetMonthDays 205 | { 206 | get 207 | { 208 | int days; 209 | switch (Month) 210 | { 211 | case 1: 212 | case 2: 213 | case 3: 214 | case 4: 215 | case 5: 216 | case 6: 217 | days = 31; 218 | break; 219 | 220 | case 7: 221 | case 8: 222 | case 9: 223 | case 10: 224 | case 11: 225 | days = 30; 226 | break; 227 | 228 | case 12: 229 | { 230 | if (IsLeapYear) days = 30; 231 | else days = 29; 232 | break; 233 | } 234 | 235 | default: 236 | throw new Exception("Month number is wrong !!!"); 237 | } 238 | return days; 239 | } 240 | } 241 | 242 | /// 243 | /// هفته چندم سال 244 | /// 245 | public int GetWeekOfYear 246 | { 247 | get 248 | { 249 | if (_dateTime <= DateTime.MinValue) return 0; 250 | return PersianCalendar.GetWeekOfYear(_dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Saturday); 251 | } 252 | } 253 | 254 | /// 255 | /// هفته چندم ماه 256 | /// 257 | public int GetWeekOfMonth 258 | { 259 | get 260 | { 261 | if (_dateTime <= DateTime.MinValue) return 0; 262 | var persianDateTime = AddDays(1 - Day); 263 | return GetWeekOfYear - persianDateTime.GetWeekOfYear + 1; 264 | } 265 | } 266 | 267 | /// 268 | /// روز چندم سال 269 | /// 270 | public int GetDayOfYear 271 | { 272 | get 273 | { 274 | if (_dateTime <= DateTime.MinValue) return 0; 275 | return PersianCalendar.GetDayOfYear(_dateTime); 276 | } 277 | } 278 | 279 | /// 280 | /// آیا سال کبیسه است؟ 281 | /// 282 | public bool IsLeapYear 283 | { 284 | get 285 | { 286 | if (_dateTime <= DateTime.MinValue) return false; 287 | return PersianCalendar.IsLeapYear(Year); 288 | } 289 | } 290 | 291 | /// 292 | /// قبل از ظهر، بعد از ظهر 293 | /// 294 | private AmPmEnum PersianAmPm => _dateTime.ToString("tt", CultureInfo.InvariantCulture) == "PM" ? AmPmEnum.PM : AmPmEnum.AM; 295 | 296 | /// 297 | /// قبل از ظهر، بعد از ظهر به شکل مخفف . کوتاه 298 | /// 299 | public string GetPersianAmPm 300 | { 301 | get 302 | { 303 | var result = string.Empty; 304 | switch (PersianAmPm) 305 | { 306 | case AmPmEnum.AM: 307 | result = "ق.ظ"; 308 | break; 309 | 310 | case AmPmEnum.PM: 311 | result = "ب.ظ"; 312 | break; 313 | } 314 | return result; 315 | } 316 | } 317 | 318 | /// 319 | /// نام کامل ماه 320 | /// 321 | public string GetLongMonthName => GetPersianMonthNamePrivate(Month); 322 | 323 | /// 324 | /// سال دو رقمی 325 | /// 326 | public int GetShortYear => Year % 100; 327 | 328 | /// 329 | /// نام کامل روز 330 | /// 331 | public string GetLongDayOfWeekName 332 | { 333 | get 334 | { 335 | string weekDayName = null; 336 | switch (DayOfWeek) 337 | { 338 | case DayOfWeek.Sunday: 339 | weekDayName = PersianWeekDaysStruct.یکشنبه.Value; 340 | break; 341 | 342 | case DayOfWeek.Monday: 343 | weekDayName = PersianWeekDaysStruct.دوشنبه.Value; 344 | break; 345 | 346 | case DayOfWeek.Tuesday: 347 | weekDayName = PersianWeekDaysStruct.سه_شنبه.Value; 348 | break; 349 | 350 | case DayOfWeek.Wednesday: 351 | weekDayName = PersianWeekDaysStruct.چهارشنبه.Value; 352 | break; 353 | 354 | case DayOfWeek.Thursday: 355 | weekDayName = PersianWeekDaysStruct.پنجشنبه.Value; 356 | break; 357 | 358 | case DayOfWeek.Friday: 359 | weekDayName = PersianWeekDaysStruct.جمعه.Value; 360 | break; 361 | 362 | case DayOfWeek.Saturday: 363 | weekDayName = PersianWeekDaysStruct.شنبه.Value; 364 | break; 365 | } 366 | return weekDayName; 367 | } 368 | } 369 | 370 | /// 371 | /// نام یک حرفی روز، حرف اول روز 372 | /// 373 | public string GetShortDayOfWeekName 374 | { 375 | get 376 | { 377 | string weekDayName = null; 378 | switch (DayOfWeek) 379 | { 380 | case DayOfWeek.Sunday: 381 | weekDayName = "ی"; 382 | break; 383 | 384 | case DayOfWeek.Monday: 385 | weekDayName = "د"; 386 | break; 387 | 388 | case DayOfWeek.Tuesday: 389 | weekDayName = "س"; 390 | break; 391 | 392 | case DayOfWeek.Wednesday: 393 | weekDayName = "چ"; 394 | break; 395 | 396 | case DayOfWeek.Thursday: 397 | weekDayName = "پ"; 398 | break; 399 | 400 | case DayOfWeek.Friday: 401 | weekDayName = "ج"; 402 | break; 403 | 404 | case DayOfWeek.Saturday: 405 | weekDayName = "ش"; 406 | break; 407 | } 408 | 409 | return weekDayName; 410 | } 411 | } 412 | 413 | /// 414 | /// تاریخ و زمان همین الان 415 | /// 416 | public static PersianDateTime Now => new(DateTime.Now); 417 | 418 | /// 419 | /// تاریخ امروز 420 | /// 421 | public static PersianDateTime Today => new(DateTime.Today); 422 | 423 | /// 424 | /// زمان به فرمتی مشابه 425 | /// 426 | /// 13:47:40:530 427 | /// 428 | public string TimeOfDay 429 | { 430 | get 431 | { 432 | var result = $"{Hour:00}:{Minute:00}:{Second:00}:{Millisecond:000}"; 433 | if (!PersianNumber) return result; 434 | return ToPersianNumber(result); 435 | } 436 | } 437 | 438 | /// 439 | /// زمان به فرمتی مشابه زیر 440 | /// 441 | /// ساعت 01:47:40:530 ب.ظ 442 | /// 443 | public string LongTimeOfDay 444 | { 445 | get 446 | { 447 | var result = $"ساعت {ShortHour:00}:{Minute:00}:{Second:00}:{Millisecond:000} {GetPersianAmPm}"; 448 | if (!PersianNumber) return result; 449 | return ToPersianNumber(result); 450 | } 451 | } 452 | 453 | /// 454 | /// زمان به فرمتی مشابه زیر 455 | /// 456 | /// 01:47:40 ب.ظ 457 | /// 458 | public string ShortTimeOfDay 459 | { 460 | get 461 | { 462 | var result = $"{ShortHour:00}:{Minute:00}:{Second:00} {GetPersianAmPm}"; 463 | if (!PersianNumber) return result; 464 | return ToPersianNumber(result); 465 | } 466 | } 467 | 468 | /// 469 | /// تاریخ بدون احتساب زمان 470 | /// 471 | public PersianDateTime Date 472 | { 473 | get 474 | { 475 | var persianDateTime = new PersianDateTime(Year, Month, Day) 476 | { 477 | PersianNumber = PersianNumber 478 | }; 479 | return persianDateTime; 480 | } 481 | } 482 | 483 | /// 484 | /// حداقل مقدار 485 | /// 486 | public static PersianDateTime MinValue => new(DateTime.MinValue); 487 | 488 | /// 489 | /// حداکثر مقدار 490 | /// 491 | public static PersianDateTime MaxValue => new(DateTime.MaxValue); 492 | 493 | #endregion 494 | 495 | #region ctor 496 | 497 | /// 498 | /// متد سازنده برای دی سریالایز شدن 499 | /// 500 | private PersianDateTime(SerializationInfo info, StreamingContext context) 501 | : this() 502 | { 503 | _dateTime = info.GetDateTime("DateTime"); 504 | PersianNumber = info.GetBoolean("PersianNumber"); 505 | } 506 | 507 | /// 508 | /// مقدار دهی اولیه با استفاده از دیت تایم میلادی 509 | /// 510 | /// DateTime 511 | /// آیا اعداد در خروجی های این آبجکت به صورت فارسی نمایش داده شوند یا فارسی؟ 512 | private PersianDateTime(DateTime dateTime, bool persianNumber) 513 | : this() 514 | { 515 | _dateTime = dateTime; 516 | PersianNumber = persianNumber; 517 | } 518 | 519 | /// 520 | /// مقدار دهی اولیه با استفاده از دیت تایم میلادی 521 | /// 522 | public PersianDateTime(DateTime dateTime) 523 | : this() 524 | { 525 | _dateTime = dateTime; 526 | } 527 | 528 | /// 529 | /// مقدار دهی اولیه با استفاده از دیت تایم قابل نال میلادی 530 | /// 531 | public PersianDateTime(DateTime? nullableDateTime) 532 | : this() 533 | { 534 | if (!nullableDateTime.HasValue) 535 | { 536 | _dateTime = DateTime.MinValue; 537 | return; 538 | } 539 | _dateTime = nullableDateTime.Value; 540 | } 541 | 542 | /// 543 | /// مقدار دهی اولیه 544 | /// 545 | /// سال شمسی 546 | /// ماه شمسی 547 | /// روز شمسی 548 | public PersianDateTime(int persianYear, int persianMonth, int persianDay) 549 | : this() 550 | { 551 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, 0, 0, 0, 0); 552 | } 553 | 554 | /// 555 | /// مقدار دهی اولیه 556 | /// 557 | /// سال شمسی 558 | /// ماه شمسی 559 | /// روز شمسی 560 | /// ساعت 561 | /// دقیقه 562 | /// ثانیه 563 | public PersianDateTime(int persianYear, int persianMonth, int persianDay, int hour, int minute, int second) 564 | : this() 565 | { 566 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, hour, minute, second, 0); 567 | } 568 | 569 | /// 570 | /// مقدار دهی اولیه 571 | /// 572 | /// سال شمسی 573 | /// ماه شمسی 574 | /// روز شمسی 575 | /// سال 576 | /// دقیقه 577 | /// ثانیه 578 | /// میلی ثانیه 579 | public PersianDateTime(int persianYear, int persianMonth, int persianDay, int hour, int minute, int second, int milliseconds) 580 | : this() 581 | { 582 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, hour, minute, second, milliseconds); 583 | } 584 | 585 | #endregion 586 | 587 | #region Types 588 | 589 | private enum AmPmEnum 590 | { 591 | // ReSharper disable once InconsistentNaming 592 | AM = 0, 593 | // ReSharper disable once InconsistentNaming 594 | PM = 1, 595 | None = 2 596 | } 597 | 598 | private enum PersianDateTimeMonthEnum 599 | { 600 | فروردین = 1, 601 | اردیبهشت = 2, 602 | خرداد = 3, 603 | تیر = 4, 604 | مرداد = 5, 605 | شهریور = 6, 606 | مهر = 7, 607 | آبان = 8, 608 | آذر = 9, 609 | دی = 10, 610 | بهمن = 11, 611 | اسفند = 12 612 | } 613 | 614 | private struct PersianWeekDaysStruct 615 | { 616 | public static KeyValuePair شنبه => new((int)DayOfWeek.Saturday, "شنبه"); 617 | public static KeyValuePair یکشنبه => new((int)DayOfWeek.Sunday, "یکشنبه"); 618 | public static KeyValuePair دوشنبه => new((int)DayOfWeek.Monday, "دوشنبه"); 619 | // ReSharper disable once InconsistentNaming 620 | public static KeyValuePair سه_شنبه => new((int)DayOfWeek.Tuesday, "سه شنبه"); 621 | public static KeyValuePair چهارشنبه => new((int)DayOfWeek.Thursday, "چهارشنبه"); 622 | public static KeyValuePair پنجشنبه => new((int)DayOfWeek.Wednesday, "پنج شنبه"); 623 | public static KeyValuePair جمعه => new((int)DayOfWeek.Friday, "جمعه"); 624 | } 625 | 626 | #endregion 627 | 628 | #region override 629 | 630 | /// 631 | /// تبدیل تاریخ به رشته با فرمت مشابه زیر 632 | /// 633 | /// 1393/09/14 13:49:40 634 | /// 635 | public override string ToString() 636 | { 637 | return ToString(""); 638 | } 639 | 640 | /// 641 | public override bool Equals(object obj) 642 | { 643 | if (obj is not PersianDateTime) return false; 644 | var persianDateTime = (PersianDateTime)obj; 645 | return _dateTime == persianDateTime.ToDateTime(); 646 | } 647 | 648 | /// 649 | public override int GetHashCode() 650 | { 651 | return _dateTime.GetHashCode(); 652 | } 653 | 654 | /// 655 | /// مقایسه با تاریخ دیگر 656 | /// 657 | /// مقدار بازگشتی همانند مقدار بازگشتی متد کامپیر در دیت تایم دات نت است 658 | public int CompareTo(PersianDateTime otherPersianDateTime) 659 | { 660 | return _dateTime.CompareTo(otherPersianDateTime.ToDateTime()); 661 | } 662 | 663 | /// 664 | /// مقایسه با تاریخ دیگر 665 | /// 666 | /// مقدار بازگشتی همانند مقدار بازگشتی متد کامپیر در دیت تایم دات نت است 667 | public int CompareTo(DateTime otherDateTime) 668 | { 669 | return _dateTime.CompareTo(otherDateTime); 670 | } 671 | 672 | #region operators 673 | 674 | /// 675 | /// تبدیل خودکار به دیت تایم میلادی 676 | /// 677 | public static implicit operator DateTime(PersianDateTime persianDateTime) 678 | { 679 | return persianDateTime.ToDateTime(); 680 | } 681 | 682 | /// 683 | /// اپراتور برابر 684 | /// 685 | public static bool operator ==(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 686 | { 687 | return persianDateTime1.Equals(persianDateTime2); 688 | } 689 | 690 | /// 691 | /// اپراتور نامساوی 692 | /// 693 | public static bool operator !=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 694 | { 695 | return !persianDateTime1.Equals(persianDateTime2); 696 | } 697 | 698 | /// 699 | /// اپراتور بزرگتری 700 | /// 701 | public static bool operator >(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 702 | { 703 | return persianDateTime1.ToDateTime() > persianDateTime2.ToDateTime(); 704 | } 705 | 706 | /// 707 | /// اپراتور کوچکتری 708 | /// 709 | public static bool operator <(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 710 | { 711 | return persianDateTime1.ToDateTime() < persianDateTime2.ToDateTime(); 712 | } 713 | 714 | /// 715 | /// اپراتور بزرگتر مساوی 716 | /// 717 | public static bool operator >=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 718 | { 719 | return persianDateTime1.ToDateTime() >= persianDateTime2.ToDateTime(); 720 | } 721 | 722 | /// 723 | /// اپراتور کوچکتر مساوی 724 | /// 725 | public static bool operator <=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 726 | { 727 | return persianDateTime1.ToDateTime() <= persianDateTime2.ToDateTime(); 728 | } 729 | 730 | /// 731 | /// اپراتور جمع تو زمان 732 | /// 733 | public static PersianDateTime operator +(PersianDateTime persianDateTime1, TimeSpan timeSpanToAdd) 734 | { 735 | DateTime dateTime1 = persianDateTime1; 736 | return new PersianDateTime(dateTime1.Add(timeSpanToAdd)); 737 | } 738 | 739 | /// 740 | /// اپراتور کم کردن دو زمان از هم 741 | /// 742 | public static TimeSpan operator -(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 743 | { 744 | DateTime dateTime1 = persianDateTime1; 745 | DateTime dateTime2 = persianDateTime2; 746 | return dateTime1 - dateTime2; 747 | } 748 | 749 | #endregion 750 | 751 | #endregion 752 | 753 | #region ISerializable 754 | 755 | /// 756 | public void GetObjectData(SerializationInfo info, StreamingContext context) 757 | { 758 | info.AddValue("DateTime", ToDateTime()); 759 | info.AddValue("PersianNumber", PersianNumber); 760 | } 761 | 762 | #endregion 763 | 764 | #region IComparable 765 | 766 | /// 767 | public bool Equals(PersianDateTime other) 768 | { 769 | return Year == other.Year && Month == other.Month && Day == other.Day && 770 | Hour == other.Hour && Minute == other.Minute && Second == other.Second && Millisecond == other.Millisecond; 771 | } 772 | 773 | /// 774 | public bool Equals(DateTime other) 775 | { 776 | return _dateTime == other; 777 | } 778 | 779 | #endregion 780 | 781 | #region Methods 782 | 783 | /// 784 | /// تاریخ شروع ماه رمضان 785 | /// 786 | /// چون ممکن است در یک سال شمسی دو شروع ماه رمضان داشته باشیم 787 | /// 788 | /// مقدار بازگشتی آرایه است که حداکثر دو آیتم دارد 789 | /// 790 | public PersianDateTime[] GetStartDayOfRamadan(int hijriAdjustment) 791 | { 792 | var result = new List(); 793 | var hijriCalendar = new HijriCalendar { HijriAdjustment = hijriAdjustment }; 794 | 795 | var currentHijriYear = hijriCalendar.GetYear(_dateTime); 796 | 797 | var startDayOfRamadan1 = new PersianDateTime(hijriCalendar.ToDateTime(currentHijriYear, 9, 1, 0, 0, 0, 0)); 798 | result.Add(startDayOfRamadan1); 799 | 800 | var startDayOfRamadan2 = new PersianDateTime(hijriCalendar.ToDateTime(++currentHijriYear, 9, 1, 0, 0, 0, 0)); 801 | if (startDayOfRamadan1.Year == startDayOfRamadan2.Year) 802 | result.Add(startDayOfRamadan2); 803 | 804 | return result.ToArray(); 805 | } 806 | 807 | /// 808 | /// تاریخ آخرین روز ماه شمسی 809 | /// 810 | public PersianDateTime GetPersianDateOfLastDayOfMonth() 811 | { 812 | return new PersianDateTime(Year, Month, GetMonthDays); 813 | } 814 | 815 | /// 816 | /// تاریخ آخرین روز سال شمسی 817 | /// 818 | public PersianDateTime GetPersianDateOfLastDayOfYear() 819 | { 820 | return new PersianDateTime(Year, 12, IsLeapYear ? 30 : 29); 821 | } 822 | 823 | /// 824 | /// پارس کردن رشته و تبدیل به نوع PersianDateTime 825 | /// 826 | /// متنی که باید پارس شود 827 | /// کاراکتری که جدا کننده تاریخ ها است 828 | public static PersianDateTime Parse(string persianDateTimeInString, string dateSeparatorPattern = @"\/|-") 829 | { 830 | //Convert persian and arabic digit to english to avoid throwing exception in Parse method 831 | persianDateTimeInString = ExtensionsHelper.ConvertDigitsToLatin(persianDateTimeInString); 832 | 833 | string month = "", year, day, 834 | hour = "0", 835 | minute = "0", 836 | second = "0", 837 | milliseconds = "0"; 838 | var amPmEnum = AmPmEnum.None; 839 | var containMonthSeparator = Regex.IsMatch(persianDateTimeInString, dateSeparatorPattern); 840 | 841 | persianDateTimeInString = ToEnglishNumber(persianDateTimeInString.Replace(" ", " ").Replace(" ", "-").Replace("\\", "-")); 842 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, dateSeparatorPattern, "-"); 843 | persianDateTimeInString = persianDateTimeInString.Replace("ك", "ک").Replace("ي", "ی"); 844 | 845 | persianDateTimeInString = $"-{persianDateTimeInString}-"; 846 | 847 | // بدست آوردن ب.ظ یا ق.ظ 848 | if (persianDateTimeInString.IndexOf("ق.ظ", StringComparison.InvariantCultureIgnoreCase) > -1) 849 | amPmEnum = AmPmEnum.AM; 850 | else if (persianDateTimeInString.IndexOf("ب.ظ", StringComparison.InvariantCultureIgnoreCase) > -1) 851 | amPmEnum = AmPmEnum.PM; 852 | 853 | if (persianDateTimeInString.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) > -1) // رشته ورودی شامل ساعت نیز هست 854 | { 855 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, "-*:-*", ":"); 856 | hour = Regex.Match(persianDateTimeInString, @"(?<=-)\d{1,2}(?=:)", RegexOptions.IgnoreCase).Value; 857 | minute = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:)\d{1,2}(?=:?)", RegexOptions.IgnoreCase).Value; 858 | if (persianDateTimeInString.IndexOf(':') != persianDateTimeInString.LastIndexOf(':')) 859 | { 860 | second = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:\d{1,2}:)\d{1,2}(?=(\d{1,2})?)", RegexOptions.IgnoreCase).Value; 861 | milliseconds = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:\d{1,2}:\d{1,2}:)\d{1,4}(?=(\d{1,2})?)", RegexOptions.IgnoreCase).Value; 862 | if (string.IsNullOrEmpty(milliseconds)) milliseconds = "0"; 863 | } 864 | } 865 | 866 | if (containMonthSeparator) 867 | { 868 | // بدست آوردن ماه 869 | month = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-)\d{1,2}(?=-\d{1,2}-\d{1,2}(?!-\d{1,2}:))", RegexOptions.IgnoreCase).Value; 870 | if (string.IsNullOrEmpty(month)) 871 | month = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-)\d{1,2}(?=-\d{1,2}[^:])", RegexOptions.IgnoreCase).Value; 872 | 873 | // بدست آوردن روز 874 | day = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-\d{1,2}-)\d{1,2}(?=-)", RegexOptions.IgnoreCase).Value; 875 | 876 | // بدست آوردن سال 877 | year = Regex.Match(persianDateTimeInString, @"(?<=-)\d{2,4}(?=-\d{1,2}-\d{1,2})", RegexOptions.IgnoreCase).Value; 878 | } 879 | else 880 | { 881 | foreach (PersianDateTimeMonthEnum item in Enum.GetValues(typeof(PersianDateTimeMonthEnum))) 882 | { 883 | var itemValueInString = item.ToString(); 884 | if (!persianDateTimeInString.Contains(itemValueInString)) continue; 885 | month = ((int)item).ToString(CultureInfo.InvariantCulture); 886 | break; 887 | } 888 | 889 | if (string.IsNullOrEmpty(month)) 890 | throw new Exception("عدد یا حرف ماه در رشته ورودی وجود ندارد"); 891 | 892 | // بدست آوردن روز 893 | var dayMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{1,2}(?=-)", RegexOptions.IgnoreCase); 894 | if (dayMatch.Success) 895 | { 896 | day = dayMatch.Value; 897 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, $"(?<=-){day}(?=-)", ""); 898 | } 899 | else 900 | throw new Exception("عدد روز در رشته ورودی وجود ندارد"); 901 | 902 | // بدست آوردن سال 903 | var yearMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{4}(?=-)", RegexOptions.IgnoreCase); 904 | if (yearMatch.Success) 905 | year = yearMatch.Value; 906 | else 907 | { 908 | yearMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{2,4}(?=-)", RegexOptions.IgnoreCase); 909 | if (yearMatch.Success) 910 | year = yearMatch.Value; 911 | else 912 | throw new Exception("عدد سال در رشته ورودی وجود ندارد"); 913 | } 914 | } 915 | 916 | //if (year.Length <= 2 && year[0] == '9') year = string.Format("13{0}", year); 917 | //else if (year.Length <= 2) year = string.Format("14{0}", year); 918 | 919 | var numericYear = int.Parse(year); 920 | var numericMonth = int.Parse(month); 921 | var numericDay = int.Parse(day); 922 | var numericHour = int.Parse(hour); 923 | var numericMinute = int.Parse(minute); 924 | var numericSecond = int.Parse(second); 925 | var numericMillisecond = int.Parse(milliseconds); 926 | 927 | if (numericYear < 100) 928 | numericYear += 1300; 929 | 930 | switch (amPmEnum) 931 | { 932 | case AmPmEnum.PM: 933 | if (numericHour < 12) 934 | numericHour = numericHour + 12; 935 | break; 936 | case AmPmEnum.AM: 937 | case AmPmEnum.None: 938 | break; 939 | } 940 | 941 | return new PersianDateTime(numericYear, numericMonth, numericDay, numericHour, numericMinute, numericSecond, numericMillisecond); 942 | } 943 | 944 | /// 945 | /// پارس کردن یک رشته برای یافتن تاریخ شمسی 946 | /// 947 | public static bool TryParse(string persianDateTimeInString, out PersianDateTime result, string dateSeparatorPattern = @"\/|-") 948 | { 949 | if (string.IsNullOrEmpty(persianDateTimeInString)) 950 | { 951 | result = MinValue; 952 | return false; 953 | } 954 | try 955 | { 956 | result = Parse(persianDateTimeInString, dateSeparatorPattern); 957 | return true; 958 | } 959 | catch 960 | { 961 | result = MinValue; 962 | return false; 963 | } 964 | } 965 | 966 | /// 967 | /// پارس کردن عددی در فرمت تاریخ شمسی 968 | /// 969 | /// همانند 13920305 970 | /// 971 | public static PersianDateTime Parse(int numericPersianDate) 972 | { 973 | if (numericPersianDate.ToString(CultureInfo.InvariantCulture).Length != 8) 974 | throw new InvalidCastException("Numeric persian date must have a format like 13920101."); 975 | var year = numericPersianDate / 10000; 976 | var day = numericPersianDate % 100; 977 | var month = numericPersianDate / 100 % 100; 978 | return new PersianDateTime(year, month, day); 979 | } 980 | /// 981 | /// پارس کردن عددی در فرمت تاریخ شمسی 982 | /// 983 | /// همانند 13920305 984 | /// 985 | public static bool TryParse(int numericPersianDate, out PersianDateTime result) 986 | { 987 | try 988 | { 989 | result = Parse(numericPersianDate); 990 | return true; 991 | } 992 | catch 993 | { 994 | result = MinValue; 995 | return false; 996 | } 997 | } 998 | 999 | /// 1000 | /// پارس کردن عددی در فرمت تاریخ و زمان شمسی 1001 | /// 1002 | /// همانند 13961223072132004 1003 | /// 1004 | public static PersianDateTime Parse(long numericPersianDateTime) 1005 | { 1006 | if (numericPersianDateTime.ToString(CultureInfo.InvariantCulture).Length != 17) 1007 | throw new InvalidCastException("Numeric persian date time must have a format like 1396122310223246."); 1008 | var year = numericPersianDateTime / 10000000000000; 1009 | var month = numericPersianDateTime / 100000000000 % 100; 1010 | var day = numericPersianDateTime / 1000000000 % 100; 1011 | var hour = numericPersianDateTime / 10000000 % 100; 1012 | var minute = numericPersianDateTime / 100000 % 100; 1013 | var second = numericPersianDateTime / 1000 % 100; 1014 | var millisecond = numericPersianDateTime % 1000; 1015 | return new PersianDateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, (int)second, (int)millisecond); 1016 | } 1017 | /// 1018 | /// پارس کردن عددی در فرمت تاریخ و زمان شمسی 1019 | /// 1020 | /// همانند 13961223102232461 1021 | /// 1022 | public static bool TryParse(long numericPersianDateTime, out PersianDateTime result) 1023 | { 1024 | try 1025 | { 1026 | result = Parse(numericPersianDateTime); 1027 | return true; 1028 | } 1029 | catch 1030 | { 1031 | result = MinValue; 1032 | return false; 1033 | } 1034 | } 1035 | 1036 | private static readonly List GregorianWeekDayNames = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]; 1037 | private static readonly List GregorianMonthNames = 1038 | [ 1039 | "january", "february", "march", 1040 | "april", "may", "june", 1041 | "july", "august", "september", 1042 | "october", "november", "december" 1043 | ]; 1044 | private static readonly List PmAm = ["pm", "am"]; 1045 | 1046 | /// 1047 | /// تبدیل به ساعت گرینویچ 1048 | /// 1049 | public PersianDateTime ToUniversalTime() 1050 | { 1051 | return new PersianDateTime(_dateTime.ToUniversalTime()); 1052 | } 1053 | 1054 | /// 1055 | /// دریافت تعداد ثانیه های سپری شده از اولین روز سال 1397 1056 | /// 1057 | public int ToEpochTime() 1058 | { 1059 | var timeSpan = _dateTime - new DateTime(1970, 1, 1); 1060 | return (int)timeSpan.TotalSeconds; 1061 | } 1062 | 1063 | /// 1064 | /// فرمت های که پشتیبانی می شوند 1065 | /// 1066 | /// yyyy: سال چهار رقمی 1067 | /// 1068 | /// yy: سال دو رقمی 1069 | /// 1070 | /// MMMM: نام فارسی ماه 1071 | /// 1072 | /// MM: عدد دو رقمی ماه 1073 | /// 1074 | /// M: عدد یک رقمی ماه 1075 | /// 1076 | /// dddd: نام فارسی روز هفته 1077 | /// 1078 | /// dd: عدد دو رقمی روز ماه 1079 | /// 1080 | /// d: عدد یک رقمی روز ماه 1081 | /// 1082 | /// HH: ساعت دو رقمی با فرمت 00 تا 24 1083 | /// 1084 | /// H: ساعت یک رقمی با فرمت 0 تا 24 1085 | /// 1086 | /// hh: ساعت دو رقمی با فرمت 00 تا 12 1087 | /// 1088 | /// h: ساعت یک رقمی با فرمت 0 تا 12 1089 | /// 1090 | /// mm: عدد دو رقمی دقیقه 1091 | /// 1092 | /// m: عدد یک رقمی دقیقه 1093 | /// 1094 | /// ss: ثانیه دو رقمی 1095 | /// 1096 | /// s: ثانیه یک رقمی 1097 | /// 1098 | /// fff: میلی ثانیه 3 رقمی 1099 | /// 1100 | /// ff: میلی ثانیه 2 رقمی 1101 | /// 1102 | /// f: میلی ثانیه یک رقمی 1103 | /// 1104 | /// tt: ب.ظ یا ق.ظ 1105 | /// 1106 | /// t: حرف اول از ب.ظ یا ق.ظ 1107 | /// 1108 | public string ToString(string format, IFormatProvider fp = null) 1109 | { 1110 | if (string.IsNullOrEmpty(format)) format = "yyyy/MM/dd HH:mm:ss"; 1111 | var dateTimeString = format.Trim(); 1112 | 1113 | dateTimeString = dateTimeString.Replace("yyyy", Year.ToString(CultureInfo.InvariantCulture)); 1114 | dateTimeString = dateTimeString.Replace("yy", GetShortYear.ToString("00", CultureInfo.InvariantCulture)); 1115 | dateTimeString = dateTimeString.Replace("MMMM", MonthName); 1116 | dateTimeString = dateTimeString.Replace("MM", Month.ToString("00", CultureInfo.InvariantCulture)); 1117 | dateTimeString = dateTimeString.Replace("M", Month.ToString(CultureInfo.InvariantCulture)); 1118 | dateTimeString = dateTimeString.Replace("dddd", GetLongDayOfWeekName); 1119 | dateTimeString = dateTimeString.Replace("dd", Day.ToString("00", CultureInfo.InvariantCulture)); 1120 | dateTimeString = dateTimeString.Replace("d", Day.ToString(CultureInfo.InvariantCulture)); 1121 | dateTimeString = dateTimeString.Replace("HH", Hour.ToString("00", CultureInfo.InvariantCulture)); 1122 | dateTimeString = dateTimeString.Replace("H", Hour.ToString(CultureInfo.InvariantCulture)); 1123 | dateTimeString = dateTimeString.Replace("hh", ShortHour.ToString("00", CultureInfo.InvariantCulture)); 1124 | dateTimeString = dateTimeString.Replace("h", ShortHour.ToString(CultureInfo.InvariantCulture)); 1125 | dateTimeString = dateTimeString.Replace("mm", Minute.ToString("00", CultureInfo.InvariantCulture)); 1126 | dateTimeString = dateTimeString.Replace("m", Minute.ToString(CultureInfo.InvariantCulture)); 1127 | dateTimeString = dateTimeString.Replace("ss", Second.ToString("00", CultureInfo.InvariantCulture)); 1128 | dateTimeString = dateTimeString.Replace("s", Second.ToString(CultureInfo.InvariantCulture)); 1129 | dateTimeString = dateTimeString.Replace("fff", Millisecond.ToString("000", CultureInfo.InvariantCulture)); 1130 | dateTimeString = dateTimeString.Replace("ff", (Millisecond / 10).ToString("00", CultureInfo.InvariantCulture)); 1131 | dateTimeString = dateTimeString.Replace("f", (Millisecond / 100).ToString(CultureInfo.InvariantCulture)); 1132 | dateTimeString = dateTimeString.Replace("tt", GetPersianAmPm); 1133 | dateTimeString = dateTimeString.Replace("t", GetPersianAmPm[0].ToString(CultureInfo.InvariantCulture)); 1134 | 1135 | if (PersianNumber) 1136 | dateTimeString = ToPersianNumber(dateTimeString); 1137 | 1138 | return dateTimeString; 1139 | } 1140 | 1141 | /// 1142 | /// بررسی میکند آیا تاریخ ورودی تاریخ میلادی است یا نه 1143 | /// 1144 | public static bool IsChristianDate(string inputString) 1145 | { 1146 | inputString = inputString.ToLower(); 1147 | bool result; 1148 | 1149 | foreach (var gregorianWeekDayName in GregorianWeekDayNames) 1150 | { 1151 | result = inputString.Contains(gregorianWeekDayName); 1152 | if (result) return true; 1153 | } 1154 | 1155 | foreach (var gregorianMonthName in GregorianMonthNames) 1156 | { 1157 | result = inputString.Contains(gregorianMonthName); 1158 | if (result) return true; 1159 | } 1160 | 1161 | foreach (var item in PmAm) 1162 | { 1163 | result = inputString.Contains(item); 1164 | if (result) return true; 1165 | } 1166 | 1167 | result = Regex.IsMatch(inputString, @"(1[8-9]|[2-9][0-9])\d{2}", RegexOptions.IgnoreCase); 1168 | 1169 | return result; 1170 | } 1171 | 1172 | /// 1173 | /// بررسی میکند آیا تاریخ ورودی مطابق تاریخ اس کسو ال سرور می باشد یا نه 1174 | /// 1175 | public static bool IsSqlDateTime(DateTime dateTime) 1176 | { 1177 | var minSqlDateTimeValue = new DateTime(1753, 1, 1); 1178 | return dateTime >= minSqlDateTimeValue; 1179 | } 1180 | 1181 | /// 1182 | /// تبدیل نام ماه شمسی به عدد معادل آن 1183 | /// 1184 | /// به طور مثال آذر را به 9 تبدیل می کند 1185 | /// 1186 | public int GetMonthEnum(string longMonthName) 1187 | { 1188 | var monthEnum = (PersianDateTimeMonthEnum)Enum.Parse(typeof(PersianDateTimeMonthEnum), longMonthName); 1189 | return (int)monthEnum; 1190 | } 1191 | 1192 | /// 1193 | /// نمایش تاریخ به فرمتی مشابه زیر 1194 | /// 1195 | /// 1393/09/14 1196 | /// 1197 | public string ToShortDateString() 1198 | { 1199 | var result = $"{Year:0000}/{Month:00}/{Day:00}"; 1200 | if (!PersianNumber) return result; 1201 | return ToPersianNumber(result); 1202 | } 1203 | 1204 | /// 1205 | /// نمایش تاریخ به فرمتی مشابه زیر 1206 | /// 1207 | /// ج 14 آذر 93 1208 | /// 1209 | public string ToShortDate1String() 1210 | { 1211 | var result = $"{GetShortDayOfWeekName} {Day:00} {GetLongMonthName} {GetShortYear}"; 1212 | if (!PersianNumber) return result; 1213 | return ToPersianNumber(result); 1214 | } 1215 | 1216 | /// 1217 | /// نمایش تاریخ به صورت عدد و در فرمتی مشابه زیر 1218 | /// 1219 | /// 13930914 1220 | /// 1221 | public int ToShortDateInt() 1222 | { 1223 | return int.Parse($"{Year:0000}{Month:00}{Day:00}"); 1224 | } 1225 | 1226 | /// 1227 | /// نمایش تاریخ و ساعت تا دقت میلی ثانیه به صورت عدد 1228 | /// 1229 | /// 1396122310324655 1230 | /// 1231 | public long ToLongDateTimeInt() 1232 | { 1233 | return long.Parse($"{Year:0000}{Month:00}{Day:00}{Hour:00}{Minute:00}{Second:00}{Millisecond:000}"); 1234 | } 1235 | 1236 | /// 1237 | /// در این فرمت نمایش ساعت و دقیقه و ثانیه در کنار هم با حذف علامت : تبدیل به عدد می شوند و نمایش داده می شود 1238 | /// 1239 | /// مثال: 123452 1240 | /// 1241 | /// که به معنای ساعت 12 و 34 دقیقه و 52 ثانیه می باشد 1242 | /// 1243 | public int ToTimeInt() 1244 | { 1245 | return int.Parse($"{Hour:00}{Minute:00}{Second:00}"); 1246 | } 1247 | 1248 | /// 1249 | /// در این فرمت نمایش ساعت و دقیقه در کنار هم با حذف علامت : تبدیل به عدد می شوند و نمایش داده می شود 1250 | /// 1251 | /// مثال: 1234 1252 | /// 1253 | /// که به معنای ساعت 12 و 34 دقیقه می باشد 1254 | /// 1255 | public short ToTimeShort() 1256 | { 1257 | return short.Parse($"{Hour:00}{Minute:00}"); 1258 | } 1259 | 1260 | /// 1261 | /// نمایش تاریخ به فرمتی مشابه زیر 1262 | /// 1263 | /// جمعه، 14 آذر 1393 1264 | /// 1265 | public string ToLongDateString() 1266 | { 1267 | var result = $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000}"; 1268 | if (!PersianNumber) return result; 1269 | return ToPersianNumber(result); 1270 | } 1271 | 1272 | /// 1273 | /// نمایش تاریخ و زمان به فرمتی مشابه زیر 1274 | /// 1275 | /// جمعه، 14 آذر 1393 ساعت 13:50:27 1276 | /// 1277 | public string ToLongDateTimeString() 1278 | { 1279 | var result = 1280 | $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000} ساعت {Hour:00}:{Minute:00}:{Second:00}"; 1281 | if (!PersianNumber) return result; 1282 | return ToPersianNumber(result); 1283 | } 1284 | 1285 | /// 1286 | /// نمایش تاریخ و زمان به فرمتی مشابه زیر 1287 | /// 1288 | /// جمعه، 14 آذر 1393 13:50 1289 | /// 1290 | public string ToShortDateTimeString() 1291 | { 1292 | var result = $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000} {Hour:00}:{Minute:00}"; 1293 | if (!PersianNumber) return result; 1294 | return ToPersianNumber(result); 1295 | } 1296 | 1297 | /// 1298 | /// نمایش زمان به فرمتی مشابه زیر 1299 | /// 1300 | /// 01:50 ب.ظ 1301 | /// 1302 | public string ToShortTimeString() 1303 | { 1304 | var result = $"{ShortHour:00}:{Minute:00} {GetPersianAmPm}"; 1305 | if (!PersianNumber) return result; 1306 | return ToPersianNumber(result); 1307 | } 1308 | 1309 | /// 1310 | /// نمایش زمان به فرمتی مشابه زیر 1311 | /// 1312 | /// 13:50:20 1313 | /// 1314 | public string ToLongTimeString() 1315 | { 1316 | var result = $"{Hour:00}:{Minute:00}:{Second:00}"; 1317 | if (!PersianNumber) return result; 1318 | return ToPersianNumber(result); 1319 | } 1320 | 1321 | /// 1322 | /// نمایش زمان به فرمتی مشابه زیر 1323 | /// 1324 | /// 1 دقیقه قبل 1325 | /// 1326 | public string ElapsedTime() 1327 | { 1328 | var persianDateTimeNow = new PersianDateTime(DateTime.Now); 1329 | var timeSpan = persianDateTimeNow - _dateTime; 1330 | if (timeSpan.TotalDays > 90) 1331 | return ToShortDateTimeString(); 1332 | 1333 | var result = string.Empty; 1334 | if (timeSpan.TotalDays > 30) 1335 | { 1336 | var month = timeSpan.TotalDays / 30; 1337 | if (month > 0) 1338 | result = $"{month:0} ماه قبل"; 1339 | } 1340 | else if (timeSpan.TotalDays >= 1) 1341 | { 1342 | result = $"{timeSpan.TotalDays:0} روز قبل"; 1343 | } 1344 | else if (timeSpan.TotalHours >= 1) 1345 | { 1346 | result = $"{timeSpan.TotalHours:0} ساعت قبل"; 1347 | } 1348 | else 1349 | { 1350 | var minute = timeSpan.TotalMinutes; 1351 | if (minute <= 1) minute = 1; 1352 | result = $"{minute:0} دقیقه قبل"; 1353 | } 1354 | if (!PersianNumber) return result; 1355 | return ToPersianNumber(result); 1356 | } 1357 | 1358 | /// 1359 | /// گرفتن فقط زمان 1360 | /// 1361 | public TimeSpan GetTime() 1362 | { 1363 | return new TimeSpan(0, _dateTime.Hour, _dateTime.Minute, _dateTime.Second, _dateTime.Millisecond); 1364 | } 1365 | 1366 | /// 1367 | /// تنظیم کردن زمان 1368 | /// 1369 | public PersianDateTime SetTime(int hour, int minute, int second = 0, int millisecond = 0) 1370 | { 1371 | return new PersianDateTime(Year, Month, Day, hour, minute, second, millisecond); 1372 | } 1373 | 1374 | /// 1375 | /// تبدیل به تاریخ میلادی 1376 | /// 1377 | public DateTime ToDateTime() 1378 | { 1379 | return _dateTime; 1380 | } 1381 | 1382 | /// 1383 | /// تبدیل به تاریخ هجری قمری 1384 | /// 1385 | public HijriDateTime ToHijri(int hijriAdjustment = 0) 1386 | { 1387 | var hijriCalendar = new HijriCalendar 1388 | { 1389 | HijriAdjustment = hijriAdjustment 1390 | }; 1391 | var month = hijriCalendar.GetMonth(_dateTime); 1392 | var monthName = ""; 1393 | switch (month) 1394 | { 1395 | case 1: 1396 | monthName = "محرم"; 1397 | break; 1398 | case 2: 1399 | monthName = "صفر"; 1400 | break; 1401 | case 3: 1402 | monthName = "ربیع الاول"; 1403 | break; 1404 | case 4: 1405 | monthName = "ربیع الثانی"; 1406 | break; 1407 | case 5: 1408 | monthName = "جمادل الاولی"; 1409 | break; 1410 | case 6: 1411 | monthName = "جمادی الاخره"; 1412 | break; 1413 | case 7: 1414 | monthName = "رجب"; 1415 | break; 1416 | case 8: 1417 | monthName = "شعبان"; 1418 | break; 1419 | case 9: 1420 | monthName = "رمضان"; 1421 | break; 1422 | case 10: 1423 | monthName = "شوال"; 1424 | break; 1425 | case 11: 1426 | monthName = "ذوالقعده"; 1427 | break; 1428 | case 12: 1429 | monthName = "ذوالحجه"; 1430 | break; 1431 | } 1432 | return new HijriDateTime 1433 | { 1434 | Day = hijriCalendar.GetDayOfMonth(_dateTime), 1435 | Month = month, 1436 | Year = hijriCalendar.GetYear(_dateTime), 1437 | MonthName = monthName 1438 | }; 1439 | } 1440 | 1441 | /// 1442 | /// کم کردن دو تاریخ از هم 1443 | /// 1444 | public TimeSpan Subtract(PersianDateTime persianDateTime) 1445 | { 1446 | return _dateTime - persianDateTime.ToDateTime(); 1447 | } 1448 | 1449 | /// 1450 | /// تعداد ماه اختلافی با تاریخ دیگری را بر میگرداند 1451 | /// 1452 | /// تعداد ماه 1453 | public int MonthDifference(DateTime dateTime) 1454 | { 1455 | return Math.Abs(dateTime.Month - _dateTime.Month + 12 * (dateTime.Year - _dateTime.Year)); 1456 | } 1457 | 1458 | /// 1459 | /// اضافه کردن مدت زمانی به تاریخ 1460 | /// 1461 | public PersianDateTime Add(TimeSpan timeSpan) 1462 | { 1463 | return new PersianDateTime(_dateTime.Add(timeSpan), PersianNumber); 1464 | } 1465 | 1466 | /// 1467 | /// اضافه کردن سال به تاریخ 1468 | /// 1469 | public PersianDateTime AddYears(int years) 1470 | { 1471 | return new PersianDateTime(PersianCalendar.AddYears(_dateTime, years), PersianNumber); 1472 | } 1473 | 1474 | /// 1475 | /// اضافه کردن روز به تاریخ 1476 | /// 1477 | public PersianDateTime AddDays(int days) 1478 | { 1479 | return new PersianDateTime(PersianCalendar.AddDays(_dateTime, days), PersianNumber); 1480 | } 1481 | 1482 | /// 1483 | /// اضافه کردن ماه به تاریخ 1484 | /// 1485 | public PersianDateTime AddMonths(int months) 1486 | { 1487 | return new PersianDateTime(PersianCalendar.AddMonths(_dateTime, months), PersianNumber); 1488 | } 1489 | 1490 | /// 1491 | /// اضافه کردن ساعت به تاریخ 1492 | /// 1493 | public PersianDateTime AddHours(int hours) 1494 | { 1495 | return new PersianDateTime(_dateTime.AddHours(hours), PersianNumber); 1496 | } 1497 | 1498 | /// 1499 | /// اضافه کردن دقیقه به تاریخ 1500 | /// 1501 | public PersianDateTime AddMinutes(int minutes) 1502 | { 1503 | return new PersianDateTime(_dateTime.AddMinutes(minutes), PersianNumber); 1504 | } 1505 | 1506 | /// 1507 | /// اضافه کردن ثانیه به تاریخ 1508 | /// 1509 | public PersianDateTime AddSeconds(int seconds) 1510 | { 1511 | return new PersianDateTime(_dateTime.AddSeconds(seconds), PersianNumber); 1512 | } 1513 | 1514 | /// 1515 | /// اضافه کردن میلی ثانیه به تاریخ 1516 | /// 1517 | public PersianDateTime AddMilliseconds(int milliseconds) 1518 | { 1519 | return new PersianDateTime(_dateTime.AddMilliseconds(milliseconds), PersianNumber); 1520 | } 1521 | 1522 | /// 1523 | /// بدست آوردن تاریخ شمسی اولین روز هفته 1524 | /// 1525 | public PersianDateTime GetFirstDayOfWeek() 1526 | { 1527 | var persianDateTime = new PersianDateTime(_dateTime).Date; 1528 | return persianDateTime.AddDays(PersianDayOfWeek.Saturday - persianDateTime.PersianDayOfWeek); 1529 | } 1530 | 1531 | /// 1532 | /// بدست آوردن تاریخ شمسی آخرین روز هفته 1533 | /// 1534 | public PersianDateTime GetPersianWeekend() 1535 | { 1536 | var persianDateTime = new PersianDateTime(_dateTime).Date; 1537 | return persianDateTime.AddDays(PersianDayOfWeek.Friday - persianDateTime.PersianDayOfWeek); 1538 | } 1539 | 1540 | /// 1541 | /// نام فارسی ماه بر اساس شماره ماه 1542 | /// 1543 | /// نام فارسی ماه 1544 | public static string GetPersianMonthName(int monthNumber) 1545 | { 1546 | return GetPersianMonthNamePrivate(monthNumber); 1547 | } 1548 | 1549 | private static string ToPersianNumber(string input) 1550 | { 1551 | if (string.IsNullOrEmpty(input)) return null; 1552 | input = input.Replace("ي", "ی").Replace("ك", "ک"); 1553 | 1554 | //۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ 1555 | return 1556 | input 1557 | .Replace("0", "۰") 1558 | .Replace("1", "۱") 1559 | .Replace("2", "۲") 1560 | .Replace("3", "۳") 1561 | .Replace("4", "۴") 1562 | .Replace("5", "۵") 1563 | .Replace("6", "۶") 1564 | .Replace("7", "۷") 1565 | .Replace("8", "۸") 1566 | .Replace("9", "۹"); 1567 | } 1568 | 1569 | private static string ToEnglishNumber(string input) 1570 | { 1571 | if (string.IsNullOrEmpty(input)) return null; 1572 | input = input.Replace("ي", "ی").Replace("ك", "ک"); 1573 | 1574 | //۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ 1575 | return input 1576 | .Replace(",", "") 1577 | .Replace("۰", "0") 1578 | .Replace("۱", "1") 1579 | .Replace("۲", "2") 1580 | .Replace("۳", "3") 1581 | .Replace("۴", "4") 1582 | .Replace("۵", "5") 1583 | .Replace("۶", "6") 1584 | .Replace("۷", "7") 1585 | .Replace("۸", "8") 1586 | .Replace("۹", "9"); 1587 | } 1588 | 1589 | private static string GetPersianMonthNamePrivate(int monthNumber) 1590 | { 1591 | var monthName = ""; 1592 | switch (monthNumber) 1593 | { 1594 | case 1: 1595 | monthName = "فروردین"; 1596 | break; 1597 | 1598 | case 2: 1599 | monthName = "اردیبهشت"; 1600 | break; 1601 | 1602 | case 3: 1603 | monthName = "خرداد"; 1604 | break; 1605 | 1606 | case 4: 1607 | monthName = "تیر"; 1608 | break; 1609 | 1610 | case 5: 1611 | monthName = "مرداد"; 1612 | break; 1613 | 1614 | case 6: 1615 | monthName = "شهریور"; 1616 | break; 1617 | 1618 | case 7: 1619 | monthName = "مهر"; 1620 | break; 1621 | 1622 | case 8: 1623 | monthName = "آبان"; 1624 | break; 1625 | 1626 | case 9: 1627 | monthName = "آذر"; 1628 | break; 1629 | 1630 | case 10: 1631 | monthName = "دی"; 1632 | break; 1633 | 1634 | case 11: 1635 | monthName = "بهمن"; 1636 | break; 1637 | 1638 | case 12: 1639 | monthName = "اسفند"; 1640 | break; 1641 | } 1642 | return monthName; 1643 | } 1644 | 1645 | #endregion 1646 | 1647 | #region GetDifferentMonths Base On Seasons 1648 | 1649 | /// 1650 | /// ماه های مرتبط با یک فصل را برمی گرداند 1651 | /// 1652 | private static int[] GetSeasonMonths(int month) 1653 | { 1654 | switch (month) 1655 | { 1656 | case 1: 1657 | case 2: 1658 | case 3: 1659 | return [1, 2, 3]; 1660 | case 4: 1661 | case 5: 1662 | case 6: 1663 | return [4, 5, 6]; 1664 | case 7: 1665 | case 8: 1666 | case 9: 1667 | return [7, 8, 9]; 1668 | case 10: 1669 | case 11: 1670 | case 12: 1671 | return [10, 11, 12]; 1672 | } 1673 | throw new Exception($"month {month} is not valid to GetFirstQuarterMonths"); 1674 | } 1675 | private static Dictionary GetSeasons(int[] firstSeasonMonths) 1676 | { 1677 | var quarter = 1; 1678 | var quarterDictionary = new Dictionary { { quarter, firstSeasonMonths } }; 1679 | var li = firstSeasonMonths; 1680 | var dd = firstSeasonMonths[0]; 1681 | while (dd != 10) 1682 | { 1683 | var temp = firstSeasonMonths.Select(du => du + 3).ToArray(); 1684 | quarter += 1; 1685 | quarterDictionary.Add(quarter, temp); 1686 | firstSeasonMonths = temp; 1687 | dd = firstSeasonMonths[0]; 1688 | } 1689 | dd = 1; 1690 | while (dd != li[0]) 1691 | { 1692 | var temp = new[] { dd, dd + 1, dd + 2 }; 1693 | quarter += 1; 1694 | quarterDictionary.Add(quarter, temp); 1695 | firstSeasonMonths = temp; 1696 | dd = firstSeasonMonths.Last() + 1; 1697 | } 1698 | 1699 | return quarterDictionary; 1700 | } 1701 | 1702 | /// 1703 | /// اختلاف بین دو تاریخ بر حسب فصول 1704 | /// 1705 | public int GetDifferenceQuarter(DateTime targetDateTime) 1706 | { 1707 | var biggerDateTime = targetDateTime; 1708 | var lesserDateTime = _dateTime; 1709 | if (_dateTime > targetDateTime) 1710 | { 1711 | var tmp = biggerDateTime; 1712 | biggerDateTime = _dateTime; 1713 | lesserDateTime = tmp; 1714 | } 1715 | var diffMonth = (biggerDateTime.Year - lesserDateTime.Year) * 12 + biggerDateTime.Month - lesserDateTime.Month; 1716 | var firstQuarter = GetSeasonMonths(lesserDateTime.Month); 1717 | var seasons = GetSeasons(firstQuarter); 1718 | if (diffMonth < 12) return seasons.First(p => p.Value.Contains(biggerDateTime.Month)).Key; 1719 | var diffYear = diffMonth / 12; 1720 | var diffQuarter = diffMonth - diffYear * 12; 1721 | return diffYear * 4 + diffQuarter / 3 + 1; 1722 | } 1723 | 1724 | #endregion 1725 | 1726 | #region IConvertible 1727 | 1728 | /// 1729 | public TypeCode GetTypeCode() 1730 | { 1731 | return TypeCode.DateTime; 1732 | } 1733 | 1734 | /// 1735 | public bool ToBoolean(IFormatProvider provider) 1736 | { 1737 | return _dateTime > DateTime.MinValue; 1738 | } 1739 | 1740 | /// 1741 | public byte ToByte(IFormatProvider provider) 1742 | { 1743 | throw new InvalidCastException(); 1744 | } 1745 | 1746 | /// 1747 | public char ToChar(IFormatProvider provider) 1748 | { 1749 | throw new InvalidCastException(); 1750 | } 1751 | 1752 | /// 1753 | public DateTime ToDateTime(IFormatProvider provider) 1754 | { 1755 | return _dateTime; 1756 | } 1757 | 1758 | /// 1759 | public decimal ToDecimal(IFormatProvider provider) 1760 | { 1761 | return ToLongDateTimeInt(); 1762 | } 1763 | 1764 | /// 1765 | public double ToDouble(IFormatProvider provider) 1766 | { 1767 | return ToLongDateTimeInt(); 1768 | } 1769 | 1770 | /// 1771 | public short ToInt16(IFormatProvider provider) 1772 | { 1773 | throw new InvalidCastException(); 1774 | } 1775 | 1776 | /// 1777 | public int ToInt32(IFormatProvider provider) 1778 | { 1779 | return ToShortDateInt(); 1780 | } 1781 | 1782 | /// 1783 | public long ToInt64(IFormatProvider provider) 1784 | { 1785 | return ToLongDateTimeInt(); 1786 | } 1787 | 1788 | /// 1789 | public sbyte ToSByte(IFormatProvider provider) 1790 | { 1791 | throw new InvalidCastException(); 1792 | } 1793 | 1794 | /// 1795 | public float ToSingle(IFormatProvider provider) 1796 | { 1797 | throw new InvalidCastException(); 1798 | } 1799 | 1800 | /// 1801 | public string ToString(IFormatProvider provider) 1802 | { 1803 | return ToString("", provider); 1804 | } 1805 | 1806 | /// 1807 | public object ToType(Type conversionType, IFormatProvider provider) 1808 | { 1809 | switch (Type.GetTypeCode(conversionType)) 1810 | { 1811 | case TypeCode.Boolean: 1812 | return ToBoolean(provider); 1813 | case TypeCode.Byte: 1814 | return ToByte(provider); 1815 | case TypeCode.Char: 1816 | return ToChar(provider); 1817 | case TypeCode.DateTime: 1818 | return ToDateTime(provider); 1819 | case TypeCode.Decimal: 1820 | return ToDecimal(provider); 1821 | case TypeCode.Double: 1822 | return ToDouble(provider); 1823 | case TypeCode.Int16: 1824 | return ToInt16(provider); 1825 | case TypeCode.Int32: 1826 | return ToInt32(provider); 1827 | case TypeCode.Int64: 1828 | return ToInt64(provider); 1829 | case TypeCode.Object: 1830 | if (typeof(PersianDateTime) == conversionType) 1831 | return this; 1832 | if (typeof(DateTime) == conversionType) 1833 | return ToDateTime(); 1834 | throw new InvalidCastException($"Conversion to a {conversionType.Name} is not supported."); 1835 | case TypeCode.SByte: 1836 | return ToSByte(provider); 1837 | case TypeCode.Single: 1838 | return ToSingle(provider); 1839 | case TypeCode.String: 1840 | return ToString(provider); 1841 | case TypeCode.UInt16: 1842 | return ToUInt16(provider); 1843 | case TypeCode.UInt32: 1844 | return ToUInt32(provider); 1845 | case TypeCode.UInt64: 1846 | return ToUInt64(provider); 1847 | case TypeCode.DBNull: 1848 | break; 1849 | case TypeCode.Empty: 1850 | break; 1851 | default: 1852 | throw new InvalidCastException($"Conversion to {conversionType.Name} is not supported."); 1853 | } 1854 | throw new InvalidCastException(); 1855 | } 1856 | 1857 | /// 1858 | public ushort ToUInt16(IFormatProvider provider) 1859 | { 1860 | throw new InvalidCastException(); 1861 | } 1862 | 1863 | /// 1864 | public uint ToUInt32(IFormatProvider provider) 1865 | { 1866 | return (uint)ToShortDateInt(); 1867 | } 1868 | 1869 | /// 1870 | public ulong ToUInt64(IFormatProvider provider) 1871 | { 1872 | return (ulong)ToLongDateTimeInt(); 1873 | } 1874 | 1875 | #endregion 1876 | } -------------------------------------------------------------------------------- /MD.PersianDateTime/PersianDateTime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Runtime.Serialization; 5 | using System.Text.RegularExpressions; 6 | 7 | // ReSharper disable UnusedMember.Local 8 | 9 | namespace MD.PersianDateTime 10 | { 11 | /// 12 | /// Created By Mohammad Dayyan, @mdssoft, mds_soft@yahoo.com 13 | /// 1393/09/14 14 | /// 15 | [Serializable] 16 | public struct PersianDateTime : 17 | ISerializable, IFormattable, IConvertible, 18 | IComparable, IComparable, 19 | IEquatable, IEquatable 20 | { 21 | #region properties and fields 22 | 23 | private static PersianCalendar _persianCalendar; 24 | private static PersianCalendar PersianCalendar 25 | { 26 | get 27 | { 28 | if (_persianCalendar != null) return _persianCalendar; 29 | _persianCalendar = new PersianCalendar(); 30 | return _persianCalendar; 31 | } 32 | } 33 | private readonly DateTime _dateTime; 34 | 35 | /// 36 | /// آیا اعداد در خروجی به صورت فارسی نمایش داده شوند؟ 37 | /// 38 | public bool PersianNumber { get; set; } 39 | 40 | /// 41 | /// سال شمسی 42 | /// 43 | public int Year 44 | { 45 | get 46 | { 47 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Year; 48 | return PersianCalendar.GetYear(_dateTime); 49 | } 50 | } 51 | 52 | /// 53 | /// ماه شمسی 54 | /// 55 | public int Month 56 | { 57 | get 58 | { 59 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Month; 60 | return PersianCalendar.GetMonth(_dateTime); 61 | } 62 | } 63 | 64 | /// 65 | /// نام فارسی ماه 66 | /// 67 | public string MonthName => ((PersianDateTimeMonthEnum)Month).ToString(); 68 | 69 | /// 70 | /// روز ماه 71 | /// 72 | public int Day 73 | { 74 | get 75 | { 76 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.Day; 77 | return PersianCalendar.GetDayOfMonth(_dateTime); 78 | } 79 | } 80 | 81 | /// 82 | /// روز هفته 83 | /// 84 | public DayOfWeek DayOfWeek 85 | { 86 | get 87 | { 88 | if (_dateTime <= DateTime.MinValue) return DateTime.MinValue.DayOfWeek; 89 | return PersianCalendar.GetDayOfWeek(_dateTime); 90 | } 91 | } 92 | 93 | /// 94 | /// روز هفته یا ایندکس شمسی 95 | /// 96 | /// شنبه دارای ایندکس صفر است 97 | /// 98 | public PersianDayOfWeek PersianDayOfWeek 99 | { 100 | get 101 | { 102 | var dayOfWeek = PersianCalendar.GetDayOfWeek(_dateTime); 103 | PersianDayOfWeek persianDayOfWeek; 104 | switch (dayOfWeek) 105 | { 106 | case DayOfWeek.Sunday: 107 | persianDayOfWeek = PersianDayOfWeek.Sunday; 108 | break; 109 | case DayOfWeek.Monday: 110 | persianDayOfWeek = PersianDayOfWeek.Monday; 111 | break; 112 | case DayOfWeek.Tuesday: 113 | persianDayOfWeek = PersianDayOfWeek.Tuesday; 114 | break; 115 | case DayOfWeek.Wednesday: 116 | persianDayOfWeek = PersianDayOfWeek.Wednesday; 117 | break; 118 | case DayOfWeek.Thursday: 119 | persianDayOfWeek = PersianDayOfWeek.Thursday; 120 | break; 121 | case DayOfWeek.Friday: 122 | persianDayOfWeek = PersianDayOfWeek.Friday; 123 | break; 124 | case DayOfWeek.Saturday: 125 | persianDayOfWeek = PersianDayOfWeek.Saturday; 126 | break; 127 | default: 128 | throw new ArgumentOutOfRangeException(); 129 | } 130 | return persianDayOfWeek; 131 | } 132 | } 133 | 134 | /// 135 | /// ساعت 136 | /// 137 | public int Hour 138 | { 139 | get 140 | { 141 | if (_dateTime <= DateTime.MinValue) return 12; 142 | return PersianCalendar.GetHour(_dateTime); 143 | } 144 | } 145 | 146 | /// 147 | /// ساعت دو رقمی 148 | /// 149 | public int ShortHour 150 | { 151 | get 152 | { 153 | int shortHour; 154 | if (Hour > 12) 155 | shortHour = Hour - 12; 156 | else 157 | shortHour = Hour; 158 | return shortHour; 159 | } 160 | } 161 | 162 | /// 163 | /// دقیقه 164 | /// 165 | public int Minute 166 | { 167 | get 168 | { 169 | if (_dateTime <= DateTime.MinValue) return 0; 170 | return PersianCalendar.GetMinute(_dateTime); 171 | } 172 | } 173 | 174 | /// 175 | /// ثانیه 176 | /// 177 | public int Second 178 | { 179 | get 180 | { 181 | if (_dateTime <= DateTime.MinValue) return 0; 182 | return PersianCalendar.GetSecond(_dateTime); 183 | } 184 | } 185 | 186 | /// 187 | /// میلی ثانیه 188 | /// 189 | public int Millisecond 190 | { 191 | get 192 | { 193 | if (_dateTime <= DateTime.MinValue) return 0; 194 | return (int)PersianCalendar.GetMilliseconds(_dateTime); 195 | } 196 | } 197 | 198 | /// 199 | /// تعداد روز در ماه 200 | /// 201 | public int GetMonthDays 202 | { 203 | get 204 | { 205 | int days; 206 | switch (Month) 207 | { 208 | case 1: 209 | case 2: 210 | case 3: 211 | case 4: 212 | case 5: 213 | case 6: 214 | days = 31; 215 | break; 216 | 217 | case 7: 218 | case 8: 219 | case 9: 220 | case 10: 221 | case 11: 222 | days = 30; 223 | break; 224 | 225 | case 12: 226 | { 227 | if (IsLeapYear) days = 30; 228 | else days = 29; 229 | break; 230 | } 231 | 232 | default: 233 | throw new Exception("Month number is wrong !!!"); 234 | } 235 | return days; 236 | } 237 | } 238 | 239 | /// 240 | /// هفته چندم سال 241 | /// 242 | public int GetWeekOfYear 243 | { 244 | get 245 | { 246 | if (_dateTime <= DateTime.MinValue) return 0; 247 | return PersianCalendar.GetWeekOfYear(_dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Saturday); 248 | } 249 | } 250 | 251 | /// 252 | /// هفته چندم ماه 253 | /// 254 | public int GetWeekOfMonth 255 | { 256 | get 257 | { 258 | if (_dateTime <= DateTime.MinValue) return 0; 259 | var persianDateTime = AddDays(1 - Day); 260 | return GetWeekOfYear - persianDateTime.GetWeekOfYear + 1; 261 | } 262 | } 263 | 264 | /// 265 | /// روز چندم سال 266 | /// 267 | public int GetDayOfYear 268 | { 269 | get 270 | { 271 | if (_dateTime <= DateTime.MinValue) return 0; 272 | return PersianCalendar.GetDayOfYear(_dateTime); 273 | } 274 | } 275 | 276 | /// 277 | /// آیا سال کبیسه است؟ 278 | /// 279 | public bool IsLeapYear 280 | { 281 | get 282 | { 283 | if (_dateTime <= DateTime.MinValue) return false; 284 | return PersianCalendar.IsLeapYear(Year); 285 | } 286 | } 287 | 288 | /// 289 | /// قبل از ظهر، بعد از ظهر 290 | /// 291 | private AmPmEnum PersianAmPm => _dateTime.ToString("tt", CultureInfo.InvariantCulture) == "PM" ? AmPmEnum.PM : AmPmEnum.AM; 292 | 293 | /// 294 | /// قبل از ظهر، بعد از ظهر به شکل مخفف . کوتاه 295 | /// 296 | public string GetPersianAmPm 297 | { 298 | get 299 | { 300 | var result = string.Empty; 301 | switch (PersianAmPm) 302 | { 303 | case AmPmEnum.AM: 304 | result = "ق.ظ"; 305 | break; 306 | 307 | case AmPmEnum.PM: 308 | result = "ب.ظ"; 309 | break; 310 | } 311 | return result; 312 | } 313 | } 314 | 315 | /// 316 | /// نام کامل ماه 317 | /// 318 | public string GetLongMonthName => GetPersianMonthNamePrivate(Month); 319 | 320 | /// 321 | /// سال دو رقمی 322 | /// 323 | public int GetShortYear => Year % 100; 324 | 325 | /// 326 | /// نام کامل روز 327 | /// 328 | public string GetLongDayOfWeekName 329 | { 330 | get 331 | { 332 | string weekDayName = null; 333 | switch (DayOfWeek) 334 | { 335 | case DayOfWeek.Sunday: 336 | weekDayName = PersianWeekDaysStruct.یکشنبه.Value; 337 | break; 338 | 339 | case DayOfWeek.Monday: 340 | weekDayName = PersianWeekDaysStruct.دوشنبه.Value; 341 | break; 342 | 343 | case DayOfWeek.Tuesday: 344 | weekDayName = PersianWeekDaysStruct.سه_شنبه.Value; 345 | break; 346 | 347 | case DayOfWeek.Wednesday: 348 | weekDayName = PersianWeekDaysStruct.چهارشنبه.Value; 349 | break; 350 | 351 | case DayOfWeek.Thursday: 352 | weekDayName = PersianWeekDaysStruct.پنجشنبه.Value; 353 | break; 354 | 355 | case DayOfWeek.Friday: 356 | weekDayName = PersianWeekDaysStruct.جمعه.Value; 357 | break; 358 | 359 | case DayOfWeek.Saturday: 360 | weekDayName = PersianWeekDaysStruct.شنبه.Value; 361 | break; 362 | } 363 | return weekDayName; 364 | } 365 | } 366 | 367 | /// 368 | /// نام یک حرفی روز، حرف اول روز 369 | /// 370 | public string GetShortDayOfWeekName 371 | { 372 | get 373 | { 374 | string weekDayName = null; 375 | switch (DayOfWeek) 376 | { 377 | case DayOfWeek.Sunday: 378 | weekDayName = "ی"; 379 | break; 380 | 381 | case DayOfWeek.Monday: 382 | weekDayName = "د"; 383 | break; 384 | 385 | case DayOfWeek.Tuesday: 386 | weekDayName = "س"; 387 | break; 388 | 389 | case DayOfWeek.Wednesday: 390 | weekDayName = "چ"; 391 | break; 392 | 393 | case DayOfWeek.Thursday: 394 | weekDayName = "پ"; 395 | break; 396 | 397 | case DayOfWeek.Friday: 398 | weekDayName = "ج"; 399 | break; 400 | 401 | case DayOfWeek.Saturday: 402 | weekDayName = "ش"; 403 | break; 404 | } 405 | 406 | return weekDayName; 407 | } 408 | } 409 | 410 | /// 411 | /// تاریخ و زمان همین الان 412 | /// 413 | public static PersianDateTime Now => new PersianDateTime(DateTime.Now); 414 | 415 | /// 416 | /// تاریخ امروز 417 | /// 418 | public static PersianDateTime Today => new PersianDateTime(DateTime.Today); 419 | 420 | /// 421 | /// زمان به فرمتی مشابه 422 | /// 423 | /// 13:47:40:530 424 | /// 425 | public string TimeOfDay 426 | { 427 | get 428 | { 429 | var result = $"{Hour:00}:{Minute:00}:{Second:00}:{Millisecond:000}"; 430 | if (!PersianNumber) return result; 431 | return ToPersianNumber(result); 432 | } 433 | } 434 | 435 | /// 436 | /// زمان به فرمتی مشابه زیر 437 | /// 438 | /// ساعت 01:47:40:530 ب.ظ 439 | /// 440 | public string LongTimeOfDay 441 | { 442 | get 443 | { 444 | var result = $"ساعت {ShortHour:00}:{Minute:00}:{Second:00}:{Millisecond:000} {GetPersianAmPm}"; 445 | if (!PersianNumber) return result; 446 | return ToPersianNumber(result); 447 | } 448 | } 449 | 450 | /// 451 | /// زمان به فرمتی مشابه زیر 452 | /// 453 | /// 01:47:40 ب.ظ 454 | /// 455 | public string ShortTimeOfDay 456 | { 457 | get 458 | { 459 | var result = $"{ShortHour:00}:{Minute:00}:{Second:00} {GetPersianAmPm}"; 460 | if (!PersianNumber) return result; 461 | return ToPersianNumber(result); 462 | } 463 | } 464 | 465 | /// 466 | /// تاریخ بدون احتساب زمان 467 | /// 468 | public PersianDateTime Date 469 | { 470 | get 471 | { 472 | var persianDateTime = new PersianDateTime(Year, Month, Day) 473 | { 474 | PersianNumber = PersianNumber 475 | }; 476 | return persianDateTime; 477 | } 478 | } 479 | 480 | /// 481 | /// حداقل مقدار 482 | /// 483 | public static PersianDateTime MinValue => new PersianDateTime(DateTime.MinValue); 484 | 485 | /// 486 | /// حداکثر مقدار 487 | /// 488 | public static PersianDateTime MaxValue => new PersianDateTime(DateTime.MaxValue); 489 | 490 | #endregion 491 | 492 | #region ctor 493 | 494 | /// 495 | /// متد سازنده برای دی سریالایز شدن 496 | /// 497 | private PersianDateTime(SerializationInfo info, StreamingContext context) 498 | : this() 499 | { 500 | _dateTime = info.GetDateTime("DateTime"); 501 | PersianNumber = info.GetBoolean("PersianNumber"); 502 | } 503 | 504 | /// 505 | /// مقدار دهی اولیه با استفاده از دیت تایم میلادی 506 | /// 507 | /// DateTime 508 | /// آیا اعداد در خروجی های این آبجکت به صورت فارسی نمایش داده شوند یا فارسی؟ 509 | private PersianDateTime(DateTime dateTime, bool persianNumber) 510 | : this() 511 | { 512 | _dateTime = dateTime; 513 | PersianNumber = persianNumber; 514 | } 515 | 516 | /// 517 | /// مقدار دهی اولیه با استفاده از دیت تایم میلادی 518 | /// 519 | public PersianDateTime(DateTime dateTime) 520 | : this() 521 | { 522 | _dateTime = dateTime; 523 | } 524 | 525 | /// 526 | /// مقدار دهی اولیه با استفاده از دیت تایم قابل نال میلادی 527 | /// 528 | public PersianDateTime(DateTime? nullableDateTime) 529 | : this() 530 | { 531 | if (!nullableDateTime.HasValue) 532 | { 533 | _dateTime = DateTime.MinValue; 534 | return; 535 | } 536 | _dateTime = nullableDateTime.Value; 537 | } 538 | 539 | /// 540 | /// مقدار دهی اولیه 541 | /// 542 | /// سال شمسی 543 | /// ماه شمسی 544 | /// روز شمسی 545 | public PersianDateTime(int persianYear, int persianMonth, int persianDay) 546 | : this() 547 | { 548 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, 0, 0, 0, 0); 549 | } 550 | 551 | /// 552 | /// مقدار دهی اولیه 553 | /// 554 | /// سال شمسی 555 | /// ماه شمسی 556 | /// روز شمسی 557 | /// ساعت 558 | /// دقیقه 559 | /// ثانیه 560 | public PersianDateTime(int persianYear, int persianMonth, int persianDay, int hour, int minute, int second) 561 | : this() 562 | { 563 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, hour, minute, second, 0); 564 | } 565 | 566 | /// 567 | /// مقدار دهی اولیه 568 | /// 569 | /// سال شمسی 570 | /// ماه شمسی 571 | /// روز شمسی 572 | /// سال 573 | /// دقیقه 574 | /// ثانیه 575 | /// میلی ثانیه 576 | public PersianDateTime(int persianYear, int persianMonth, int persianDay, int hour, int minute, int second, int millisecond) 577 | : this() 578 | { 579 | _dateTime = PersianCalendar.ToDateTime(persianYear, persianMonth, persianDay, hour, minute, second, millisecond); 580 | } 581 | 582 | #endregion 583 | 584 | #region Types 585 | 586 | private enum AmPmEnum 587 | { 588 | AM = 0, 589 | PM = 1, 590 | None = 2 591 | } 592 | 593 | private enum PersianDateTimeMonthEnum 594 | { 595 | فروردین = 1, 596 | اردیبهشت = 2, 597 | خرداد = 3, 598 | تیر = 4, 599 | مرداد = 5, 600 | شهریور = 6, 601 | مهر = 7, 602 | آبان = 8, 603 | آذر = 9, 604 | دی = 10, 605 | بهمن = 11, 606 | اسفند = 12 607 | } 608 | 609 | private struct PersianWeekDaysStruct 610 | { 611 | public static KeyValuePair شنبه => new KeyValuePair((int)DayOfWeek.Saturday, "شنبه"); 612 | public static KeyValuePair یکشنبه => new KeyValuePair((int)DayOfWeek.Sunday, "یکشنبه"); 613 | public static KeyValuePair دوشنبه => new KeyValuePair((int)DayOfWeek.Monday, "دوشنبه"); 614 | public static KeyValuePair سه_شنبه => new KeyValuePair((int)DayOfWeek.Tuesday, "سه شنبه"); 615 | public static KeyValuePair چهارشنبه => new KeyValuePair((int)DayOfWeek.Thursday, "چهارشنبه"); 616 | public static KeyValuePair پنجشنبه => new KeyValuePair((int)DayOfWeek.Wednesday, "پنج شنبه"); 617 | public static KeyValuePair جمعه => new KeyValuePair((int)DayOfWeek.Friday, "جمعه"); 618 | } 619 | 620 | #endregion 621 | 622 | #region override 623 | 624 | /// 625 | /// تبدیل تاریخ به رشته با فرمت مشابه زیر 626 | /// 627 | /// 1393/09/14 13:49:40 628 | /// 629 | public override string ToString() 630 | { 631 | return ToString(""); 632 | } 633 | 634 | /// 635 | public override bool Equals(object obj) 636 | { 637 | if (!(obj is PersianDateTime)) return false; 638 | var persianDateTime = (PersianDateTime)obj; 639 | return _dateTime == persianDateTime.ToDateTime(); 640 | } 641 | 642 | /// 643 | public override int GetHashCode() 644 | { 645 | return _dateTime.GetHashCode(); 646 | } 647 | 648 | /// 649 | /// مقایسه با تاریخ دیگر 650 | /// 651 | /// مقدار بازگشتی همانند مقدار بازگشتی متد کامپیر در دیت تایم دات نت است 652 | public int CompareTo(PersianDateTime otherPersianDateTime) 653 | { 654 | return _dateTime.CompareTo(otherPersianDateTime.ToDateTime()); 655 | } 656 | 657 | /// 658 | /// مقایسه با تاریخ دیگر 659 | /// 660 | /// مقدار بازگشتی همانند مقدار بازگشتی متد کامپیر در دیت تایم دات نت است 661 | public int CompareTo(DateTime otherDateTime) 662 | { 663 | return _dateTime.CompareTo(otherDateTime); 664 | } 665 | 666 | #region operators 667 | 668 | /// 669 | /// تبدیل خودکار به دیت تایم میلادی 670 | /// 671 | public static implicit operator DateTime(PersianDateTime persianDateTime) 672 | { 673 | return persianDateTime.ToDateTime(); 674 | } 675 | 676 | /// 677 | /// اپراتور برابر 678 | /// 679 | public static bool operator ==(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 680 | { 681 | return persianDateTime1.Equals(persianDateTime2); 682 | } 683 | 684 | /// 685 | /// اپراتور نامساوی 686 | /// 687 | public static bool operator !=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 688 | { 689 | return !persianDateTime1.Equals(persianDateTime2); 690 | } 691 | 692 | /// 693 | /// اپراتور بزرگتری 694 | /// 695 | public static bool operator >(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 696 | { 697 | return persianDateTime1.ToDateTime() > persianDateTime2.ToDateTime(); 698 | } 699 | 700 | /// 701 | /// اپراتور کوچکتری 702 | /// 703 | public static bool operator <(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 704 | { 705 | return persianDateTime1.ToDateTime() < persianDateTime2.ToDateTime(); 706 | } 707 | 708 | /// 709 | /// اپراتور بزرگتر مساوی 710 | /// 711 | public static bool operator >=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 712 | { 713 | return persianDateTime1.ToDateTime() >= persianDateTime2.ToDateTime(); 714 | } 715 | 716 | /// 717 | /// اپراتور کوچکتر مساوی 718 | /// 719 | public static bool operator <=(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 720 | { 721 | return persianDateTime1.ToDateTime() <= persianDateTime2.ToDateTime(); 722 | } 723 | 724 | /// 725 | /// اپراتور جمع تو زمان 726 | /// 727 | public static PersianDateTime operator +(PersianDateTime persianDateTime1, TimeSpan timeSpanToAdd) 728 | { 729 | DateTime dateTime1 = persianDateTime1; 730 | return new PersianDateTime(dateTime1.Add(timeSpanToAdd)); 731 | } 732 | 733 | /// 734 | /// اپراتور کم کردن دو زمان از هم 735 | /// 736 | public static TimeSpan operator -(PersianDateTime persianDateTime1, PersianDateTime persianDateTime2) 737 | { 738 | DateTime dateTime1 = persianDateTime1; 739 | DateTime dateTime2 = persianDateTime2; 740 | return dateTime1 - dateTime2; 741 | } 742 | 743 | #endregion 744 | 745 | #endregion 746 | 747 | #region ISerializable 748 | 749 | /// 750 | public void GetObjectData(SerializationInfo info, StreamingContext context) 751 | { 752 | info.AddValue("DateTime", ToDateTime()); 753 | info.AddValue("PersianNumber", PersianNumber); 754 | } 755 | 756 | #endregion 757 | 758 | #region IComparable 759 | 760 | /// 761 | public bool Equals(PersianDateTime other) 762 | { 763 | return Year == other.Year && Month == other.Month && Day == other.Day && 764 | Hour == other.Hour && Minute == other.Minute && Second == other.Second && Millisecond == other.Millisecond; 765 | } 766 | 767 | /// 768 | public bool Equals(DateTime other) 769 | { 770 | return _dateTime == other; 771 | } 772 | 773 | #endregion 774 | 775 | #region Methods 776 | 777 | /// 778 | /// تاریخ شروع ماه رمضان 779 | /// 780 | /// چون ممکن است در یک سال شمسی دو شروع ماه رمضان داشته باشیم 781 | /// 782 | /// مقدار بازگشتی آرایه است که حداکثر دو آیتم دارد 783 | /// 784 | public PersianDateTime[] GetStartDayOfRamadan(int hijriAdjustment) 785 | { 786 | var result = new List(); 787 | var hijriCalendar = new HijriCalendar { HijriAdjustment = hijriAdjustment }; 788 | 789 | var currentHijriYear = hijriCalendar.GetYear(_dateTime); 790 | 791 | var startDayOfRamadan1 = new PersianDateTime(hijriCalendar.ToDateTime(currentHijriYear, 9, 1, 0, 0, 0, 0)); 792 | result.Add(startDayOfRamadan1); 793 | 794 | var startDayOfRamadan2 = new PersianDateTime(hijriCalendar.ToDateTime(++currentHijriYear, 9, 1, 0, 0, 0, 0)); 795 | if (startDayOfRamadan1.Year == startDayOfRamadan2.Year) 796 | result.Add(startDayOfRamadan2); 797 | 798 | return result.ToArray(); 799 | } 800 | 801 | /// 802 | /// تاریخ آخرین روز ماه شمسی 803 | /// 804 | public PersianDateTime GetPersianDateOfLastDayOfMonth() 805 | { 806 | return new PersianDateTime(Year, Month, GetMonthDays); 807 | } 808 | 809 | /// 810 | /// تاریخ آخرین روز سال شمسی 811 | /// 812 | public PersianDateTime GetPersianDateOfLastDayOfYear() 813 | { 814 | return new PersianDateTime(Year, 12, IsLeapYear ? 30 : 29); 815 | } 816 | 817 | /// 818 | /// پارس کردن رشته و تبدیل به نوع PersianDateTime 819 | /// 820 | /// متنی که باید پارس شود 821 | /// کاراکتری که جدا کننده تاریخ ها است 822 | public static PersianDateTime Parse(string persianDateTimeInString, string dateSeparatorPattern = @"\/|-") 823 | { 824 | //Convert persian and arabic digit to english to avoid throwing exception in Parse method 825 | persianDateTimeInString = ExtensionsHelper.ConvertDigitsToLatin(persianDateTimeInString); 826 | 827 | string month = "", year, day, 828 | hour = "0", 829 | minute = "0", 830 | second = "0", 831 | milliseconds = "0"; 832 | var amPmEnum = AmPmEnum.None; 833 | var containMonthSeparator = Regex.IsMatch(persianDateTimeInString, dateSeparatorPattern); 834 | 835 | persianDateTimeInString = ToEnglishNumber(persianDateTimeInString.Replace(" ", " ").Replace(" ", "-").Replace("\\", "-")); 836 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, dateSeparatorPattern, "-"); 837 | persianDateTimeInString = persianDateTimeInString.Replace("ك", "ک").Replace("ي", "ی"); 838 | 839 | persianDateTimeInString = $"-{persianDateTimeInString}-"; 840 | 841 | // بدست آوردن ب.ظ یا ق.ظ 842 | if (persianDateTimeInString.IndexOf("ق.ظ", StringComparison.InvariantCultureIgnoreCase) > -1) 843 | amPmEnum = AmPmEnum.AM; 844 | else if (persianDateTimeInString.IndexOf("ب.ظ", StringComparison.InvariantCultureIgnoreCase) > -1) 845 | amPmEnum = AmPmEnum.PM; 846 | 847 | if (persianDateTimeInString.IndexOf(":", StringComparison.InvariantCultureIgnoreCase) > -1) // رشته ورودی شامل ساعت نیز هست 848 | { 849 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, @"-*:-*", ":"); 850 | hour = Regex.Match(persianDateTimeInString, @"(?<=-)\d{1,2}(?=:)", RegexOptions.IgnoreCase).Value; 851 | minute = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:)\d{1,2}(?=:?)", RegexOptions.IgnoreCase).Value; 852 | if (persianDateTimeInString.IndexOf(':') != persianDateTimeInString.LastIndexOf(':')) 853 | { 854 | second = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:\d{1,2}:)\d{1,2}(?=(\d{1,2})?)", RegexOptions.IgnoreCase).Value; 855 | milliseconds = Regex.Match(persianDateTimeInString, @"(?<=-\d{1,2}:\d{1,2}:\d{1,2}:)\d{1,4}(?=(\d{1,2})?)", RegexOptions.IgnoreCase).Value; 856 | if (string.IsNullOrEmpty(milliseconds)) milliseconds = "0"; 857 | } 858 | } 859 | 860 | if (containMonthSeparator) 861 | { 862 | // بدست آوردن ماه 863 | month = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-)\d{1,2}(?=-\d{1,2}-\d{1,2}(?!-\d{1,2}:))", RegexOptions.IgnoreCase).Value; 864 | if (string.IsNullOrEmpty(month)) 865 | month = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-)\d{1,2}(?=-\d{1,2}[^:])", RegexOptions.IgnoreCase).Value; 866 | 867 | // بدست آوردن روز 868 | day = Regex.Match(persianDateTimeInString, @"(?<=\d{2,4}-\d{1,2}-)\d{1,2}(?=-)", RegexOptions.IgnoreCase).Value; 869 | 870 | // بدست آوردن سال 871 | year = Regex.Match(persianDateTimeInString, @"(?<=-)\d{2,4}(?=-\d{1,2}-\d{1,2})", RegexOptions.IgnoreCase).Value; 872 | } 873 | else 874 | { 875 | foreach (PersianDateTimeMonthEnum item in Enum.GetValues(typeof(PersianDateTimeMonthEnum))) 876 | { 877 | var itemValueInString = item.ToString(); 878 | if (!persianDateTimeInString.Contains(itemValueInString)) continue; 879 | month = ((int)item).ToString(CultureInfo.InvariantCulture); 880 | break; 881 | } 882 | 883 | if (string.IsNullOrEmpty(month)) 884 | throw new Exception("عدد یا حرف ماه در رشته ورودی وجود ندارد"); 885 | 886 | // بدست آوردن روز 887 | var dayMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{1,2}(?=-)", RegexOptions.IgnoreCase); 888 | if (dayMatch.Success) 889 | { 890 | day = dayMatch.Value; 891 | persianDateTimeInString = Regex.Replace(persianDateTimeInString, $"(?<=-){day}(?=-)", ""); 892 | } 893 | else 894 | throw new Exception("عدد روز در رشته ورودی وجود ندارد"); 895 | 896 | // بدست آوردن سال 897 | var yearMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{4}(?=-)", RegexOptions.IgnoreCase); 898 | if (yearMatch.Success) 899 | year = yearMatch.Value; 900 | else 901 | { 902 | yearMatch = Regex.Match(persianDateTimeInString, @"(?<=-)\d{2,4}(?=-)", RegexOptions.IgnoreCase); 903 | if (yearMatch.Success) 904 | year = yearMatch.Value; 905 | else 906 | throw new Exception("عدد سال در رشته ورودی وجود ندارد"); 907 | } 908 | } 909 | 910 | //if (year.Length <= 2 && year[0] == '9') year = string.Format("13{0}", year); 911 | //else if (year.Length <= 2) year = string.Format("14{0}", year); 912 | 913 | var numericYear = int.Parse(year); 914 | var numericMonth = int.Parse(month); 915 | var numericDay = int.Parse(day); 916 | var numericHour = int.Parse(hour); 917 | var numericMinute = int.Parse(minute); 918 | var numericSecond = int.Parse(second); 919 | var numericMilliseconds = int.Parse(milliseconds); 920 | 921 | if (numericYear < 100) 922 | numericYear += 1300; 923 | 924 | switch (amPmEnum) 925 | { 926 | case AmPmEnum.PM: 927 | if (numericHour < 12) 928 | numericHour = numericHour + 12; 929 | break; 930 | case AmPmEnum.AM: 931 | case AmPmEnum.None: 932 | break; 933 | } 934 | 935 | return new PersianDateTime(numericYear, numericMonth, numericDay, numericHour, numericMinute, numericSecond, numericMilliseconds); 936 | } 937 | 938 | /// 939 | /// پارس کردن یک رشته برای یافتن تاریخ شمسی 940 | /// 941 | public static bool TryParse(string persianDateTimeInString, out PersianDateTime result, string dateSeparatorPattern = @"\/|-") 942 | { 943 | if (string.IsNullOrEmpty(persianDateTimeInString)) 944 | { 945 | result = MinValue; 946 | return false; 947 | } 948 | try 949 | { 950 | result = Parse(persianDateTimeInString, dateSeparatorPattern); 951 | return true; 952 | } 953 | catch 954 | { 955 | result = MinValue; 956 | return false; 957 | } 958 | } 959 | 960 | /// 961 | /// پارس کردن عددی در فرمت تاریخ شمسی 962 | /// 963 | /// همانند 13920305 964 | /// 965 | public static PersianDateTime Parse(int numericPersianDate) 966 | { 967 | if (numericPersianDate.ToString(CultureInfo.InvariantCulture).Length != 8) 968 | throw new InvalidCastException("Numeric persian date must have a format like 13920101."); 969 | var year = numericPersianDate / 10000; 970 | var day = numericPersianDate % 100; 971 | var month = numericPersianDate / 100 % 100; 972 | return new PersianDateTime(year, month, day); 973 | } 974 | /// 975 | /// پارس کردن عددی در فرمت تاریخ شمسی 976 | /// 977 | /// همانند 13920305 978 | /// 979 | public static bool TryParse(int numericPersianDate, out PersianDateTime result) 980 | { 981 | try 982 | { 983 | result = Parse(numericPersianDate); 984 | return true; 985 | } 986 | catch 987 | { 988 | result = MinValue; 989 | return false; 990 | } 991 | } 992 | 993 | /// 994 | /// پارس کردن عددی در فرمت تاریخ و زمان شمسی 995 | /// 996 | /// همانند 13961223072132004 997 | /// 998 | public static PersianDateTime Parse(long numericPersianDateTime) 999 | { 1000 | if (numericPersianDateTime.ToString(CultureInfo.InvariantCulture).Length != 17) 1001 | throw new InvalidCastException("Numeric persian date time must have a format like 1396122310223246."); 1002 | var year = numericPersianDateTime / 10000000000000; 1003 | var month = numericPersianDateTime / 100000000000 % 100; 1004 | var day = numericPersianDateTime / 1000000000 % 100; 1005 | var hour = numericPersianDateTime / 10000000 % 100; 1006 | var minute = numericPersianDateTime / 100000 % 100; 1007 | var second = numericPersianDateTime / 1000 % 100; 1008 | var millisecond = numericPersianDateTime % 1000; 1009 | return new PersianDateTime((int)year, (int)month, (int)day, (int)hour, (int)minute, (int)second, (int)millisecond); 1010 | } 1011 | /// 1012 | /// پارس کردن عددی در فرمت تاریخ و زمان شمسی 1013 | /// 1014 | /// همانند 13961223102232461 1015 | /// 1016 | public static bool TryParse(long numericPersianDateTime, out PersianDateTime result) 1017 | { 1018 | try 1019 | { 1020 | result = Parse(numericPersianDateTime); 1021 | return true; 1022 | } 1023 | catch 1024 | { 1025 | result = MinValue; 1026 | return false; 1027 | } 1028 | } 1029 | 1030 | private static readonly List GregorianWeekDayNames = new List { "monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" }; 1031 | private static readonly List GregorianMonthNames = new List { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december" }; 1032 | private static readonly List PmAm = new List { "pm", "am" }; 1033 | 1034 | /// 1035 | /// فرمت های که پشتیبانی می شوند 1036 | /// 1037 | /// yyyy: سال چهار رقمی 1038 | /// 1039 | /// yy: سال دو رقمی 1040 | /// 1041 | /// MMMM: نام فارسی ماه 1042 | /// 1043 | /// MM: عدد دو رقمی ماه 1044 | /// 1045 | /// M: عدد یک رقمی ماه 1046 | /// 1047 | /// dddd: نام فارسی روز هفته 1048 | /// 1049 | /// dd: عدد دو رقمی روز ماه 1050 | /// 1051 | /// d: عدد یک رقمی روز ماه 1052 | /// 1053 | /// HH: ساعت دو رقمی با فرمت 00 تا 24 1054 | /// 1055 | /// H: ساعت یک رقمی با فرمت 0 تا 24 1056 | /// 1057 | /// hh: ساعت دو رقمی با فرمت 00 تا 12 1058 | /// 1059 | /// h: ساعت یک رقمی با فرمت 0 تا 12 1060 | /// 1061 | /// mm: عدد دو رقمی دقیقه 1062 | /// 1063 | /// m: عدد یک رقمی دقیقه 1064 | /// 1065 | /// ss: ثانیه دو رقمی 1066 | /// 1067 | /// s: ثانیه یک رقمی 1068 | /// 1069 | /// fff: میلی ثانیه 3 رقمی 1070 | /// 1071 | /// ff: میلی ثانیه 2 رقمی 1072 | /// 1073 | /// f: میلی ثانیه یک رقمی 1074 | /// 1075 | /// tt: ب.ظ یا ق.ظ 1076 | /// 1077 | /// t: حرف اول از ب.ظ یا ق.ظ 1078 | /// 1079 | public string ToString(string format, IFormatProvider fp = null) 1080 | { 1081 | if (string.IsNullOrEmpty(format)) format = "yyyy/MM/dd HH:mm:ss"; 1082 | var dateTimeString = format.Trim(); 1083 | 1084 | dateTimeString = dateTimeString.Replace("yyyy", Year.ToString(CultureInfo.InvariantCulture)); 1085 | dateTimeString = dateTimeString.Replace("yy", GetShortYear.ToString("00", CultureInfo.InvariantCulture)); 1086 | dateTimeString = dateTimeString.Replace("MMMM", MonthName); 1087 | dateTimeString = dateTimeString.Replace("MM", Month.ToString("00", CultureInfo.InvariantCulture)); 1088 | dateTimeString = dateTimeString.Replace("M", Month.ToString(CultureInfo.InvariantCulture)); 1089 | dateTimeString = dateTimeString.Replace("dddd", GetLongDayOfWeekName); 1090 | dateTimeString = dateTimeString.Replace("dd", Day.ToString("00", CultureInfo.InvariantCulture)); 1091 | dateTimeString = dateTimeString.Replace("d", Day.ToString(CultureInfo.InvariantCulture)); 1092 | dateTimeString = dateTimeString.Replace("HH", Hour.ToString("00", CultureInfo.InvariantCulture)); 1093 | dateTimeString = dateTimeString.Replace("H", Hour.ToString(CultureInfo.InvariantCulture)); 1094 | dateTimeString = dateTimeString.Replace("hh", ShortHour.ToString("00", CultureInfo.InvariantCulture)); 1095 | dateTimeString = dateTimeString.Replace("h", ShortHour.ToString(CultureInfo.InvariantCulture)); 1096 | dateTimeString = dateTimeString.Replace("mm", Minute.ToString("00", CultureInfo.InvariantCulture)); 1097 | dateTimeString = dateTimeString.Replace("m", Minute.ToString(CultureInfo.InvariantCulture)); 1098 | dateTimeString = dateTimeString.Replace("ss", Second.ToString("00", CultureInfo.InvariantCulture)); 1099 | dateTimeString = dateTimeString.Replace("s", Second.ToString(CultureInfo.InvariantCulture)); 1100 | dateTimeString = dateTimeString.Replace("fff", Millisecond.ToString("000", CultureInfo.InvariantCulture)); 1101 | dateTimeString = dateTimeString.Replace("ff", (Millisecond / 10).ToString("00", CultureInfo.InvariantCulture)); 1102 | dateTimeString = dateTimeString.Replace("f", (Millisecond / 100).ToString(CultureInfo.InvariantCulture)); 1103 | dateTimeString = dateTimeString.Replace("tt", GetPersianAmPm); 1104 | dateTimeString = dateTimeString.Replace("t", GetPersianAmPm[0].ToString(CultureInfo.InvariantCulture)); 1105 | 1106 | if (PersianNumber) 1107 | dateTimeString = ToPersianNumber(dateTimeString); 1108 | 1109 | return dateTimeString; 1110 | } 1111 | 1112 | /// 1113 | /// بررسی میکند آیا تاریخ ورودی تاریخ میلادی است یا نه 1114 | /// 1115 | public static bool IsChristianDate(string inputString) 1116 | { 1117 | inputString = inputString.ToLower(); 1118 | bool result; 1119 | 1120 | foreach (var gregorianWeekDayName in GregorianWeekDayNames) 1121 | { 1122 | result = inputString.Contains(gregorianWeekDayName); 1123 | if (result) return true; 1124 | } 1125 | 1126 | foreach (var gregorianMonthName in GregorianMonthNames) 1127 | { 1128 | result = inputString.Contains(gregorianMonthName); 1129 | if (result) return true; 1130 | } 1131 | 1132 | foreach (var item in PmAm) 1133 | { 1134 | result = inputString.Contains(item); 1135 | if (result) return true; 1136 | } 1137 | 1138 | result = Regex.IsMatch(inputString, @"(1[8-9]|[2-9][0-9])\d{2}", RegexOptions.IgnoreCase); 1139 | 1140 | return result; 1141 | } 1142 | 1143 | /// 1144 | /// بررسی میکند آیا تاریخ ورودی مطابق تاریخ اس کسو ال سرور می باشد یا نه 1145 | /// 1146 | public static bool IsSqlDateTime(DateTime dateTime) 1147 | { 1148 | var minSqlDateTimeValue = new DateTime(1753, 1, 1); 1149 | return dateTime >= minSqlDateTimeValue; 1150 | } 1151 | 1152 | /// 1153 | /// تبدیل نام ماه شمسی به عدد معادل آن 1154 | /// 1155 | /// به طور مثال آذر را به 9 تبدیل می کند 1156 | /// 1157 | public int GetMonthEnum(string longMonthName) 1158 | { 1159 | var monthEnum = (PersianDateTimeMonthEnum)Enum.Parse(typeof(PersianDateTimeMonthEnum), longMonthName); 1160 | return (int)monthEnum; 1161 | } 1162 | 1163 | /// 1164 | /// نمایش تاریخ به فرمتی مشابه زیر 1165 | /// 1166 | /// 1393/09/14 1167 | /// 1168 | public string ToShortDateString() 1169 | { 1170 | var result = $"{Year:0000}/{Month:00}/{Day:00}"; 1171 | if (!PersianNumber) return result; 1172 | return ToPersianNumber(result); 1173 | } 1174 | 1175 | /// 1176 | /// نمایش تاریخ به فرمتی مشابه زیر 1177 | /// 1178 | /// ج 14 آذر 93 1179 | /// 1180 | public string ToShortDate1String() 1181 | { 1182 | var result = $"{GetShortDayOfWeekName} {Day:00} {GetLongMonthName} {GetShortYear}"; 1183 | if (!PersianNumber) return result; 1184 | return ToPersianNumber(result); 1185 | } 1186 | 1187 | /// 1188 | /// نمایش تاریخ به صورت عدد و در فرمتی مشابه زیر 1189 | /// 1190 | /// 13930914 1191 | /// 1192 | public int ToShortDateInt() 1193 | { 1194 | return int.Parse($"{Year:0000}{Month:00}{Day:00}"); 1195 | } 1196 | 1197 | /// 1198 | /// نمایش تاریخ و ساعت تا دقت میلی ثانیه به صورت عدد 1199 | /// 1200 | /// 1396122310324655 1201 | /// 1202 | public long ToLongDateTimeInt() 1203 | { 1204 | return long.Parse($"{Year:0000}{Month:00}{Day:00}{Hour:00}{Minute:00}{Second:00}{Millisecond:000}"); 1205 | } 1206 | 1207 | /// 1208 | /// در این فرمت نمایش ساعت و دقیقه و ثانیه در کنار هم با حذف علامت : تبدیل به عدد می شوند و نمایش داده می شود 1209 | /// 1210 | /// مثال: 123452 1211 | /// 1212 | /// که به معنای ساعت 12 و 34 دقیقه و 52 ثانیه می باشد 1213 | /// 1214 | public int ToTimeInt() 1215 | { 1216 | return int.Parse($"{Hour:00}{Minute:00}{Second:00}"); 1217 | } 1218 | 1219 | /// 1220 | /// در این فرمت نمایش ساعت و دقیقه در کنار هم با حذف علامت : تبدیل به عدد می شوند و نمایش داده می شود 1221 | /// 1222 | /// مثال: 1234 1223 | /// 1224 | /// که به معنای ساعت 12 و 34 دقیقه می باشد 1225 | /// 1226 | public short ToTimeShort() 1227 | { 1228 | return short.Parse($"{Hour:00}{Minute:00}"); 1229 | } 1230 | 1231 | /// 1232 | /// نمایش تاریخ به فرمتی مشابه زیر 1233 | /// 1234 | /// جمعه، 14 آذر 1393 1235 | /// 1236 | public string ToLongDateString() 1237 | { 1238 | var result = $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000}"; 1239 | if (!PersianNumber) return result; 1240 | return ToPersianNumber(result); 1241 | } 1242 | 1243 | /// 1244 | /// نمایش تاریخ و زمان به فرمتی مشابه زیر 1245 | /// 1246 | /// جمعه، 14 آذر 1393 ساعت 13:50:27 1247 | /// 1248 | public string ToLongDateTimeString() 1249 | { 1250 | var result = $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000} ساعت {Hour:00}:{Minute:00}:{Second:00}"; 1251 | if (!PersianNumber) return result; 1252 | return ToPersianNumber(result); 1253 | } 1254 | 1255 | /// 1256 | /// نمایش تاریخ و زمان به فرمتی مشابه زیر 1257 | /// 1258 | /// جمعه، 14 آذر 1393 13:50 1259 | /// 1260 | public string ToShortDateTimeString() 1261 | { 1262 | var result = $"{GetLongDayOfWeekName}، {Day:00} {GetLongMonthName} {Year:0000} {Hour:00}:{Minute:00}"; 1263 | if (!PersianNumber) return result; 1264 | return ToPersianNumber(result); 1265 | } 1266 | 1267 | /// 1268 | /// نمایش زمان به فرمتی مشابه زیر 1269 | /// 1270 | /// 01:50 ب.ظ 1271 | /// 1272 | public string ToShortTimeString() 1273 | { 1274 | var result = $"{ShortHour:00}:{Minute:00} {GetPersianAmPm}"; 1275 | if (!PersianNumber) return result; 1276 | return ToPersianNumber(result); 1277 | } 1278 | 1279 | /// 1280 | /// نمایش زمان به فرمتی مشابه زیر 1281 | /// 1282 | /// 13:50:20 1283 | /// 1284 | public string ToLongTimeString() 1285 | { 1286 | var result = $"{Hour:00}:{Minute:00}:{Second:00}"; 1287 | if (!PersianNumber) return result; 1288 | return ToPersianNumber(result); 1289 | } 1290 | 1291 | /// 1292 | /// نمایش زمان به فرمتی مشابه زیر 1293 | /// 1294 | /// 1 دقیقه قبل 1295 | /// 1296 | public string ElapsedTime() 1297 | { 1298 | var persianDateTimeNow = new PersianDateTime(DateTime.Now); 1299 | var timeSpan = persianDateTimeNow - _dateTime; 1300 | if (timeSpan.TotalDays > 90) 1301 | return ToShortDateTimeString(); 1302 | 1303 | var result = string.Empty; 1304 | if (timeSpan.TotalDays > 30) 1305 | { 1306 | var month = timeSpan.TotalDays / 30; 1307 | if (month > 0) 1308 | result = $"{month:0} ماه قبل"; 1309 | } 1310 | else if (timeSpan.TotalDays >= 1) 1311 | { 1312 | result = $"{timeSpan.TotalDays:0} روز قبل"; 1313 | } 1314 | else if (timeSpan.TotalHours >= 1) 1315 | { 1316 | result = $"{timeSpan.TotalHours:0} ساعت قبل"; 1317 | } 1318 | else 1319 | { 1320 | var minute = timeSpan.TotalMinutes; 1321 | if (minute <= 1) minute = 1; 1322 | result = $"{minute:0} دقیقه قبل"; 1323 | } 1324 | if (!PersianNumber) return result; 1325 | return ToPersianNumber(result); 1326 | } 1327 | 1328 | /// 1329 | /// گرفتن فقط زمان 1330 | /// 1331 | public TimeSpan GetTime() 1332 | { 1333 | return new TimeSpan(0, _dateTime.Hour, _dateTime.Minute, _dateTime.Second, _dateTime.Millisecond); 1334 | } 1335 | 1336 | /// 1337 | /// تنظیم کردن زمان 1338 | /// 1339 | public PersianDateTime SetTime(int hour, int minute, int second = 0, int milliseconds = 0) 1340 | { 1341 | return new PersianDateTime(Year, Month, Day, hour, minute, second, milliseconds); 1342 | } 1343 | 1344 | /// 1345 | /// تبدیل به تاریخ میلادی 1346 | /// 1347 | public DateTime ToDateTime() 1348 | { 1349 | return _dateTime; 1350 | } 1351 | 1352 | /// 1353 | /// تبدیل به تاریخ هجری قمری 1354 | /// 1355 | public HijriDateTime ToHijri(int hijriAdjustment = 0) 1356 | { 1357 | var hijriCalendar = new HijriCalendar 1358 | { 1359 | HijriAdjustment = hijriAdjustment 1360 | }; 1361 | var month = hijriCalendar.GetMonth(_dateTime); 1362 | var monthName = ""; 1363 | switch (month) 1364 | { 1365 | case 1: 1366 | monthName = "محرم"; 1367 | break; 1368 | case 2: 1369 | monthName = "صفر"; 1370 | break; 1371 | case 3: 1372 | monthName = "ربیع الاول"; 1373 | break; 1374 | case 4: 1375 | monthName = "ربیع الثانی"; 1376 | break; 1377 | case 5: 1378 | monthName = "جمادل الاولی"; 1379 | break; 1380 | case 6: 1381 | monthName = "جمادی الاخره"; 1382 | break; 1383 | case 7: 1384 | monthName = "رجب"; 1385 | break; 1386 | case 8: 1387 | monthName = "شعبان"; 1388 | break; 1389 | case 9: 1390 | monthName = "رمضان"; 1391 | break; 1392 | case 10: 1393 | monthName = "شوال"; 1394 | break; 1395 | case 11: 1396 | monthName = "ذوالقعده"; 1397 | break; 1398 | case 12: 1399 | monthName = "ذوالحجه"; 1400 | break; 1401 | } 1402 | return new HijriDateTime 1403 | { 1404 | Day = hijriCalendar.GetDayOfMonth(_dateTime), 1405 | Month = month, 1406 | Year = hijriCalendar.GetYear(_dateTime), 1407 | MonthName = monthName 1408 | }; 1409 | } 1410 | 1411 | /// 1412 | /// کم کردن دو تاریخ از هم 1413 | /// 1414 | public TimeSpan Subtract(PersianDateTime persianDateTime) 1415 | { 1416 | return _dateTime - persianDateTime.ToDateTime(); 1417 | } 1418 | 1419 | /// 1420 | /// تعداد ماه اختلافی با تاریخ دیگری را بر میگرداند 1421 | /// 1422 | /// تعداد ماه 1423 | public int MonthDifference(DateTime dateTime) 1424 | { 1425 | return Math.Abs(dateTime.Month - _dateTime.Month + 12 * (dateTime.Year - _dateTime.Year)); 1426 | } 1427 | 1428 | /// 1429 | /// اضافه کردن مدت زمانی به تاریخ 1430 | /// 1431 | public PersianDateTime Add(TimeSpan timeSpan) 1432 | { 1433 | return new PersianDateTime(_dateTime.Add(timeSpan), PersianNumber); 1434 | } 1435 | 1436 | /// 1437 | /// اضافه کردن سال به تاریخ 1438 | /// 1439 | public PersianDateTime AddYears(int years) 1440 | { 1441 | return new PersianDateTime(PersianCalendar.AddYears(_dateTime, years), PersianNumber); 1442 | } 1443 | 1444 | /// 1445 | /// اضافه کردن روز به تاریخ 1446 | /// 1447 | public PersianDateTime AddDays(int days) 1448 | { 1449 | return new PersianDateTime(PersianCalendar.AddDays(_dateTime, days), PersianNumber); 1450 | } 1451 | 1452 | /// 1453 | /// اضافه کردن ماه به تاریخ 1454 | /// 1455 | public PersianDateTime AddMonths(int months) 1456 | { 1457 | return new PersianDateTime(PersianCalendar.AddMonths(_dateTime, months), PersianNumber); 1458 | } 1459 | 1460 | /// 1461 | /// اضافه کردن ساعت به تاریخ 1462 | /// 1463 | public PersianDateTime AddHours(int hours) 1464 | { 1465 | return new PersianDateTime(_dateTime.AddHours(hours), PersianNumber); 1466 | } 1467 | 1468 | /// 1469 | /// اضافه کردن دقیقه به تاریخ 1470 | /// 1471 | public PersianDateTime AddMinutes(int minutes) 1472 | { 1473 | return new PersianDateTime(_dateTime.AddMinutes(minutes), PersianNumber); 1474 | } 1475 | 1476 | /// 1477 | /// اضافه کردن ثانیه به تاریخ 1478 | /// 1479 | public PersianDateTime AddSeconds(int seconds) 1480 | { 1481 | return new PersianDateTime(_dateTime.AddSeconds(seconds), PersianNumber); 1482 | } 1483 | 1484 | /// 1485 | /// اضافه کردن میلی ثانیه به تاریخ 1486 | /// 1487 | public PersianDateTime AddMilliseconds(int milliseconds) 1488 | { 1489 | return new PersianDateTime(_dateTime.AddMilliseconds(milliseconds), PersianNumber); 1490 | } 1491 | 1492 | /// 1493 | /// بدست آوردن تاریخ شمسی اولین روز هفته 1494 | /// 1495 | public PersianDateTime GetFirstDayOfWeek() 1496 | { 1497 | var persianDateTime = new PersianDateTime(_dateTime).Date; 1498 | return persianDateTime.AddDays(PersianDayOfWeek.Saturday - persianDateTime.PersianDayOfWeek); 1499 | } 1500 | 1501 | /// 1502 | /// بدست آوردن تاریخ شمسی آخرین روز هفته 1503 | /// 1504 | public PersianDateTime GetPersianWeekend() 1505 | { 1506 | var persianDateTime = new PersianDateTime(_dateTime).Date; 1507 | return persianDateTime.AddDays(PersianDayOfWeek.Friday - persianDateTime.PersianDayOfWeek); 1508 | } 1509 | 1510 | /// 1511 | /// نام فارسی ماه بر اساس شماره ماه 1512 | /// 1513 | /// نام فارسی ماه 1514 | public static string GetPersianMonthName(int monthNumber) 1515 | { 1516 | return GetPersianMonthNamePrivate(monthNumber); 1517 | } 1518 | 1519 | private static string ToPersianNumber(string input) 1520 | { 1521 | if (string.IsNullOrEmpty(input)) return null; 1522 | input = input.Replace("ي", "ی").Replace("ك", "ک"); 1523 | 1524 | //۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ 1525 | return 1526 | input 1527 | .Replace("0", "۰") 1528 | .Replace("1", "۱") 1529 | .Replace("2", "۲") 1530 | .Replace("3", "۳") 1531 | .Replace("4", "۴") 1532 | .Replace("5", "۵") 1533 | .Replace("6", "۶") 1534 | .Replace("7", "۷") 1535 | .Replace("8", "۸") 1536 | .Replace("9", "۹"); 1537 | } 1538 | 1539 | private static string ToEnglishNumber(string input) 1540 | { 1541 | if (string.IsNullOrEmpty(input)) return null; 1542 | input = input.Replace("ي", "ی").Replace("ك", "ک"); 1543 | 1544 | //۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ 1545 | return input 1546 | .Replace(",", "") 1547 | .Replace("۰", "0") 1548 | .Replace("۱", "1") 1549 | .Replace("۲", "2") 1550 | .Replace("۳", "3") 1551 | .Replace("۴", "4") 1552 | .Replace("۵", "5") 1553 | .Replace("۶", "6") 1554 | .Replace("۷", "7") 1555 | .Replace("۸", "8") 1556 | .Replace("۹", "9"); 1557 | } 1558 | 1559 | private static string GetPersianMonthNamePrivate(int monthNumber) 1560 | { 1561 | var monthName = ""; 1562 | switch (monthNumber) 1563 | { 1564 | case 1: 1565 | monthName = "فروردین"; 1566 | break; 1567 | 1568 | case 2: 1569 | monthName = "اردیبهشت"; 1570 | break; 1571 | 1572 | case 3: 1573 | monthName = "خرداد"; 1574 | break; 1575 | 1576 | case 4: 1577 | monthName = "تیر"; 1578 | break; 1579 | 1580 | case 5: 1581 | monthName = "مرداد"; 1582 | break; 1583 | 1584 | case 6: 1585 | monthName = "شهریور"; 1586 | break; 1587 | 1588 | case 7: 1589 | monthName = "مهر"; 1590 | break; 1591 | 1592 | case 8: 1593 | monthName = "آبان"; 1594 | break; 1595 | 1596 | case 9: 1597 | monthName = "آذر"; 1598 | break; 1599 | 1600 | case 10: 1601 | monthName = "دی"; 1602 | break; 1603 | 1604 | case 11: 1605 | monthName = "بهمن"; 1606 | break; 1607 | 1608 | case 12: 1609 | monthName = "اسفند"; 1610 | break; 1611 | } 1612 | return monthName; 1613 | } 1614 | 1615 | #endregion 1616 | 1617 | #region IConvertible 1618 | 1619 | /// 1620 | public TypeCode GetTypeCode() 1621 | { 1622 | return TypeCode.DateTime; 1623 | } 1624 | 1625 | /// 1626 | public bool ToBoolean(IFormatProvider provider) 1627 | { 1628 | return _dateTime > DateTime.MinValue; 1629 | } 1630 | 1631 | /// 1632 | public byte ToByte(IFormatProvider provider) 1633 | { 1634 | throw new InvalidCastException(); 1635 | } 1636 | 1637 | /// 1638 | public char ToChar(IFormatProvider provider) 1639 | { 1640 | throw new InvalidCastException(); 1641 | } 1642 | 1643 | /// 1644 | public DateTime ToDateTime(IFormatProvider provider) 1645 | { 1646 | return _dateTime; 1647 | } 1648 | 1649 | /// 1650 | public decimal ToDecimal(IFormatProvider provider) 1651 | { 1652 | return ToLongDateTimeInt(); 1653 | } 1654 | 1655 | /// 1656 | public double ToDouble(IFormatProvider provider) 1657 | { 1658 | return ToLongDateTimeInt(); 1659 | } 1660 | 1661 | /// 1662 | public short ToInt16(IFormatProvider provider) 1663 | { 1664 | throw new InvalidCastException(); 1665 | } 1666 | 1667 | /// 1668 | public int ToInt32(IFormatProvider provider) 1669 | { 1670 | return ToShortDateInt(); 1671 | } 1672 | 1673 | /// 1674 | public long ToInt64(IFormatProvider provider) 1675 | { 1676 | return ToLongDateTimeInt(); 1677 | } 1678 | 1679 | /// 1680 | public sbyte ToSByte(IFormatProvider provider) 1681 | { 1682 | throw new InvalidCastException(); 1683 | } 1684 | 1685 | /// 1686 | public float ToSingle(IFormatProvider provider) 1687 | { 1688 | throw new InvalidCastException(); 1689 | } 1690 | 1691 | /// 1692 | public string ToString(IFormatProvider provider) 1693 | { 1694 | return ToString("", provider); 1695 | } 1696 | 1697 | /// 1698 | public object ToType(Type conversionType, IFormatProvider provider) 1699 | { 1700 | switch (Type.GetTypeCode(conversionType)) 1701 | { 1702 | case TypeCode.Boolean: 1703 | return ToBoolean(provider); 1704 | case TypeCode.Byte: 1705 | return ToByte(provider); 1706 | case TypeCode.Char: 1707 | return ToChar(provider); 1708 | case TypeCode.DateTime: 1709 | return ToDateTime(provider); 1710 | case TypeCode.Decimal: 1711 | return ToDecimal(provider); 1712 | case TypeCode.Double: 1713 | return ToDouble(provider); 1714 | case TypeCode.Int16: 1715 | return ToInt16(provider); 1716 | case TypeCode.Int32: 1717 | return ToInt32(provider); 1718 | case TypeCode.Int64: 1719 | return ToInt64(provider); 1720 | case TypeCode.Object: 1721 | if (typeof(PersianDateTime) == conversionType) 1722 | return this; 1723 | if (typeof(DateTime) == conversionType) 1724 | return ToDateTime(); 1725 | throw new InvalidCastException($"Conversion to a {conversionType.Name} is not supported."); 1726 | case TypeCode.SByte: 1727 | return ToSByte(provider); 1728 | case TypeCode.Single: 1729 | return ToSingle(provider); 1730 | case TypeCode.String: 1731 | return ToString(provider); 1732 | case TypeCode.UInt16: 1733 | return ToUInt16(provider); 1734 | case TypeCode.UInt32: 1735 | return ToUInt32(provider); 1736 | case TypeCode.UInt64: 1737 | return ToUInt64(provider); 1738 | case TypeCode.DBNull: 1739 | break; 1740 | case TypeCode.Empty: 1741 | break; 1742 | default: 1743 | throw new InvalidCastException($"Conversion to {conversionType.Name} is not supported."); 1744 | } 1745 | throw new InvalidCastException(); 1746 | } 1747 | 1748 | /// 1749 | public ushort ToUInt16(IFormatProvider provider) 1750 | { 1751 | throw new InvalidCastException(); 1752 | } 1753 | 1754 | /// 1755 | public uint ToUInt32(IFormatProvider provider) 1756 | { 1757 | return (uint)ToShortDateInt(); 1758 | } 1759 | 1760 | /// 1761 | public ulong ToUInt64(IFormatProvider provider) 1762 | { 1763 | return (ulong)ToLongDateTimeInt(); 1764 | } 1765 | 1766 | #endregion 1767 | } 1768 | } --------------------------------------------------------------------------------