محاسبه اختلاف دو تاریخ

در این بخش به شما نحوه ایجاد یک ماشین حساب که اختلاف بین دو تاریخ را محاسبه می کند آموزش داده می شود. برنامه از متدهای System.DateTime و System.TimeSpan استفاده می کند این آموزش همچنین مهارت شما را در استفاده از رویدادها و کنترل ComboBox افزایش می دهد. یک برنامه ویندوزی ایجاد کنیدو نام آن را TimeDifferenceCalculator بگذارید. سپس مانند شکل زیر کنترلهای لازم را بر روی آن قرار دهید و مرتب کنید.
time-difference-calculator-02-02-11-01
به صورت اختیاری می توانید خاصیت Text فرم را تغییر داده و همچنین خاصیت FormBorderStyle را به FixedSingle تغییر دهید تا اندازه فرم ثابت بماند. خاصیت Name کنترل های شماره گذاری شده را مطابق جدول زیر تغییر دهید.
time-difference-calculator-02-02-11-02

شماره نام
1 comboBeginDateMonth
2 comboBeginDateDay
3 comboBeginDateYear
4 comboEndDateMonth
5 comboEndDateDay
6 comboEndDateYear
7 labelResult
8 buttonCalculate

خاصیت Text کنترل labelResult را پاک کنید تا نتیجه محاسبه در آن قرار بگیرد. بر روی فرم (نه کنترل ها) دو بار کلیک کنید تا یک کنترل کننده رویداد برای خاصیت Load فرم ایجاد شود. سپس کد زیر را به آن اضافه کنید.

private void Form1_Load(object sender, EventArgs e)
{
    //تعریف ماه ها
    string[] months = 
    {
        "January", "February", "March", "April",
        "May", "June", "July", "August",
        "September", "October", "November", "December"
    };

    //پر کردن کمبوباکس ها با ماه ها
    for (int i = 0; i < 12; i++)
    {
        comboBeginDateMonth.Items.Add(months[i]);
        comboEndDateMonth.Items.Add(months[i]);
    }

    //قرار دادن ماه ژانویه به عنوان ماه پیشفرض
    comboBeginDateMonth.SelectedIndex = 0;
    comboEndDateMonth.SelectedIndex = 0;

    //پر کردن کمبوباکس ها با سال
    for (int i = 1; i <= DateTime.Now.Year; i++)
    {
        comboBeginDateYear.Items.Add(String.Format("{0:0000}", i));
        comboEndDateYear.Items.Add(String.Format("{0:0000}", i));
    }

    //پیشفرض قرار دادن سال 2000
    comboBeginDateYear.SelectedIndex = 1999;
    comboEndDateYear.SelectedIndex = 1999;

    //پر کردن کمبوباکس ها با روز
    FillDays(comboBeginDateDay, "Begin");
    FillDays(comboEndDateDay, "End");

    //اضافه کردن کنترل کننده رویداد
    comboBeginDateMonth.SelectedIndexChanged += new EventHandler(RecalculateDays);
    comboBeginDateYear.SelectedIndexChanged += new EventHandler(RecalculateDays);
    comboEndDateMonth.SelectedIndexChanged += new EventHandler(RecalculateDays);
    comboEndDateYear.SelectedIndexChanged += new EventHandler(RecalculateDays);
}

