بهترین روش ها جهت ذخیره سازی و نمایش اطلاعاتی از نوع تاریخ و زمان
  در این مقاله به معرفی روش های مختلف جهت ذخیره سازی زمان و تاریخ در پایگاه داده و نمایش اطلاعات و مشکلات مربوطه می پردازم.
   ASP.NET
   ۳۲۳۶۳
   این مقاله حاوی فایل ضمیمه نمی باشد
   مرتضی صحراگرد
   ۱۳۸۹/۱/۲۱
ارسال لینک صفحه برای دوستان ارسال لینک صفحه برای دوستان  اضافه کردن به علاقه مندیها اضافه کردن به علاقه مندیها   نسخه قابل چاپ نسخه قابل چاپ

 

یکی از مشکلات متداولی که برنامه نویسان برنامه های تحت وب و به طور کلی برنامه های توزیع شده (Distributed Applications) با آن روبرو هستند، ذخیره سازی تاریخ و زمان در پایگاه داده می باشد.

ادامه مقاله را با ذکر دو مثال دنبال می کنیم.

اگر شما برای یک منطقه خاص جغرافیایی (Time Zone) برنامه نویسی انجام می دهید، شاید نحوه ذخیره سازی تاریخ و زمان چندان مسئله ساز نباشد و شما براحتی با استفاده از دستور DateTime.Now در فریم ورک DotNet و یا با استفاده از متد GETDATE در پایگاه داده SQL Server مشکل خود را حل نمایید. دلیل این موضوع این است که در یک منطقه جغرافیایی خاص، تاریخ و زمان در تمام نقاط یکسان می باشد. به طور مثال هنگامی که در تهران ساعت 4:30 باشد، در مشهد، اصفهان و تبریز نیز ساعت 4:30 است و در نتیجه تاریخ و زمان ذخیره سازی برای ساعت 4:30 کاملا معتبر می باشد.

ولی در مورد کشور هایی که در مناطق مختلف جغرافیایی قرار دارند، این موضوع متفاوت می باشد زیرا مناطق مختلف جغرافیایی با یکدیگر اختلاف زمانی دارند. مثلا هنگامی که در کشور ایران ساعت 4:30 می باشد، در کشور های کانادا و ایالت های مختلف امریکا، ساعت چندین ساعت جلوتر و یا عقب تر می باشد.

فرض کنید قرار است کنفرانسی در تاریخ 9 آوریل و ساعت 18:30 قرار است در یک از ایالت های امریکا برگزار گردد و شما قصد دارید از تمام افراد واجد شرایط در کشورهای مختلف دنیا برای این کنفرانس دعوت به عمل آورید. ایالت های مختلف امریکا در منطقه های جغرافیایی مختلفی قرار دارند. یعنی مثلا اگر کنفرانس قرار باشد در ساعت 18:30 به وقت تگزاس برگزار گردد، این ساعت ممکن است برابر ساعت 14:30 به وقت ایالت دالاس باشد! پس چگونه باید تاریخ و زمان را اعلام نمود؟

به مثالی دیگر توجه فرمایید.

فرض کنید شما در حال طراحی یک برنامه تالار گفتمان هستید. شخصی در یک منطقه زمانی خاص سوالی را در این تالار مطرح می کند و شما تاریخ مطرح شدن سوال را براحتی ذخیره می کنید. این تاریخ می تواند 9 آوریل 2010 ساعت 16:30 باشد. اکنون شخص دیگری وارد تالار گفتمان می شود که در منطقه جغرافیایی متفاوتی قرار دارد. این شخص ملاحظه می کند که تاریخ ثبت شده برای این سوال، مربوط به چند ساعت بعد می باشد که هنوز فرا نرسیده است! چگونه باید این مشکل را رفع نمود؟

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

