سؤال

كنت أفكر في استخدام الطابع الزمني لتخزين التاريخ + الوقت، لكنني قرأت أن هناك قيود على أساس عام 2038 عليه. بدلا من طرح سؤالي بكميات كبيرة، فضلت كسرها إلى أجزاء صغيرة بحيث يكون من السهل أن يفهم مستخدمو المبتدئين أيضا. لذلك سؤالي (ق):

  1. ما هو بالضبط مشكلة عام 2038؟
  2. لماذا يحدث وما يحدث عند حدوثه؟
  3. كيف نحلها؟
  4. هل هناك أي بدائل محتملة لاستخدامها، والتي لا تشكل مشكلة مماثلة؟
  5. ما الذي يمكننا فعله في التطبيقات الحالية التي تستخدم الطابع الزمني، لتجنب المشكلة المزعومة، عندما يحدث ذلك حقا؟

شكرا مقدما.

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

المحلول

لقد قمت بتمييز هذا كمجتمع Wiki، لذلك لا تتردد في تحريره في وقت فراغك.

ما هو بالضبط مشكلة عام 2038؟

"مشكلة عام 2038 (المعروفة أيضا باسم UNIX Millennium BUG، Y2K38 عن طريق تشبيه مشكلة Y2K) قد تتسبب في فشل بعض برامج الكمبيوتر قبل أو في عام 2038. تؤثر المشكلة على جميع البرامج والأنظمة التي تخزن وقت النظام كوقت موقعة عدد صحيح، وتفسير هذا الرقم كعدد الثواني منذ 00:00:00 UTC في 1 يناير 1970. "


لماذا يحدث وما يحدث عند حدوثه؟

مرات بعد 03:14:07 UTC يوم الثلاثاء، 19 يناير 2038 سيتم "التفاف حولها" وتخزينها داخليا كرقم سالب، والتي ستفسر هذه الأنظمة كوقت في 13 ديسمبر 1901 بدلا من عام 2038. وهذا يرجع إلى حقيقة أن عدد الثواني منذ عصر يونيكس (1 يناير 1970 00:00:00 بتوقيت جرينتش) سوف تجاوزت القيمة القصوى لجهاز الكمبيوتر لعدد صحيح موقعة 32 بت.


كيف نحلها؟

  • استخدام أنواع البيانات الطويلة (64 بت كافية)
  • ل mysql (أو mariadb)، إذا كنت لا تحتاج إلى معلومات الوقت تنظر في استخدام DATE نوع العمود. إذا كنت بحاجة إلى دقة أعلى، فاستخدم DATETIME بدلا من TIMESTAMP. وبعد احذر ذلك DATETIME لا تخزن الأعمدة معلومات حول timezone، لذلك سيتعين على طلبك معرفة الوقت الذي تم استخدامه.
  • الحلول الممكنة الأخرى الموصوفة على ويكيبيديا
  • انتظر MySQL Devs لإصلاح هذا الخطأ ذكرت منذ أكثر من عقد.

هل هناك أي بدائل محتملة لاستخدامها، والتي لا تشكل مشكلة مماثلة؟

حاول أينما كان من الممكن استخدام أنواع كبيرة لتخزين التواريخ في قواعد البيانات: 64 بت كافية - نوع طويل في جنو ج وبوسيكس / سوس، أو sprintf('%u'...) في PHP أو ملحق BCMATH.


ما هي بعض حالات الاستخدام المحتملة على الرغم من أننا لسنا حتى الآن في عام 2038؟

لذلك mysql. DateTime. لديه مجموعة من 1000-9999، ولكن الطابع الزمني لديه فقط مجموعة من 1970-2038. إذا قام نظامك بتخزين المواليد، تواريخ المستقبل المستقبلية (على سبيل المثال القروض العقارية لمدة 30 عاما)، أو ما شابه ذلك، فأنت ستركض بالفعل في هذا الخطأ. مرة أخرى، لا تستخدم الطابع الزمني إذا كانت هذه ستكون مشكلة.


ما الذي يمكننا فعله في التطبيقات الحالية التي تستخدم الطابع الزمني، لتجنب المشكلة المزعومة، عندما يحدث ذلك حقا؟

ستظل عدد قليل من تطبيقات PHP موجودة في عام 2038، على الرغم من أنها من الصعب توقعها لأن الويب بالكاد منصة قديمة حتى الآن.

فيما يلي عملية لتغيير عمود جدول قاعدة البيانات للتحويل TIMESTAMP ل DATETIME. وبعد يبدأ بإنشاء عمود مؤقت:

# rename the old TIMESTAMP field
ALTER TABLE `myTable` CHANGE `myTimestamp` `temp_myTimestamp` int(11) NOT NULL;

# create a new DATETIME column of the same name as your old column
ALTER TABLE `myTable` ADD `myTimestamp` DATETIME NOT NULL;

# update all rows by populating your new DATETIME field
UPDATE `myTable` SET `myTimestamp` = FROM_UNIXTIME(temp_myTimestamp);

# remove the temporary column
ALTER TABLE `myTable` DROP `temp_myTimestamp`

