محوّل طوابع زمن Unix

حوّل طابع زمن Unix إلى تاريخ مقروء في أي منطقة زمنية، وحوّل التاريخ إلى قيمة epoch.

زمن Unix الحالي
جارٍ التحديد…
الإدخال

ما هو طابع زمن Unix

طابع زمن Unix — ويُسمّى أيضًا زمن epoch أو زمن POSIX — هو رقم واحد يَعُدّ كم ثانية مضت منذ الساعة 00:00:00 بتوقيت UTC من الأول من يناير 1970، وهي لحظة تُعرف باسم epoch الخاصة بـ Unix. ولأنه عدد صحيح واحد، بلا منطقة زمنية ولا تقويم ولا تنسيق، فهو الصيغة التي تلجأ إليها الحواسيب كلما لزم تخزين لحظة زمنية أو ترتيبها أو مقارنتها أو إرسالها عبر الشبكة. وهو ما يقف خلف العمود «created_at» في قاعدة بياناتك، وخلف الحقلين «iat» و«exp» في رمز JWT، وخلف mtime لأي ملف، وخلف الطوابع الزمنية في كل ملف سجل تقريبًا ستقرؤه يومًا.

المقابل أن الرقم المجرّد لا يعني شيئًا للإنسان. فالقيمة 1716197600 لحظة سليمة تمامًا، لكنك لا تستطيع أن تعرف بنظرة واحدة أهي الثلاثاء الماضي أم قبل ثلاث سنوات. وهذه الترجمة، في الاتجاهين معًا، هي ما تفعله هذه الأداة.

ثوانٍ أم ميلي ثانية — الالتباس الذي يعَضّ

العُرف الأصلي في Unix يَعُدّ ثوانيَ كاملة، وهو ما تحصل عليه من date +%s في الصدفة، ومن time()‎ في PHP، ومن time.time()‎ في بايثون بعد الاقتطاع. أما جافاسكربت وجافا وكثير غيرهما فتَعُدّ الميلي ثانية: فـ Date.now()‎ يُعيد رقمًا أكبر بألف مرة. وكلاهما يُسمّى «طابعًا زمنيًا»، والخلط بينهما من أشيع أخطاء التواريخ على الإطلاق.

والعطل هنا صامت لا صاخب. اقرأ قيمة بالميلي ثانية على أنها ثوانٍ فيهبط تاريخك عشرات آلاف السنين في المستقبل؛ واقرأ قيمة بالثواني على أنها ميلي ثانية فينهار كل شيء إلى يناير 1970. ولا يرفع أيٌّ منهما خطأً — بل تحصل ببساطة على تاريخ خاطئ يبدو كأنه تاريخ حقيقي.

تُخمّن هذه الأداة اعتمادًا على رتبة حجم الرقم، ثم تخبرك بما خمّنته إلى جوار النتيجة مباشرة. فثواني epoch اليوم من عشرة أرقام، وميلي ثوانيها من ثلاثة عشر، ولذلك يكون التخمين صائبًا في الغالب الأعم — غير أن «الغالب» لا يكفي لقيمة توشك أن تلصقها في تقرير خلل، ولهذا تبقى القراءة ظاهرة دائمًا وعلى بُعد نقرة واحدة من التبديل.

المناطق الزمنية وUTC ولماذا «المحلي» زَلِق

لا منطقة زمنية لطابع زمن Unix. فهو يحدّد لحظة، وتلك اللحظة نفسها هي في آنٍ واحد 09:33 في لندن، و11:33 في القدس، و18:33 في طوكيو. المنطقة الزمنية ليست جزءًا من القيمة؛ بل هي العدسة التي تنظر بها إليها.

ولهذا تعرض الأداة عدة عدسات في وقت واحد. فـ UTC هو المرجع المحايد الذي تتفق عليه كل الخوادم وكل السجلات. وتوقيتك المحلي هو ما يبلّغ عنه جهازك أنت، ويُعرض مع اسم منطقته (مثل Europe/Berlin) لتعرف دائمًا أي عدسة أنتجته — والاكتشاف يجري داخل متصفحك، فالزائر من برلين يرى توقيت برلين والزائر من طوكيو يرى توقيت طوكيو. أما السطر الثالث فهو أي منطقة تختارها من قاعدة بيانات IANA الكاملة، وهو السطر الذي تحتاجه حين تقرأ سجلّ خادم يقيم في مكان آخر.

  • UTC — المرجع الذي تتفق عليه كل الأنظمة، والصواب في التخزين وتدوين السجلات.
  • المحلي — اللحظة نفسها كما يراها جهازك، موسومة بالمنطقة التي اكتُشفت.
  • منطقة من اختيارك — لقراءة السجلات والتتبّعات من أجهزة في أماكن أخرى.
  • ISO 8601 — صيغة النص المعتمدة للتبادل، مثل 2024-05-20T09:33:20.000Z.
  • نسبي — «قبل 3 ساعات»، لإحساس سريع بمدى حداثة الشيء.