برای ذخیره نمودن تاریخ در پایگاه داده SQL Server معمولا از دو روش استفاده می شود. یا تاریخ توسط برنامه برای پایگاه داده ارسال می شود (به طور مثال با استفاده از دستور DateTime.Now) و یا اینکه با استفاده از تابع  GETDATE مربوط به SQL Server و از طریق پایگاه داده این عمل انجام می شود. (در اینجا فرض بر این است که نوع فیلد پایگاه داده از جنس DateTime می باشد و بنده قصد معرفی انواع مختلف فیلد های پایگاه داده SQL Server را که جهت نگهداری انواع تاریخ و زمان استفاده می شود را ندارم)

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

بهترین روش:

اما بهترین روش برای حل مشکلاتی که در بالا ذکر شد، استفاده از زمان استاندارد بین المللی یعنی Coordinated Universal Time یا به عبارت دیگری UTC می باشد. این زمان در تمام مناطق جغرافیایی یکسان می باشد. یعنی اگر زمان UTC در حال حاضر 9 آوریل 2010 و ساعت 16:30 باشد، این ساعت در تمام دنیا یکسان می باشد. در فریم ورک DotNet با استفاده از دستور DateTime.UtcNow و در پایگاه داده SQL Server با استفاده از تابع GETutcDATE می توانید به این تاریخ و زمان دسترسی پیدا نمایید.

در شکل زیر حاصل دو دستور مختلف ذکر شده برای پاگاه داده SQL Server را ملاحظه می نمایید.


دقت کنید که حاصل اجرای دستور GETDATE ساعت 22:58 می باشد در حالیکه حاصل اجرای دستور GETutcDATE ساعت 18:28 می باشد. مبنای تشخیص ساعت تمام مناطق جغرافیایی بر اساس تاریخ و زمان UTC می باشد و ما همواره با اضافه و یا کم نموده میزان مشخصی از زمان UTC می توانیم تاریخ و زمان هر منطقه جغرافیایی را بدست آوریم.(در ادامه مقاله این موضوع را ملاحظه می نمایید)

توجه:

میزان زمانی که با توجه به تاریک و روشن بودن هوا در کشور های مختلف از ساعت رسمی کم و زیاد می شوند (Daylight Saving) در تاریخ و زمان UTC مورد محاسبه قرار نمی گیرد. به طور مثال در کشور ما در ابتدای سال یک ساعت زمان رسمی به جلو کشیده شده و در ابتدای شش ماهه دوم، این زمان مجددا به عقب کشیده می شود.

تاکنون مشکل ذخیره سازی تاریخ و زمان را حل نموده ایم ولی مسئله ای که هم اکنون وجود دارد این است که چگونه این زمان را نمایش دهیم. به عبارت دیگر، کاربران و مخاطبین وب سایت معمولا آگاهی چندانی در مورد تبدیل زمان بین المللی UTC به زمان منطقه جغرافیایی خود ندارند و شما صرفا با نمایش تاریخ UTC کمک چندانی به مخاطبین خود ننموده اید.

در اینجا نحوه های مختلف نمایش زمان را ملاحظه می نمایید.

  1. نمایش تاریخ و زمان دقیقا همانطور که در پایگاه داده ذخیره شده است

  2. نمایش تاریخ و زمان به صورت نسبی و تقریبی

  3. نمایش تاریخ و زمان متناسب با هر منطقه جغرافیایی

اکنون به معرفی هر کدام از این روش ها می پردازیم.

نمایش تاریخ و زمان دقیقا همانطور که در پایگاه داده ذخیره شده است:

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

نمایش تاریخ و زمان به صورت نسبی و تقریبی:

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

  • یک دقیقه پیش

  • سه ساعت پیش

  • دو روز پیش

  • 30 ثانیه پیش

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

در قسمت زیر یک پیاده سازی به زبان #C و به صورت متدهای توسعه گر(Extension Method) برای کلاس DateTime ملاحظه می نمایید.

public static class DateTimeExtensions
{
    #region Methods
 