اولین چیزی که ما ایجاد می کنیم آرایه ای رشته ای است که 12 ماه سال را در خود جای می دهد. سپس با استفاده از حلقه for ماه ها را به دو کمبوباکس (combo boxes) برای نشان دادن آنها (ماه ها) اضافه می کنیم. به وسیله متد Add خاصیت Item کلاس ComboBox این کار را انجام می دهیم. سپس خاصیت SelectedIndex دو کمبوباکس را به عدد صفر تغییر می دهیم که نشان دهنده اولین آیتم یعنی ماه ژانویه است.
نکته مهم این است که چون اندیس ها در کمبو باکسها از صفر شروع می شود در نتیجه شمارش نیز از صفر آغاز می شود. سپس کمبو باکسهایی که قرار است سال ها را نمایش دهند را از عدد 1 تا سال جاری پر می کنیم. برای دسترسی به سال جاری از خاصیت Year خاصیت Now کلاس DateTime استفاده می کنیم. خاصیت Now نشان دهنده ساعت و تاریخ جاری است.
همه سال ها را برای نمایش به کمبوباکس ها اضافه می کنیم. برای قالب بندی سال ها از 4 صفر استفاده می کنیم بنابراین همه سال ها 4 رقمی نشان داده می شوند. با اختصاص مقدار 1999 به خاصیت SelectedIndex دو کمبوباکس مسئول نمایش سال، سال 2000 را سال مبنا قرار می دهیم. به خاطر داشته باشید که SelectedIndex از صفر شروع می شود در نتیجه برای نمایش سال 2000 باید اندیس آن 1999 باشد.
به این نکته توجه کنید که می توانیم به قسمت طراحی فرم رفته و بر روی کمبوباکس مورد نظر کلیک کنیم سپس با استفاده خاصیت Items پیدا کنیم. با کلیک بر رو دکمه مقابل این خاصیت که دارای سه نقطه است صفحه ای باز می شود که بوسیله آن می توانیم هر آیتمی به کمبوباکس اضافه کنیم. اما این کار قطعا برای شما خسته کننده است چون قرار است که 2000 یا تعداد بیشتری مقدار را به آن اضافه کنیم. برای راحتی کار می توانیم از طریق کدنویسی این کار را انجام دهیم.
متد FillDays که قبلا ایجاد کرده ایم کمبوباکس ها را برای نمایش روز پر می کند ولی تعداد روزها در کمبو باکس ها برابر است مثلا کمبوباکس های مسئول نشان دادن روزها همگی دارای 30 روز می باشند، در اینجا به مشکل بر می خوریم چون بعضی از ماه ها 31 روزه هستند و سال کبیسه هم وجود دارد. در 4 خط آخر کد یک کنترل کننده رویداد به رویداد SelectedIndexChanged هر کمبوباکس اضافه کرده ایم. این رویداد زمانی آزاد می شود که یک اندیس انتخاب شود و یا یک آیتم تغییر کند. یک کنترل کننده رویداد ایجاد کرده ایم که بین 4 کنترل تقسیم می شود.
لازم است که این کنترل کننده رویداد را به کمبوباکس هایی که مسئول نگداری ماه ها و سال ها هستند اضافه کنیم، بنابر این زمانی که کاربر یک سال یا ماه را تغییر می دهد، آیتم های داخل کمبو باکس های مسئول نگهداری روز به طور خودکار به روز (آپدیت) می شوند. کنترل کننده های رویداد را در آخر کدها قرار می دهیم، چون ما خاصیت SelectedIndex کمبوباکس ها را تغییر می دهیم که این کار باعث آزاد شدن رویداد و اجرای کنترل کننده های رویدادی می شود که باعث خالی شدن کمبوباکس ها می شوند. این کار باعث به وجود آمدن یک خطا می شود. اجازه دهید که یک متد FillDays ایجاد کنیم. این متد باعث پر شدن روزهای یک کمبوباکس مشخص می شود. این متد یک کمبوباکس را به عنوان پارامتر آرگومان قبول می کند و دومین پارامتر آن یک رشته ای است که نشان می دهد کدام یک از کمبوباکس های comboBeginDateDay یا comboEndDataDay به روز شده اند.

private void FillDays(ComboBox comboBox, string tag)
{
    int selectedMonth;
    int selectedYear;

    if (tag == "Begin")
    {
        selectedMonth = comboBeginDateMonth.SelectedIndex + 1;
        selectedYear = comboBeginDateYear.SelectedIndex + 1;
    }
    else
    {
        selectedMonth = comboEndDateMonth.SelectedIndex + 1;
        selectedYear = comboEndDateYear.SelectedIndex + 1;
    }

    int maxDay = DateTime.DaysInMonth(selectedYear, selectedMonth);

    comboBox.Items.Clear();

    for (int i = 1; i <= maxDay; i++)
    {
        comboBox.Items.Add(i);
    }

    comboBox.SelectedIndex = 0;
}

ابتدا با استفاده از پارامتر tag مشخص می کنیم کدام یک از کمبوباکس های month و year مقادیر را دریافت می کنند. سپس خاصیت SelectedIndex آنها را با عدد 1 جمع کرده و برابر متغیرهایی قرار می دهیم که به وسیله متد DaysInMonth مورد استفاده قرار می گیرند. سپس از متد استاتیک DaysInMonth کلاس DateTime برای چک کردن روزهای ماه های سال های خاص (کبیسه) استفاده می کنیم. برای آپدیت کردن کمبوباکس ابتدا آیتم ها را حذف می کنیم. تعداد روزها را با خواندن روزها با استفاده از یک حلقه for بروز می کنیم.سر انجام مقدار خاصیت SelectedIndex ازکامبو باکس را برابر 0 قرار می دهیم تا مقدار پیشفرض آن برابر 1 شود. سازنده Form1 را پیدا کرده و کد پر رنگ شده زیر را به آن اضافه کنید.

public Form1()
{
    InitializeComponent();

    comboBeginDateMonth.Tag = "Begin";
    comboBeginDateYear.Tag = "Begin";
    comboEndDateMonth.Tag = "End";
    comboEndDateYear.Tag = "End";
}

سپس آن مقادیر را به خصوصیت Tag نسبت می دهیم تا کامبوباکس درست را برای بروزرسانی به متد RecalculateDays ارسال کنیم.

private void RecalculateDays(object sender, EventArgs e)
{
    if ((sender as ComboBox).Tag.ToString() == "Begin")
        FillDays(comboBeginDateDay, "Begin");
    else
        FillDays(comboEndDateDay, "End");
}