وتُعرض الإزاحات بجانب كل توقيت (‎+03:00 و‎-04:00) لأنها ليست ثابتة: فأغلب المناطق تنزاح ساعةً بسبب التوقيت الصيفي، حتى إن المنطقة الواحدة قد تُنتج إزاحات مختلفة في أوقات مختلفة من السنة. والتاريخ القريب من موعد التحويل هو بالضبط الموضع الذي يخطئ فيه الحساب اليدوي.

التعامل مع زمن epoch عمليًا

لكل لغة ولكل صدفة طريقتها في إنتاج قيم epoch وقراءتها. وهذه تستحق أن تُحفظ:

date +%s                         # الصدفة: الوقت الحالي بالثواني
date -d @1716197600              # الصدفة (GNU): من الثواني إلى تاريخ
Date.now()                       # جافاسكربت: الوقت الحالي بالميلي ثانية
new Date(1716197600 * 1000)      # جافاسكربت: من الثواني إلى Date
time.time()                      # بايثون: ثوانٍ، كعدد عشري
datetime.fromtimestamp(1716197600, tz=timezone.utc)
SELECT EXTRACT(EPOCH FROM now()) -- PostgreSQL: ثوانٍ

قاعدة عملية تجنّبك معظم آلام التواريخ: خزّن اللحظات وأرسلها بتوقيت UTC — إما عددًا صحيحًا من نوع epoch أو نصًّا بصيغة ISO 8601 — ولا تحوّلها إلى منطقة محلية إلا في اللحظة الأخيرة، حين تعرضها فعلًا على أحد. فالتنسيق المبكر هو الطريق الذي يجعل خطأ المنطقة الزمنية يُخبَز داخل بياناتك بدل أن يبقى في طبقة العرض.

وثمة أمر آخر يحسن معرفته: عدّاد الثواني ذو 32 بتًا بإشارة ينفد في 19 يناير 2038، وهي «مشكلة عام 2038». الأنظمة الحديثة تستعمل قيمًا من 64 بتًا وهي بمأمن، لكن الأجهزة المضمّنة القديمة وأعمدة قواعد البيانات الموروثة هي بالضبط المواضع التي قد تصادفها فيها بعد.

الأسئلة الشائعة

كيف تعرف الأداة إن كان رقمي بالثواني أم بالميلي ثانية؟
من رتبة حجمه: القيم دون 1e11 تقريبًا تُقرأ ثوانيَ، والأكبر منها تُقرأ ميلي ثانية. وهذا اليوم يفصل بوضوح بين الثواني ذات العشرة أرقام والميلي ثواني ذات الثلاثة عشر. والقراءة معروضة بجانب النتيجة ويمكنك تبديلها بنقرة واحدة، فالتخمين لا يُخفى عنك أبدًا.
ما المنطقة الزمنية التي تُعدّ «محلية»؟
المنطقة التي يبلّغ عنها جهازك أنت، تُكتشف في متصفحك وتُعرض باسمها كي لا يبقى شك. إنها منطقتك أنت لا منطقة الموقع: فالزائر من برلين يرى توقيت برلين والزائر من طوكيو يرى توقيت طوكيو.
هل يمكنني تحويل تاريخ إلى طابع زمني؟
نعم. الحقل نفسه يقبل الاتجاهين: اكتب رقمًا فتحصل على تاريخ، واكتب تاريخًا مثل 2024-05-20 أو 2024-05-20T09:33:20Z فتحصل على قيمة epoch. ولا وضع عليك تبديله.
هل يتعامل مع تواريخ ما قبل 1970؟
نعم. الطوابع الزمنية السابقة لـ epoch سالبة ببساطة — فالقيمة ‎-86400 هي 31 ديسمبر 1969 — والقيم السالبة تُقبل وتُحوَّل كالمعتاد.
لماذا يعرض طابعي الزمني تاريخًا غير الذي توقّعته؟
يعود ذلك دائمًا تقريبًا إلى أحد سببين: إما أن قراءة الثواني/الميلي ثانية ليست ما افترضته (انظر إلى الوسم وبدّله)، وإما أنك تقارن قيمة بتوقيت UTC بتوقّع بالتوقيت المحلي. وتعرض الأداة السطرين جنبًا إلى جنب لترى أيّهما الحاصل.
ما مشكلة عام 2038؟
الأنظمة التي تخزّن ثواني epoch في عدد صحيح من 32 بتًا بإشارة تفيض في 19 يناير 2038 وتنقلب إلى رقم سالب، فتعطي تواريخ في عام 1901. وكل ما يستعمل قيمًا من 64 بتًا — أي كل ما هو حديث تقريبًا — غير متأثر، لكن الأنظمة المضمّنة الموروثة وأعمدة قواعد البيانات القديمة قد تظل معرّضة للخطر.
هل يُرسَل الطابع الزمني الذي أُدخله إلى أي جهة؟
لا. التحليل والتحويل والتنسيق تجري كلها داخل متصفحك، اعتمادًا على دعم التواريخ والمناطق الزمنية المدمج في المنصّة نفسها. ولا يغادر شيء مما تكتبه جهازك.