    public static string ToRelativeDateString(this DateTime date)
    {
        return GetRelativeDateValue(date, DateTime.Now);
    }
 
    public static string ToRelativeDateStringUtc(this DateTime date)
    {
        return GetRelativeDateValue(date, DateTime.UtcNow);
    }
 
    private static string GetRelativeDateValue(DateTime date, DateTime comparedTo)
    {
        TimeSpan diff = comparedTo.Subtract(date);
        if (diff.Days >= 7)
            return string.Concat("on ", date.ToString("MMMM dd, yyyy"));
        else if (diff.Days > 1)
            return string.Concat(diff.Days, " days ago");
        else if (diff.Days == 1)
            return "yesterday";
        else if (diff.Hours >= 2)
            return string.Concat(diff.Hours, " hours ago");
        else if (diff.Minutes >= 60)
            return "more than an hour ago";
        else if (diff.Minutes >= 5)
            return string.Concat(diff.Minutes, " minutes ago");
        if (diff.Minutes >= 1)
            return "a few minutes ago";
        else
            return "less than a minute ago";
    }
 
    #endregion Methods
}

اگر زمان را به شکل معمولی ذخیره نموده باشیم، با استفاده از متد ToRelativeDateString می توانیم زمانی نسبی مورد نظر را بدست آوریم و در صورتی که زمان را به شکل UTC ذخیره نموده باشیم، با فراخوانی تابع ToRelativeDateStringUtc می توانیم زمان نسبی سپری شده را بدست آوریم.

در قسمت زیر نحوه استفاده از متدهای بالا را ملاحظه می نمایید:

DateTime dateTime = GetDatabaseTime();
string relativeTimeString= DateTime.ToRelativeDateString(dateTime);
 
DateTime dateTime = GetDatabaseUtcTime();
string relativeTimeString = DateTime.ToRelativeDateStringUtc(dateTime);

نمایش تاریخ و زمان متناسب با هر منطقه جغرافیایی:

در این روش ما زمان را به صورت UTC در دیتابیس ذخیره می کنیم و سپس منطقه جغرافیایی کاربر را بدست می آوریم. اکنون زمان ذخیره شده به شکل UTC را تبدیل به زمان مورد استفاده کاربر در یک محدوده جغرافیایی خاص  می کنیم.

فرض کنید که یک کاربر از کشور ایران وارد وب سایت می شود و قصد داریم زمانی که در دیتابیس به شکل UTC ذخیره شده است را به زمان منطقه جغرافیایی ایران تبدیل کنیم. برای انجام این کار باید مشابه زیر عمل نماییم.

TimeZoneInfo timeZoneInfo;
DateTime dateTime;
//Set the time zone information to Iran Standard Time
timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Iran Standard Time");
//Get date and time in Iran Standard Time
dateTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, timeZoneInfo);
//Print out the date and time
Label1.Text = dateTime.ToString();

در قطعه کد بالا ما شناسه منطقه جغرافیایی (Time Zone ID) ایران("Iran Standard Time") را به تابع FindSystemTimeZoneById ارسال نموده ایم و این تابع، مشخصات منطقه جغرافیایی ایران را برگردانده است. سپس با استفاده از دستور  TimeZoneInfo.ConvertTime زمان دخیره شده به شکل UTC تبدیل به زمان مورد استفاده در منطقه جغرافیایی ما می شود.

لیست کامل شناسه مناطق مختلف جغرافیایی جهان را در قسمت زیر ملاحظه می نمایید.

 

Time Zone ID

Time Zone Display Name

Morocco Standard Time

(GMT) Casablanca

GMT Standard Time

(GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London

Greenwich Standard Time

(GMT) Monrovia, Reykjavik

W. Europe Standard Time

(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna

Central Europe Standard Time

(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague

Romance Standard Time

(GMT+01:00) Brussels, Copenhagen, Madrid, Paris

Central European Standard Time

(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb

W. Central Africa Standard Time

(GMT+01:00) West Central Africa

Jordan Standard Time

(GMT+02:00) Amman

GTB Standard Time

(GMT+02:00) Athens, Bucharest, Istanbul

Middle East Standard Time

(GMT+02:00) Beirut

Egypt Standard Time

(GMT+02:00) Cairo

South Africa Standard Time

(GMT+02:00) Harare, Pretoria

FLE Standard Time

(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius

Israel Standard Time

(GMT+02:00) Jerusalem

E. Europe Standard Time

(GMT+02:00) Minsk

Namibia Standard Time

(GMT+02:00) Windhoek

Arabic Standard Time

(GMT+03:00) Baghdad

Arab Standard Time

(GMT+03:00) Kuwait, Riyadh

Russian Standard Time

(GMT+03:00) Moscow, St. Petersburg, Volgograd

E. Africa Standard Time

(GMT+03:00) Nairobi

Georgian Standard Time

(GMT+03:00) Tbilisi

Iran Standard Time

(GMT+03:30) Tehran

Arabian Standard Time

(GMT+04:00) Abu Dhabi, Muscat

Azerbaijan Standard Time

(GMT+04:00) Baku

Mauritius Standard Time

(GMT+04:00) Port Louis

Caucasus Standard Time

(GMT+04:00) Yerevan

Afghanistan Standard Time

(GMT+04:30) Kabul

Ekaterinburg Standard Time

(GMT+05:00) Ekaterinburg

Pakistan Standard Time

(GMT+05:00) Islamabad, Karachi

West Asia Standard Time

(GMT+05:00) Tashkent

India Standard Time

(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi

Sri Lanka Standard Time

(GMT+05:30) Sri Jayawardenepura

Nepal Standard Time

(GMT+05:45) Kathmandu

N. Central Asia Standard Time

(GMT+06:00) Almaty, Novosibirsk

Central Asia Standard Time

(GMT+06:00) Astana, Dhaka

Myanmar Standard Time

(GMT+06:30) Yangon (Rangoon)

SE Asia Standard Time

(GMT+07:00) Bangkok, Hanoi, Jakarta

North Asia Standard Time

(GMT+07:00) Krasnoyarsk

China Standard Time

(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi

North Asia East Standard Time

(GMT+08:00) Irkutsk, Ulaan Bataar

Singapore Standard Time

(GMT+08:00) Kuala Lumpur, Singapore

W. Australia Standard Time

(GMT+08:00) Perth

Taipei Standard Time

(GMT+08:00) Taipei

Tokyo Standard Time

(GMT+09:00) Osaka, Sapporo, Tokyo

Korea Standard Time

(GMT+09:00) Seoul

Yakutsk Standard Time

(GMT+09:00) Yakutsk

Cen. Australia Standard Time

(GMT+09:30) Adelaide

AUS Central Standard Time

(GMT+09:30) Darwin

E. Australia Standard Time

(GMT+10:00) Brisbane

AUS Eastern Standard Time

(GMT+10:00) Canberra, Melbourne, Sydney

West Pacific Standard Time

(GMT+10:00) Guam, Port Moresby

Tasmania Standard Time

(GMT+10:00) Hobart

Vladivostok Standard Time

(GMT+10:00) Vladivostok

Central Pacific Standard Time

(GMT+11:00) Magadan, Solomon Is., New Caledonia

New Zealand Standard Time

(GMT+12:00) Auckland, Wellington

Fiji Standard Time

(GMT+12:00) Fiji, Kamchatka, Marshall Is.

Tonga Standard Time

(GMT+13:00) Nuku'alofa

Azores Standard Time

(GMT-01:00) Azores

Cape Verde Standard Time

(GMT-01:00) Cape Verde Is.

Mid-Atlantic Standard Time

(GMT-02:00) Mid-Atlantic

E. South America Standard Time

(GMT-03:00) Brasilia

Argentina Standard Time

(GMT-03:00) Buenos Aires

SA Eastern Standard Time

(GMT-03:00) Georgetown

Greenland Standard Time

(GMT-03:00) Greenland

Montevideo Standard Time

(GMT-03:00) Montevideo

Newfoundland Standard Time

(GMT-03:30) Newfoundland

Atlantic Standard Time

(GMT-04:00) Atlantic Time (Canada)

SA Western Standard Time

(GMT-04:00) La Paz

Central Brazilian Standard Time

(GMT-04:00) Manaus

Pacific SA Standard Time

(GMT-04:00) Santiago

Venezuela Standard Time

(GMT-04:30) Caracas

SA Pacific Standard Time

(GMT-05:00) Bogota, Lima, Quito, Rio Branco

Eastern Standard Time

(GMT-05:00) Eastern Time (US & Canada)

US Eastern Standard Time

(GMT-05:00) Indiana (East)

Central America Standard Time

(GMT-06:00) Central America

Central Standard Time

(GMT-06:00) Central Time (US & Canada)

Central Standard Time (Mexico)

(GMT-06:00) Guadalajara, Mexico City, Monterrey

Canada Central Standard Time

(GMT-06:00) Saskatchewan

US Mountain Standard Time

(GMT-07:00) Arizona

Mountain Standard Time (Mexico)

(GMT-07:00) Chihuahua, La Paz, Mazatlan

Mountain Standard Time

(GMT-07:00) Mountain Time (US & Canada)

Pacific Standard Time

(GMT-08:00) Pacific Time (US & Canada)

Pacific Standard Time (Mexico)

(GMT-08:00) Tijuana, Baja California

Alaskan Standard Time

(GMT-09:00) Alaska

Hawaiian Standard Time

(GMT-10:00) Hawaii

Samoa Standard Time

(GMT-11:00) Midway Island, Samoa

Dateline Standard Time

(GMT-12:00) International Date Line West

در صورتی که شما قصد دارید از این روش جهت نمایش تاریخ استفاده نمایید، بهتر است از کاربران هنگام ثبت نام در سایت، نام منطقه جغرافیایی مورد نظر آن ها را سوال نموده و ذخیره نمایید (حتما تاکنون هنگام ثبت نام در تالار های گفتمان با گزینه انتخاب Time Zone مواجه شده اید)

در غیر اینصورت باید با توجه به IP کاربر منطقه جغرافیایی را محاصبه نموده و سایر موارد را اعمال نمایید.

نمایش تاریخ با فرمت مناسب:

یکی دیگر از مشکلاتی که هنگام نمایش تاریخ با آن روبرو هستیم، فرمت نمایش تاریخ می باشد.

به نحوه نمایش تاریخ در چند فرهنگ زیر توجه نمایید:

// Iran              --> YYYY/MM/DD -- روز/ماه/سال
 
// USA               --> MM/DD/YYYY -- سال/روز/ماه
 
// United Kingdom    --> DD/MM/YYYY -- سال/ماه/روز

همانطور که ملاحظه می نمایید، تاریخ 5/7/2010 در کشور انگلستان و امریکا کاملا معنی متفاوتی می دهد. در انگلستان این تاریخ برابر پنجم ماه جولای سال 2010 می باشد در حالیکه در امریکا این تاریخ هفتم ماه MAY سال 2010 معنا می دهد!

برای نمایش تاریخ های میلادی پیشنهاد می شود از فرمت های زیر بنابر نیاز خود استفاده نمایید.

string result = DateTime.Now.ToString("d MMM yyyy h:mm tt"); //  result is --> 10 Apr 2010 12:26 AM
 
//OR
 
string result = DateTime.Now.ToString("MMMM d, yyyy h:mm tt"); //  result is --> April 10, 2010 12:29 AM


منابع:     30sharp.com

           4GuysFromRolla

            xiirus