موارد

نصائح أخرى

عند استخدام TimEstamps Unix لتخزين التواريخ، فأنت تستخدم بالفعل أعداد صحيحة 32 بت، والتي تحافظ على عدد الثواني منذ 1970-01-01؛ يرى وقت يونكس

هذا الرقم 32 بت سوف يتفوق في عام 2038. هذه هي المشكلة 2038.


لحل هذه المشكلة، يجب ألا تستخدم الطابع الزمني ل UNIX 32 بت لتخزين التواريخ الخاصة بك - مما يعني، عند استخدام MySQL، يجب ألا تستخدمه TIMESTAMP, ، لكن DATETIME (يرى 10.3.1. أنواع DateTime والتاريخ والطابع الزمني) :

ال DATETIME يتم استخدام الكتابة عند الحاجة إلى القيم التي تحتوي على معلومات التاريخ والوقت. النطاق المدعوم هو '1000-01-01 00:00:00' ل '9999-12-31 23:59:59'.

ال TIMESTAMP نوع البيانات لديه مجموعة من '1970-01-01 00:00:01' UTC إلى '2038-01-19 03:14:07' التوقيت العالمي.


ال (المحتمل) أفضل شيء يمكنك القيام به في طلبك لتجنب / إصلاح هذه المشكلة هو عدم استخدامه TIMESTAMP, ، لكن DATETIME بالنسبة للأعمدة التي يجب أن تحتوي على التواريخ التي لا تتراوح بين عامي 1970 و 2038.

ملاحظة صغيرة واحدة، رغم ذلك: هناك مرتفع للغاية (متحدث إحصائي) سيتم إعادة كتابة طلبك في عدة مرات قبل 2038 ^^ لذلك ربما، إذا لم يكن لديك للتعامل مع التواريخ في المستقبل، فلن تضطر إلى العناية بهذه المشكلة مع الإصدار الحالي من طلبك ...

ستقوم البحث السريع على Google بالخدعة: عام 2038 مشكلة

  1. قد تسبب مشكلة عام 2038 (المعروف أيضا باسم UNIX Millennium Bug، Y2K38 عن طريق التشبيه إلى مشكلة Y2K) في فشل بعض برامج الكمبيوتر قبل أو في عام 2038
  2. تؤثر المشكلة على جميع البرامج والأنظمة التي تخزن وقت النظام كعدد صحيح موقعة 32 بت، وتفسير هذا الرقم كعدد الثواني منذ 00:00:00 UTC في 1 يناير 1970. أحدث وقت يمكن تمثيله بهذه الطريقة هو 03:14:07 UTC يوم الثلاثاء، 19 يناير 2038. أوقات تتجاوز هذه اللحظة سوف "تغلب حولها" وتخزينها داخليا كرقم سلبي، والتي ستفسر هذه الأنظمة كتاريخ في عام 1901 بدلا من 2038
  3. لا يوجد حل سهل لهذه المشكلة لمجموعات وحدة المعالجة المركزية / OS الموجودة وأنظمة الملفات الموجودة أو تنسيقات البيانات الثنائية الحالية

http://en.wikipedia.org/wiki/year_2038_problem. لديه معظم التفاصيل

باختصار:

1) + 2) المشكلة هي أن العديد من تطبيقات Design Store STYSTAME كالموقع 32 بت يساوي عدد الثواني منذ 1/1/1970. أحدث موعد يمكن تخزينه مثل هذا هو 03:14:07 UTC يوم الثلاثاء، 19 يناير 2038. عندما يحدث هذا int سوف "التفاف حولها" ويتم تخزينها كرقم سالب سيتم تفسيره كموعد في عام 1901. ما الذي سيحدث بالضبط بعد ذلك، يختلف من النظام إلى النظام ولكنه يكفي أن نقول أنه ربما لن يكون جيدا لأي منهم!

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

3) استخدم أحد تنسيقات التاريخ البديلة المتاحة أو الانتقال إلى نظام 64 بت واستخدم INTS 64 بت. أو بالنسبة لقواعد البيانات، استخدم تنسيق ختم وقت بديل (على سبيل المثال بالنسبة ل MySQL استخدم DateTime)

4) انظر 3!

5) انظر 4! ؛)

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

استخدام وظيفة custom_date (). داخلها، استخدم DateTime. إليك محلول DateTime.

طالما أن لديك bigint غير موقعة (8) مثل الطابع الزمني الخاص بك في قاعدة البيانات. طالما لديك PHP 5.2.0 ++

كما لا أريد ترقيت أي شيء، سألت الخلفية (MSSQL) للقيام بهذه المهمة بدلا من PHP!

$qry = "select DATEADD(month, 1, :date) next_date ";
$rs_tmp = $pdo->prepare($qry);
$rs_tmp->bindValue(":date", '2038/01/15');
$rs_tmp->execute();
$row_tmp = $rs_tmp->fetch(PDO::FETCH_ASSOC);

echo $row_tmp['next_date'];

قد لا تكون وسيلة فعالة، لكنها تعمل.

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