به این نکته توجه نمایید که این متد به عنوان کنترل کننده رویداد برای رویداد SelectedIndexChanged انتخاب شده است ، نماینده این رویداد متدی را می پذیرد که 2 پارامتر از نوع object و EventArgs داشته باشد. متد شامل یک دستور if است که کنترل فعال کننده متد را به نوع کامبو باکس تبدیل می کند تا از خصوصیت Tag آن استفاده کند. ما نتیجه را با رشته “Begin” مقایسه می کنیم بنابراین برنامه تشخیص می دهد که کمبوباکس به روز شده است. به قسمت طراحی برمی گردیم و بر روی buttonCalculate دو بار کلیک می کنیم تا یک کنترل کننده رویداد برای رویداد کلیک ایجاد شود. کد زیر را اضافه می کنیم.

private void buttonCalculate_Click(object sender, EventArgs e)
{
    DateTime beginDate = new DateTime(
        comboBeginDateYear.SelectedIndex + 1,
        comboBeginDateMonth.SelectedIndex + 1,
        comboBeginDateDay.SelectedIndex + 1);

    DateTime endDate = new DateTime(
        comboEndDateYear.SelectedIndex + 1,
        comboEndDateMonth.SelectedIndex + 1,
        comboEndDateDay.SelectedIndex + 1);

    TimeSpan difference = endDate.Subtract(beginDate);

    labelResult.Text = String.Format("{0} Days", difference.Days);
}

بر روی دکمه کلیک کرده تاریخ های شروع و پایان به درستی در کامبوباکس ها نمایش داده می شوند. سپس تفاوت را با استفاده از متد Subtract محاسبه می کنیم. این متد یک شی از TimeSpan را برگشت می دهد. در آخر هم تفاوت دو تاریخ را در کنترل labelResult نمایش می دهیم. برنامه قابلیت بهبود بیشتری را هم دارا می باشد. به عنوان مثال شما می توانید تعداد بیشتری کمبو باکس جهت یافتن اختلاف ساعت، دقیقه و ثانیه به برنامه اضافه کنید. همچنین می توانید تفاوت بین ماهها و سال ها را نیز محاسبه کنید. از متد IsLeapYear هم می توان برای تشخیص سال های کبیسه استفاده نمود.

لطفا اگر نظر، پیشنهاد و یا انتقادی در باره مطلب بالا دارید در قسمت زیر و اگر سوالی دارید در بخش پرسش و پاسخ مطرح بفرمایید.

  1. محمدرضا پاسخ دادن

    سلام
    دوست عزیز واقعا سایتت خیلی خیلی عالیه…حتما به دوستام معرفی می کنم…البته از قبل کتابتون با عنوان “سی شارپ به زبان ساده” رو خوندم …گویا از چاپش منصرف شدین…میشه PDF ش رو بذارین واسه فروش…من یکی که می خرم.

  2. یونس ابراهیمی پاسخ دادن

    سلام دوست عزیز…ممنون از اینکه نظر دادین..
    آره فعلا با این گرونی،چاپش به صرفه نیست…

    اتفاقا دارم PDF ش رو تکمیل می کنم…حتما میذارم برا فروش… ۱۰-۱۲ روز دیگه آماده میشه

    مطالبش هم
    ۱- تمامی مطالب وب سایت (البته کامل شدشون…چون مباحثی هستن که هنوز نذاشتم)
    ۲- یک پروِِِژه کامل از صفر تا صد…. به صورت تصویری که مباحثی مانند :
    معماری سه لایه
    گزارش گیری و کار با کریستال ریپورت
    پرینت
    کار با بانک (ADO و LINQ)
    و….
    درش گونجوندم… اگه استقبال بشه حتما مطالب سایت رو بیشتر می کنم
    مثلا قصد دارم thread و GDI و WPF رو هم بذارم

    (( از دوستان هم اگه کمک کنن و هرکس در حد بضاعت ، حتی اگه شده یک کد رو هم ارسال کنه تا در قسمت کدهای مفید واسه دوستان بذارم ممنون میشم))))

  3. محمد حسین غفاری پاسخ دادن

    اقا از این سایت اموزشی بهتر هیچ جا سراغ ندارم.به کل کلاسمون این سایتو معرفی میکنم.مرسیییییییییییییییییییییییییییییییییییییی

  4. محمد حسین غفاری پاسخ دادن

    راستی!!!!!میشه بپرسم شما کجا درس میدید.با کله میام

  5. یونس ابراهیمی پاسخ دادن

    ممنون از لطفت دوست عزیز…
    لطف بزرگیه که سایت رو به دوستاتون معرفی بفرمایید.
    والا درس می خونم!!!!!!!!!!!!!!

  6. Emad پاسخ دادن

    Thanks sir,I really appreciate it

  7. t.tvs پاسخ دادن

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

  8. قاسم پاسخ دادن

    سلام و تشکر بابت آموزش های سایت :)
    آقا یونس چطور میتونه هفته جاری سیستم رو بدست بیارم (واسه گزارش فروش هفتگی میخوام)