التاريخ والوقت.الآن مقابل.DateTime.UtcNow
-
09-06-2019 - |
سؤال
لقد كنت أتساءل ما هي بالضبط مبادئ كيفية عمل الخاصيتين.أعلم أن الخيار الثاني عالمي ولا يتعامل بشكل أساسي مع المناطق الزمنية، ولكن هل يمكن لأي شخص أن يشرح بالتفصيل كيفية عملها وأي منها يجب استخدامه في أي سيناريو؟
المحلول
DateTime.UtcNow يخبرك بالتاريخ والوقت كما هو الحال في التوقيت العالمي المنسق، والذي يُطلق عليه أيضًا المنطقة الزمنية لتوقيت غرينتش - تمامًا كما لو كنت في لندن بإنجلترا، ولكن ليس خلال فصل الصيف. التاريخ والوقت.الآن يعطي التاريخ والوقت كما يبدو لشخص ما في لغتك الحالية.
أنصح باستخدام DateTime.Now
عندما تعرض تاريخًا على أحد الأشخاص - وبهذه الطريقة يشعر بالارتياح تجاه القيمة التي يراها - فهو شيء يمكنهم مقارنته بسهولة بما يرونه على ساعتهم أو ساعتهم.يستخدم DateTime.UtcNow
عندما تريد تخزين التواريخ أو استخدامها لإجراء حسابات لاحقة بهذه الطريقة (في نموذج خادم العميل)، لا يتم الخلط بين حساباتك من قبل العملاء في مناطق زمنية مختلفة من الخادم الخاص بك أو من بعضهم البعض.
نصائح أخرى
الأمر بسيط جدًا حقًا، لذلك أعتقد أن الأمر يعتمد على نوع جمهورك والمكان الذي يعيشون فيه.
إذا كنت لا تستخدم UTC، فإنك يجب تعرف على المنطقة الزمنية للشخص الذي تعرض التواريخ والأوقات له - وإلا ستخبره بشيء ما حدث في الساعة 3 مساءً بتوقيت النظام أو الخادم، في حين أنه حدث بالفعل في الساعة 5 مساءً في المكان الذي يعيش فيه.
نحن نستخدم DateTime.UtcNow
نظرًا لأن لدينا جمهورًا عالميًا على الويب، ولأنني أفضل عدم إزعاج كل مستخدم لملء نموذج يشير إلى المنطقة الزمنية التي يعيش فيها.
نعرض أيضًا الأوقات النسبية (منذ ساعتين، قبل يوم واحد، وما إلى ذلك) حتى يصبح المنشور قديمًا بدرجة كافية بحيث يصبح الوقت "نفسه" بغض النظر عن المكان الذي تعيش فيه على الأرض.
لاحظ أيضًا فرق الأداء؛يعد DateTime.UtcNow أسرع بنحو 30 مرة من DateTime.Now، لأن DateTime.Now داخليًا يقوم بالكثير من تعديلات المنطقة الزمنية (يمكنك التحقق من ذلك بسهولة باستخدام Reflector).
لذلك لا تستخدم DateTime.Now لقياسات الوقت النسبية.
أحد المفاهيم الرئيسية التي يجب فهمها في .NET هو ذلك الآن يكون الآن في جميع أنحاء الأرض بغض النظر عن المنطقة الزمنية التي تتواجد فيها.لذلك إذا قمت بتحميل متغير مع DateTime.Now
أو DateTime.UtcNow
- المهمة متطابقة.* الخاص بك DateTime
يعرف الكائن المنطقة الزمنية التي تتواجد فيها ويأخذ ذلك في الاعتبار بغض النظر عن المهمة.
فائدة DateTime.UtcNow
يكون مفيدًا عند حساب التواريخ عبر حدود التوقيت الصيفي.أي أنه في الأماكن التي تشارك في التوقيت الصيفي، أحيانًا يكون هناك 25 ساعة من الظهر إلى الظهر في اليوم التالي، وأحيانًا يكون هناك 23 ساعة بين الظهر والظهيرة في اليوم التالي.إذا كنت تريد تحديد عدد الساعات من الوقت A والوقت B بشكل صحيح، فأنت بحاجة أولاً إلى ترجمة كل منهما إلى مكافئاتها بالتوقيت العالمي المنسق (UTC) قبل حساب TimeSpan
.
ويغطي هذا أ بلوق وظيفة كتبت وهذا يوضح كذلك TimeSpan
, ، ويتضمن رابطًا لمقالة MS أكثر شمولاً حول هذا الموضوع.
*إيضاح:سيتم تخزين أي مهمة الوقت الحالي.إذا كنت تريد تحميل متغيرين أحدهما عبر DateTime.Now()
والآخر عبر DateTime.UtcNow()
ال TimeSpan
سيكون الفرق بين الاثنين ميلي ثانية، وليس ساعات على افتراض أنك في منطقة زمنية تبعد ساعات عن توقيت جرينتش.كما هو مذكور أدناه، طباعة String
ستعرض القيم سلاسل مختلفة.
هذا سؤال وجيه.أقوم بإحيائه لتقديم المزيد من التفاصيل حول كيفية تعامل .Net مع مختلف Kind
قيم.كما يشير @Jan Zich، إنها في الواقع خاصية بالغة الأهمية ويتم تعيينها بشكل مختلف اعتمادًا على ما إذا كنت تستخدمها أم لا Now
أو UtcNow
.
داخليًا يتم تخزين التاريخ كـ Ticks
والذي (خلافًا لإجابة @Carl Camera) يختلف اعتمادًا على ما إذا كنت تستخدمه Now
أو UtcNow
.
DateTime.UtcNow
يتصرف مثل اللغات الأخرى.إنه يحدد Ticks
إلى قيمة تعتمد على توقيت جرينتش.كما أنه يحدد Kind
ل Utc
.
DateTime.Now
يغير Ticks
قيمة ل ماذا سيكون الأمر لو كان وقتك من اليوم بتوقيت جرينتش.كما أنه يحدد Kind
ل Local
.
إذا كنت متأخرًا بـ 6 ساعات (GMT-6)، فستحصل على توقيت GMT منذ 6 ساعات..Net يتجاهل فعلا Kind
ويتعامل مع هذه المرة كما لو كانت قبل 6 ساعات، رغم أنه من المفترض أن يكون "الآن".وهذا يكسر أكثر إذا قمت بإنشاء ملف DateTime
على سبيل المثال، قم بتغيير المنطقة الزمنية الخاصة بك وحاول استخدامها.
مثيلات DateTime ذات قيم "النوع" المختلفة غير متوافقة.
دعونا نلقي نظرة على بعض التعليمات البرمجية ...
DateTime utc = DateTime.UtcNow;
DateTime now = DateTime.Now;
Debug.Log (utc + " " + utc.Kind); // 05/20/2015 17:19:27 Utc
Debug.Log (now + " " + now.Kind); // 05/20/2015 10:19:27 Local
Debug.Log (utc.Ticks); // 635677391678617830
Debug.Log (now.Ticks); // 635677139678617840
now = now.AddHours(1);
TimeSpan diff = utc - now;
Debug.Log (diff); // 05:59:59.9999990
Debug.Log (utc < now); // false
Debug.Log (utc == now); // false
Debug.Log (utc > now); // true
Debug.Log (utc.ToUniversalTime() < now.ToUniversalTime()); // true
Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime()); // false
Debug.Log (utc.ToUniversalTime() > now.ToUniversalTime()); // false
Debug.Log (utc.ToUniversalTime() - now.ToUniversalTime()); // -01:00:00.0000010
كما ترون هنا، لا يتم تحويل المقارنات والدوال الرياضية تلقائيًا إلى أوقات متوافقة.ال Timespan
كان ينبغي أن يكون ما يقرب من ساعة واحدة، ولكن بدلا من ذلك كان ما يقرب من 6.كان من المفترض أن يكون "utc < now" صحيحًا (حتى أنني أضفت ساعة للتأكد من ذلك)، لكنه ظل خطأً.
يمكنك أيضًا رؤية "الحل البديل" وهو التحويل ببساطة إلى التوقيت العالمي في أي مكان Kind
ليس هو نفسه.
تتوافق إجابتي المباشرة على السؤال مع توصية الإجابة المقبولة حول وقت استخدام كل منها.يجب عليك دائما يحاول للعمل مع DateTime
الكائنات التي لديها Kind=Utc
, باستثناء أثناء الإدخال/الإخراج (العرض والتحليل).هذا يعني أنك يجب أن تستخدم دائمًا تقريبًا DateTime.UtcNow
, ، باستثناء الحالات التي تقوم فيها بإنشاء الكائن لعرضه فقط، ثم تجاهله على الفور.
ليس لدى DateTime أي فكرة عن المناطق الزمنية.يفترض دائمًا أنك بالتوقيت المحلي الخاص بك. UTCNow يعني فقط "طرح منطقتي الزمنية من الوقت".
إذا كنت تريد استخدام التواريخ المتوافقة مع المنطقة الزمنية، فاستخدم DateTimeOffset, ، والذي يمثل تاريخًا/وقتًا بمنطقة زمنية.لقد تعلمت هذا بالطريقة الصعبة.
إضافة بسيطة للنقاط المذكورة أعلاه:تحتوي بنية DateTime أيضًا على حقل غير معروف يُسمى عطوف (على الأقل، لم أكن أعرف عن ذلك لفترة طويلة).إنها في الأساس مجرد علامة تشير إلى ما إذا كان الوقت محليًا أم UTC؛ولا يحدد الإزاحة الحقيقية من التوقيت العالمي المنسق (UTC) للأوقات المحلية.بالإضافة إلى حقيقة أنه يشير إلى النوايا التي تم بناء الدعامة بها، فإنه يؤثر أيضًا على طريقة إنشاء الأساليب تويونيفرسالتيمي () و تولوكالتيمي () عمل.
الجواب "البسيط" على السؤال هو:
التاريخ والوقت.الآن يعود أ التاريخ والوقت القيمة التي تمثل وقت النظام الحالي (في أي منطقة زمنية يعمل فيها النظام).ال التاريخ والوقت.النوع الملكية ستكون DateTimeKind.Local
DateTime.UtcNow يعود أ التاريخ والوقت القيمة التي تمثل التوقيت العالمي المنسق الحالي (المعروف أيضًا باسم UTC) والذي سيكون هو نفسه بغض النظر عن المنطقة الزمنية للنظام.ال التاريخ والوقت.النوع الملكية ستكون DateTimeKind.Utc
لقد تأخرت الحفلة قليلًا، لكنني وجدت أن هذين الرابطين (4guysfromrolla) مفيدان جدًا:
استخدام التوقيت العالمي المنسق (UTC) لتخزين قيم التاريخ/الوقت
DateTime.UtcNow هو مقياس زمني مستمر ذو قيمة واحدة، في حين أن DateTime.Now ليس مستمرًا أو ذو قيمة واحدة.السبب الرئيسي هو التوقيت الصيفي، والذي لا ينطبق على التوقيت العالمي المنسق (UTC).لذا فإن التوقيت العالمي المنسق (UTC) لا يقفز أبدًا إلى الأمام أو إلى الخلف لمدة ساعة، في حين أن التوقيت المحلي (DateTime.Now) يفعل ذلك.وعندما يقفز للخلف، فإن نفس القيمة الزمنية تحدث مرتين.
DateTime.UtcNow هو مقياس زمني عالمي يحذف التوقيت الصيفي.لذا فإن التوقيت العالمي المنسق (UTC) لا يتغير أبدًا بسبب التوقيت الصيفي.
لكن DateTime.Now ليس مستمرًا أو أحادي القيمة لأنه يتغير وفقًا للتوقيت الصيفي.وهو ما يعني DateTime. الآن، قد تحدث نفس القيمة الزمنية مرتين مما يترك العملاء في حالة من الحيرة.
عندما تحتاج إلى توقيت محلي للجهاز الذي يعمل عليه تطبيقك (مثل CEST لأوروبا)، استخدم الآن.إذا كنت تريد توقيتًا عالميًا - UtcNow.إنها مجرد مسألة تفضيلاتك - ربما إنشاء موقع ويب محلي/تطبيق مستقل ترغب في استخدام الوقت الذي يمتلكه المستخدم - متأثرًا جدًا بإعدادات المنطقة الزمنية الخاصة به - DateTime.Now.
فقط تذكر أنه بالنسبة لموقع الويب، فهذا هو إعداد المنطقة الزمنية للخادم.لذا، إذا كنت تعرض الوقت للمستخدم، فاحصل على المنطقة الزمنية المفضلة لديه وقم بتغيير الوقت (فقط احفظ وقت UTC في قاعدة البيانات ثم قم بتعديله) أو حدد التوقيت العالمي المنسق (UTC).إذا نسيت القيام بذلك، يمكن للمستخدم رؤية شيء مثل: نشرت منذ 3 ناقص ثم وقت في المستقبل بالقرب منه :)