سؤال

أنا أعمل على مشروع "نظام تذكير عبر الإنترنت" (ASP.NET 2.0 (C#) / SQL Server 2005)

نظرًا لأن هذه خدمة تذكير سترسل البريد إلى المستخدمين في تواريخ معينة. لكن المشكلة هي أن المستخدمين ليسوا من بلدان معينة ، فهم من جميع أنحاء العالم ومن مناطق زمنية مختلفة. الآن عندما أسجل ، أطلب المنطقة الزمنية للمستخدمين بالطريقة نفسها التي يسأل بها Windows منطقتنا الزمنية في وقت التثبيت.

لكنني لا أحصل على محدد المستخدم (+5.30) أو أي شيء من المنطقة الزمنية ، ثم كيفية التعامل مع هذه المنطقة الزمنية في تطبيق ASP.NET الخاص بي. كيفية العمل وفقا ل timezone.

ويرجى اقتراح ما إذا كانت هناك طريقة أفضل للتعامل مع المناطق الزمنية في هذا التطبيق ؟؟

شكرًا

هل كانت مفيدة؟

المحلول

أول شيء هو التأكد من أن بياناتك الزمنية موجودة. أوصي بالتأكد من أن أي وقت تخزنه ، يتم تخزينه في وقت UTC (استخدم DateTime.ToUniversalTime() للحصول على ذلك).

عندما تقوم بتخزين تذكير للمستخدم ، ستحتاج إلى وقت UTC الحالي ، إضافة أو إزالة اختلاف المنطقة الزمنية للمستخدم ، وتحويل هذا الوقت الجديد إلى UTC ؛ هذا ما تريد تخزينه في DB.

بعد ذلك ، عندما تريد التحقق من الإرسال ، تحتاج ببساطة إلى البحث في قاعدة البيانات لتذكيرات لإرسالها الآن ، وفقًا لـ UTC Time ؛ احصل بشكل أساسي على جميع التذكيرات التي لديها طابع زمني موجود من قبل DateTime.Now.ToUniversalTime().

تحديث مع بعض تفاصيل التنفيذ: يمكنك الحصول على قائمة بالمناطق الزمنية من TimeZoneInfo.GetSystemTimeZones() طريقة؛ يمكنك استخدام تلك لإظهار قائمة من المناطق الزمنية للمستخدم. إذا قمت بتخزين Id خاصية من المنطقة الزمنية المحددة ، يمكنك إنشاء مثيل فئة TimezoneInfo منه ، وحساب وقت UTC لقيمة تاريخ/زمنية محلية معينة:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("<the time zone id>");
// May 7, 08:04:00
DateTime userDateTime = new DateTime(2009, 5, 7, 8, 4, 0);
DateTime utcDateTime = userDateTime.Subtract(tzi.BaseUtcOffset);

نصائح أخرى

أود أن أوصي دائما استخدم وقت UTC (GMT) على جانب الخادم (في الكود-بيهيند ، قاعدة البيانات ، إلخ) ، وتحويل الوقت من UTC إلى الوقت المحلي لأغراض العرض فقط. هذا يعني أنه يجب إجراء جميع التلاعب في الوقت - بما في ذلك توفير الوقت في قاعدة البيانات ، وإجراء الحسابات ، وما إلى ذلك - باستخدام UTC.

المشكلة هي: كيف تعرف الكود-ما هي المنطقة الزمنية لمتصفح العميل؟ قل أن المستخدم يدخل بعض القيمة/الوقت (مثل 12/30/2009 14:30) في النموذج وتقديمه إلى الخادم. على افتراض أن المستخدم قدم بالتوقيت المحلي ، كيف يعرف الخادم كيفية تحويل هذه القيمة إلى UTC؟

يمكن للتطبيق أن يطلب من المستخدم تحديد المنطقة الزمنية (وحفظه في ملف تعريف ارتباط أو قاعدة بيانات مستمرة) ، لكنه يتطلب وجهد إضافي من المستخدم ، وسيحتاج تطبيقك إلى تنفيذ المنطق والشاشات لهذا الغرض. سيكون من أجمل إذا استطاع التطبيق تحديد المنطقة الزمنية للعميل تلقائيًا.

لقد تناولت هذه المشكلة بمساعدة JavaScript getTimeZoneOffset الوظيفة ، وهي واجهة برمجة التطبيقات الوحيدة التي يمكنها إخبار الخادم عن الفرق الزمني بين التوقيت المحلي على العميل و GMT. نظرًا لأن هذه واجهة برمجة تطبيقات من جانب العميل ، فقد فعلت ما يلي: على جانب الخادم ، تحقق من ملف تعريف ارتباط مخصص للجلسة يحتفظ بقيمة إزاحة الوقت ، وإذا لم يكن متاحًا ، فأعد إعادة تحميل الصفحة (فقط أثناء الحصول على المكالمات ، وليس النشر) مع إضافة بعض منطق JavaScript لإنشاء إزاحة الوقت وحفظه في ملف تعريف الارتباط. من جانب العميل ، يكون هذا شفافًا تقريبًا (مرة واحدة خلال الجلسة ، أقوم بإعادة تحميل صفحة على GET). بمجرد أن أحصل على الإزاحة في ملف تعريف الارتباط ، أقوم بتطبيقه على وظائف إدارة الوقت اعتمادًا على اتجاه تحويل الوقت (UTC إلى التوقيت المحلي ، أو بالتوقيت المحلي إلى UTC).

قد يبدو هذا الأمر معقدًا بعض الشيء ، ولكن بعد أن كتبت وظائف المساعد ، كان دمج هذه الميزة في الموقع مسألة صنع أ مكالمة واحدة في page_load (من الصفحات التي تحتاج إلى تحويل الوقت) ، واستخدام إجراءات تحويل الوقت عند إرسال واستعادة قيم الوقت من وإلى المتصفح. فيما يلي مثال على كيفية استخدامه:

using My.Utilities.Web;
...

// Derive the form class from BaseForm instead of Page.
public class WebForm1: BaseForm
{
...
private void Page_Load(object sender, System.EventArgs e)
{
  // If we only want to load the page to generate the time
  // zone offset cookie, we do not need to do anything else.
  if (InitializeLocalTime())
    return;

  // Assume that txtStartDate is a TextBox control.
  if (!IsPostback)
  {
     // To display a date-time value, convert it from GMT (UTC)
     // to local time.
     DateTime startDate = GetStartDateFromDB(...);
     txtStartDate.Text  = FormatLocalDate(startDate);
     ...
  }
  else
  {
     // To save a date-time value, convert it from local
     // time to GMT (UTC).
     DateTime tempDate  = DateTime.Parse(txtStartDate.Text);
     DateTime startDate = ConvertLocalTimeToUtc(tempDate);
     SaveStartDateInDB(startDate, ...);
     ...
  }
}
...
}

إذا كنت بحاجة إلى مزيد من التفاصيل ، تحقق من لقد حان الوقت: توطين الوقت في تطبيقات ASP.NET مقال (آسف ، لكن ليس لدي رابط مباشر إلى المقالة على موقع الناشر ، لأن ASP.NETPRO يقيد الوصول إلى المشتركين المدفوعين فقط ؛ هناك روابط لنسخ PDF ، على الرغم من). أتمنى أن أتمكن من نشر العينة من المقالة ، لكنني لا أريد انتهاك حقوق الطبع والنشر ؛ ومع ذلك ، ها هو أ مشروع لبناء مكتبة مساعد التي لديها جميع الوظائف والوثائق اللازمة (فقط تجاهل الأشياء التي لا تحتاجها).

تحديث: تم نشر المقالة عبر الإنترنت مع عينة مشروع من قبل الناشر الجديد هنا.

المشكلة في جميع الإجابات حتى الآن هي أنها لا تأخذ في الاعتبار ما يحاول Prashant تحقيقه. إذا كان مستخدم نظامه في اليوم السابق لتغييرات التوفير في وضح النهار ، فإن إزاحة +12 ويحدد تذكيرًا لليوم التالي ، فسيكون إزاحةه عندما يتم تشغيل التذكير هو +13 بدلاً من ذلك.

لهذا السبب يمكنك فقط استخدام الإزاحة الحالية لشيء يحدث الآن. على الرغم من أنني أتفق مع أي شخص آخر على أنه يجب تخزين جميع الأوقات من جانب الخادم (باستثناء من المحتمل أن يتم استخدامها للعرض) في UTC.

قد ترغب في النظر في استخدام DateTimeOffset بنية بدلا من وقت البيانات إذا كنت على إطار 2.0 أو أحدث.

تمثل DateTimeOffset نقطة زمنية بالنسبة إلى وقت UTC ، لذلك يجب أن يكون من الأسهل العمل معها في هذه الحالة.

هناك خطوتين:

  • اكتشف منطقة زمنية مختلفة في جانب العميل باستخدام JavaScript:

    var dt = new Date();
    var diffInMinutes = -dt.getTimezoneOffset();
    
  • ثم على جانب الخادم ، رمز C# لتحويل وقت الخادم إلى وقت العميل بناءً على إزاحة المنطقة الزمنية المكتشفة أعلاه:

------------------------;

string queryStr = Request.QueryString["diffInMinutes"];
int diffInMinutes = 0;
if (Int32.TryParse(queryStr, out diffInMinutes))
{
    clientTime = serverTime.ToUniversalTime().AddMinutes(diffInMinutes);
}

في الأساس ، كل ما عليك فعله هو إضافة الإزاحة (ساعات + دقائق) إلى التوقيت المحلي الذي دخله المستخدم. يمنحك إضافة الإزاحة أساسًا وقتًا في المنطقة الزمنية (GMT) بشكل أساسي.

عادة ما يكون من الأسهل توحيد جميع الأوقات الخاصة بك إلى UTC ، بحيث لا يتعين على منطق التطبيق الخاص بك التعامل مع الإزاحة.

تحتوي هذه الصفحة على بعض الأمثلة الجيدة: http://msdn.microsoft.com/en-us/library/bb546099.aspx

تكمن المشكلة في أن الإزاحة من UTC ستختلف في أوقات مختلفة من السنة - في كل منطقة زمنية لها قواعدها الخاصة. (لقد تعلمت هذا بالطريقة الصعبة عند تطوير تطبيق جدولة غرفة الاجتماعات.)

يبدو أن هناك دعمًا مدمجًا هنا: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttime.aspx

لم أجربها بنفسي ، لكن يبدو أنه يعد بالتحويل الصحيح ، وهو ما يمثل مدخرات في ضوء النهار.

إذا لم يكن الأمر كذلك ، فإليك أداة تجارية (باهظة الثمن) التي استخدمتها: http://www.worldtimeserver.com/time_zone_guide/

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top