آموزش تبدیل تاریخ میلادی به شمسی و شمسی به میلادی در ASP.NET

چگونه در ASP.NET تاریخ میلادی را به شمسی تبدیل کنیم؟ فرض کنید درون پایگاه داده SQL Server جدولی ساخته اید و یکی از ستون های آن را از نوع datetime تعریف کرده اید. استفاده از نوع داده ای datetime کاربر را ملزم می کند که فقط از تاریخ های میلادی استفاده کند. در صورتی که کاربر از تاریخ های دیگری (مثلا هجری شمسی) استفاده کند، با خطا مواجه می شود. در ادامه، با به کارگیری زبان سی شارپ راهکاری برای رفع این مشکل ارائه می دهیم.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران

یکی از اولین راه حل هایی که برای غلبه بر این مشکل به ذهن میرسد این است که به جای تعریف ستون جدول از نوع datetime، آن را از نوع nvarchar تعریف کنیم. این کار سبب می شود که کاربر تاریخ مورد نظر خود را درون پایگاه داده به صورت رشته وارد کند. راهکار ذکر شده در مواردی می تواند مفید واقع شود اما مشکلاتی را نیز به همراه دارد و ممکن است در بعضی مواقع پاسخگوی نیازهای ما نباشد.

روش دیگر این است که تاریخ هجری شمسی وارد شده توسط کاربر را به طریقی به میلادی تبدیل کنیم و سپس تاریخ میلادی به دست آمده را درون فیلدی که از نوع datetime است ذخیره کنیم. این کار با استفاده از کلاس PersianCalendar که در فضای نام System.Globalization واقع است امکان پذیر می باشد. کلاس PersianCalendar دارای متدهایی گوناگونی است که در ادامه به برخی از آن ها اشاره می کنیم:

  • (ToDateTime (int yaer, int month, int day, int hour, int minute, int second, int millisecond : این متد تاریخ را از هجری شمسی به میلادی تبدیل می کند، به این ترتیب که سال، ماه و روز (به هجری شمسی) را گرفته و شی ای از نوع DateTime برای ما برمی گرداند. ما می توانیم از همین شی DateTime برگردانده شده توسط این متد برای نوشتن تاریخ در پایگاه داده استفاده کنیم.(در ادامه خواهیم دید)
  • (GetDayOfMonth (DateTime time: این متد شی ای از نوع DateTime را به عنوان آرگومان می پذیرد و یک عدد integer برمیگرداند. این عدد نشان دهنده چندمین روز ماه در تاریخ هجری شمسی می باشد.
  • (GetMonth (DateTime time : این متد شی ای از نوع DateTime را به عنوان آرگومان می پذیرد و یک عدد integer برمیگرداند. این عدد نشان دهنده چندمین ماه سال در تاریخ هجری شمسی می باشد.
  • (GetYear (DateTime time : این متد شی ای از نوع DateTime را به عنوان آرگومان می پذیرد و یک عدد integer برمیگرداند. این عدد نشان دهنده سال در تاریخ هجری شمسی می باشد.

بعد از خواندن فیلدی از نوع datetime از پایگاه داده، میتوانیم با استفاده از متدهای GetDayOfMonth ، GetMonth و GetYear آن را به هجری شمسی تبدیل کرده و سپس به کاربر نمایش دهیم.(در ادامه خواهیم دید) بدین ترتیب کاربر تاریخ مورد نظر خود را از طریق واسط کاربر به صورت هجری شمسی وارد می کند و هنگامی هم که می خواهد آن ها را از پایگاه داده بازیابی کند، آن ها را به صورت هجری شمسی مشاهده خواهد کرد، اما در اصل، داده ها درون پایگاه داده به شکل صحیح خود یعنی میلادی وارد شده اند.حال جهت ارائه یک مثال، با استفاده از ASP.NET یک webform به عنوان واسط کاربر طراحی می کنیم و موارد ذکر شده را با استفاده از آن توضیح خواهیم داد.

  • توجه: منطق کار در صورت استفاده از winform به عنوان واسط کاربر یکسان خواهد بود.

در اینجا می خواهیم از پایگاه داده Northwind استفاده کرده و نام، نام خانوادگی و تاریخ استخدام افراد را از جدول Employees بازیابی کنیم و آن ها را در یک gridview نمایش دهیم. همچنین می خواهیم امکان وارد کردن کارمند جدید به این جدول را نیز داشته باشیم. پس فرمی مانند زیر طراحی کرده و برای برقراری ارتباط با پایگاه، یک SqlDataSource نیز به آن اضافه می کنیم:

وب سایت توسینسو

سپس تنظیمات لازم را برای ارتباط SqlDataSource با پایگاه داده Northwind و بازیابی نام، نام خانوادگی و تاریخ استخدام کارمندان را انجام می دهیم:

<asp:GridView ID="gvEmployees" CssClass="gridStyle" runat="server" Caption="کارمندان موجود در پایگاه داده" DataSourceID="sqlDtSrcEmployees">
<AlternatingRowStyle BackColor="#FF99CC" />
<EditRowStyle BackColor="#FF99CC" />
<HeaderStyle BackColor="#FF66CC" Font-Bold="True" Font-Names="Calibri" ForeColor="White" />
<RowStyle BackColor="#FFCCFF" Font-Names="Calibri" HorizontalAlign="Center" />
</asp:GridView>
<asp:SqlDataSource ID="sqlDtSrcEmployees" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"
InsertCommand="INSERT INTO [Employees] ([LastName], [FirstName], [HireDate]) VALUES (@LastName, @FirstName, @HireDate)"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT [EmployeeID], [LastName], [FirstName], [HireDate] FROM [Employees]">
<InsertParameters>
<asp:ControlParameter ControlID="txtLastName" Name="LastName" PropertyName="Text" Type="String" />
<asp:ControlParameter ControlID="txtFirstName" Name="FirstName" PropertyName="Text" Type="String" />
<asp:Parameter Name="HireDate" Type="DateTime" />
</InsertParameters>
</asp:SqlDataSource>

حال به قسمت مورد بحث یعنی بازیابی تاریخ به صورت هجری شمسی می پردازیم. GridView دارای یک رویداد به نام RowDataBound می باشد. این رویداد بعد از databound شدن هر سطر GridView اتفاق می افتد. می توانیم از این رویداد استفاده کرده و پس از Databound شدن هر سطر، فیلد تاریخ آن را با استفاده از متدهای ذکر شده در بالا از میلادی به هجری شمسی تبدیل کنیم:

protected void gvEmployees_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        try
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                DateTime usDate = (DateTime)DataBinder.Eval(e.Row.DataItem, "HireDate");
                System.Globalization.PersianCalendar faDate = new System.Globalization.PersianCalendar();

                string day = faDate.GetDayOfMonth(usDate).ToString("D2");
                string month = faDate.GetMonth(usDate).ToString("D2");
                string year = faDate.GetYear(usDate).ToString("D4");

                e.Row.Cells[3].Text = string.Format("{0} / {1} / {2}", year, month, day);
            }
        }
        catch { }
    }
  • توجه: عبارت (if (e.Row.RowType == DataControlRowType.DataRow الزامی است و حتما باید حضور داشته باشد.

اگر برنامه را اجرا کنید، نتیجه ای مانند زیر مشاهده خواهید کرد. (تمامی تاریخ های زیر ستون HireDate به هجری شمسی تبدیل شده اند.)

وب سایت توسینسو

حال به حالتی می پردازیم که کاربر می خواهد کارمند جدیدی را در پایگاه داده ثبت کند و تاریخ استخدام را نیز به هجری شمسی وارد می کند. ما باید قبل از اجرای دستور insert تاریخ وارد شده را به میلادی تبدیل کنیم. برای این کار به سراغ SqlDataSource می رویم. SqlDataSource دارای رویدادی به نام Inserting می باشد. این رویداد دقیقا قبل از این که عملیات Insert اجرا شود، فعال می شود و ما می توانیم از طریق آن پارامترهای لازم را برای دستور insert فراهم کنیم. (مثلا تاریخ وارد شده توسط کاربر را به میلادی تبدیل کنیم):

protected void sqlDtSrcEmployees_Inserting(object sender, SqlDataSourceCommandEventArgs e)
    {
        try
        {
            int day = Convert.ToInt32(txtHireDay.Text);
            int month = Convert.ToInt32(txtHireMonth.Text);
            int year = Convert.ToInt32(txtHireYear.Text);

            System.Globalization.PersianCalendar faDate = new System.Globalization.PersianCalendar();
            e.Command.Parameters["@HireDate"].Value = faDate.ToDateTime(year, month, day, 23, 0, 0, 0);
        }
        catch { }
    }
  • توجه: متد ToDateTime علاوه بر آرگومان های year، month و day (که به صورت هجری شمسی وارد می شوند) نیاز به چهار آرگومان دیگر یعنی hour، minute ، second و millisecond نیز دارد که شما می توانید به آن ها مقادیر دلخواه خود بدهید.

SqlDataSource هم چنین یک متد به نام ()Insert دارد که با فراخوانی آن InsertCommand اجرا شده و داده درون پایگاه داده ثبت می شود. این متد را درون رویداد کلیک دکمه موجود روی فرم، فراخوانی می کنیم:

protected void btnInsert_Click(object sender, EventArgs e)
    {
        sqlDtSrcEmployees.Insert();
    }

حال برنامه را اجرا کرده و داده ای را درون پایگاه داده ثبت می کنیم:

وب سایت توسینسو

همانطور که مشاهده می کنید پس از فشار دادن دکمه صفحه refresh شده و مشخصات کارمند جدید از جمله تاریخ استخدام (به صورت هجری شمسی) درون GridView نمایان می شود اما اگر نگاهی به پایگاه داده بیندازیم، می بینیم که تاریخ استخدام بدون هیچ مشکلی به شکل صحیح خود یعنی میلادی وارد شده است:

وب سایت توسینسو

به عنوان نتیجه گیری کلی، هنگام طراحی جداول پایگاه داده، ستون های تاریخ را از نوع datetime تعریف می کنیم و به هنگام بازیابی یا وارد کردن داده درون فیلدهایی از این نوع از ابزارهایی که زبان سی شارپ برای تبدیل کردن تاریخ ها در اختیارمان می گذارد استفاده می کنیم.


نظرات