الانتقال إلى المحتوى الرئيسي
يتيح تخزين نقطة زمنية يمكن التعبير عنها كتاريخ تقويمي ووقت من اليوم. الصياغة:
DateTime([timezone])
نطاق القيم المدعوم: [1970-01-01 00:00:00, 2106-02-07 06:28:15]. الدقة: ثانية واحدة.

السرعة

يكون نوع البيانات Date أسرع من DateTime في معظم الحالات. يتطلب النوع Date مساحة تخزين قدرها 2 بايت، بينما يتطلب DateTime 4 بايتات. ومع ذلك، أثناء الضغط، يصبح الفرق في الحجم بين Date وDateTime أكثر وضوحًا. ويرجع هذا التضخيم إلى أن الدقائق والثواني في DateTime أقل قابليةً للضغط. كما أن تصفية Date وتجميعه بدلًا من DateTime أسرع أيضًا.

ملاحظات الاستخدام

تُحفَظ النقطة الزمنية على شكل Unix timestamp، بغضّ النظر عن المنطقة الزمنية أو التوقيت الصيفي. وتؤثر المنطقة الزمنية في كيفية عرض قيم النوع DateTime بتنسيق نصي، وفي كيفية تحليل القيم المحددة كسلاسل نصية (‘2020-01-01 05:00:01’). يُخزَّن Unix timestamp غير المرتبط بمنطقة زمنية في الجداول، وتُستخدم المنطقة الزمنية لتحويله إلى تنسيق نصي أو العكس أثناء استيراد البيانات أو تصديرها، أو لإجراء حسابات تقويمية على القيم (على سبيل المثال: الدالتان toDate وtoHour، إلخ). ولا تُخزَّن المنطقة الزمنية في صفوف الجدول (أو في resultset)، بل تُخزَّن في البيانات الوصفية للعمود. يمكن العثور على قائمة بالمناطق الزمنية المدعومة في IANA Time Zone Database، كما يمكن الاستعلام عنها باستخدام SELECT * FROM system.time_zones. وهذه القائمة متاحة أيضًا على Wikipedia. يمكنك تعيين منطقة زمنية صراحةً للأعمدة من النوع DateTime عند إنشاء جدول. Example: DateTime('UTC'). وإذا لم تُعيَّن منطقة زمنية، يستخدم ClickHouse قيمة المعلمة timezone في إعدادات الخادم أو في إعدادات نظام التشغيل وقت بدء تشغيل ClickHouse server. يستخدم clickhouse-client المنطقة الزمنية الخاصة بالخادم افتراضيًا إذا لم تُعيَّن منطقة زمنية صراحةً عند تهيئة نوع البيانات. ولاستخدام المنطقة الزمنية الخاصة بالعميل، شغّل clickhouse-client باستخدام المعلمة --use_client_time_zone. يعرض ClickHouse القيم وفقًا لقيمة الإعداد date_time_output_format. ويكون التنسيق النصي الافتراضي هو YYYY-MM-DD hh:mm:ss. بالإضافة إلى ذلك، يمكنك تغيير تنسيق الإخراج باستخدام الدالة formatDateTime. عند insert البيانات إلى ClickHouse، يمكنك استخدام تنسيقات مختلفة لسلاسل التاريخ والوقت، وذلك بحسب قيمة الإعداد date_time_input_format.

أمثلة

1. إنشاء جدول يحتوي على عمود من النوع DateTime وإدخال بيانات إليه:
CREATE TABLE dt
(
    `timestamp` DateTime('Asia/Istanbul'),
    `event_id` UInt8
)
ENGINE = TinyLog;
-- Parse DateTime
-- - from string,
-- - from integer interpreted as number of seconds since 1970-01-01.
INSERT INTO dt VALUES ('2019-01-01 00:00:00', 1), (1546300800, 2);

SELECT * FROM dt;
┌───────────timestamp─┬─event_id─┐
│ 2019-01-01 00:00:00 │        1 │
│ 2019-01-01 03:00:00 │        2 │
└─────────────────────┴──────────┘
  • عند إدراج قيمة datetime كعدد صحيح، تُعامَل على أنها Unix Timestamp ‏(UTC). تمثّل 1546300800 القيمة '2019-01-01 00:00:00' بتوقيت UTC. ولكن بما أن العمود timestamp محدَّد له المنطقة الزمنية Asia/Istanbul ‏(UTC+3)، فعند إخراجها كسلسلة نصية ستظهر القيمة على شكل '2019-01-01 03:00:00'
  • عند إدراج قيمة نصية كـ datetime، تُعامَل على أنها ضمن المنطقة الزمنية للعمود. ستُعامَل '2019-01-01 00:00:00' على أنها ضمن المنطقة الزمنية Asia/Istanbul وتُحفَظ على أنها 1546290000.
2. التصفية حسب قيم DateTime
SELECT * FROM dt WHERE timestamp = toDateTime('2019-01-01 00:00:00', 'Asia/Istanbul')
┌───────────timestamp─┬─event_id─┐
│ 2019-01-01 00:00:00 │        1 │
└─────────────────────┴──────────┘
يمكن تصفية قيم عمود DateTime باستخدام قيمة نصية في شرط WHERE. وسيُحوَّل هذا تلقائيًا إلى DateTime:
SELECT * FROM dt WHERE timestamp = '2019-01-01 00:00:00'
┌───────────timestamp─┬─event_id─┐
│ 2019-01-01 00:00:00 │        1 │
└─────────────────────┴──────────┘
3. الحصول على المنطقة الزمنية لعمود من النوع DateTime:
SELECT toDateTime(now(), 'Asia/Istanbul') AS column, toTypeName(column) AS x
┌──────────────column─┬─x─────────────────────────┐
│ 2019-10-16 04:12:04 │ DateTime('Asia/Istanbul') │
└─────────────────────┴───────────────────────────┘
4. تحويل التوقيت بين المناطق الزمنية
SELECT
toDateTime(timestamp, 'Europe/London') AS lon_time,
toDateTime(timestamp, 'Asia/Istanbul') AS istanbul_time
FROM dt
┌───────────lon_time──┬───────istanbul_time─┐
│ 2019-01-01 00:00:00 │ 2019-01-01 03:00:00 │
│ 2018-12-31 21:00:00 │ 2019-01-01 00:00:00 │
└─────────────────────┴─────────────────────┘
بما أن تحويل المنطقة الزمنية لا يغيّر سوى البيانات الوصفية، فلا تترتب على هذه العملية أي تكلفة حسابية.

القيود على دعم المناطق الزمنية

قد لا تكون بعض المناطق الزمنية مدعومة بالكامل. وهناك بضع حالات: إذا لم تكن الإزاحة عن UTC من مضاعفات 15 دقيقة، فقد يكون حساب الساعات والدقائق غير دقيق. على سبيل المثال، كانت المنطقة الزمنية في مونروفيا، ليبيريا ذات إزاحة UTC -0:44:30 قبل 7 Jan 1972. إذا كنت تُجري حسابات على أوقات تاريخية في المنطقة الزمنية لمونروفيا، فقد تُعطي دوال معالجة الوقت نتائج غير صحيحة. ومع ذلك، ستكون النتائج بعد 7 Jan 1972 صحيحة. إذا حدث الانتقال الزمني (بسبب التوقيت الصيفي أو لأسباب أخرى) عند نقطة زمنية ليست من مضاعفات 15 دقيقة، فقد تحصل أيضًا على نتائج غير صحيحة في ذلك اليوم تحديدًا. تواريخ تقويمية غير أحادية التدرج. على سبيل المثال، في Happy Valley - Goose Bay، أُعيد الوقت ساعة واحدة إلى الوراء عند 00:01:00 في 7 Nov 2010 (أي بعد دقيقة واحدة من منتصف الليل). لذلك، بعد انتهاء 6th Nov، عاش الناس دقيقة كاملة من 7th Nov، ثم أُعيد الوقت إلى 23:01 من 6th Nov، وبعد 59 دقيقة أخرى بدأ 7th Nov مرةً أخرى. لا يدعم ClickHouse (حتى الآن) هذا النوع من الطرائف. خلال هذه الأيام، قد تكون نتائج دوال معالجة الوقت غير دقيقة قليلًا. توجد مشكلة مشابهة في محطة Casey Antarctic في عام 2010. فقد أُعيد الوقت ثلاث ساعات إلى الوراء في 5 Mar عند 02:00. إذا كنت تعمل في هذه المحطة في القارة القطبية الجنوبية، فلا تتردد في استخدام ClickHouse. فقط تأكد من ضبط المنطقة الزمنية على UTC أو كن على دراية بإمكانية حدوث بعض حالات عدم الدقة. إزاحات زمنية تمتد لعدة أيام. غيّرت بعض جزر المحيط الهادئ إزاحة منطقتها الزمنية من UTC+14 إلى UTC-12. هذا مقبول، ولكن قد تظهر بعض حالات عدم الدقة إذا أجريت حسابات باستخدام منطقتها الزمنية لنقاط زمنية تاريخية في أيام التحويل.

التعامل مع التوقيت الصيفي (DST)

قد يُظهر نوع DateTime في ClickHouse مع المناطق الزمنية سلوكًا غير متوقع أثناء الانتقال بين التوقيت الصيفي (DST) والتوقيت القياسي، وخصوصًا عندما:
  • يكون date_time_output_format مضبوطًا على simple.
  • تُعاد الساعات إلى الخلف (“Fall Back”)، مما يؤدي إلى تداخل لمدة ساعة واحدة.
  • تُقدَّم الساعات إلى الأمام (“Spring Forward”)، مما يؤدي إلى فجوة لمدة ساعة واحدة.
بشكل افتراضي، يختار ClickHouse دائمًا أول ظهور للوقت المتداخل، وقد يفسّر الأوقات غير الموجودة أثناء التقديم إلى الأمام. على سبيل المثال، تأمل الانتقال التالي من التوقيت الصيفي (DST) إلى التوقيت القياسي.
  • في 29 أكتوبر 2023، عند 02:00:00، تُعاد الساعات إلى الخلف إلى 01:00:00 (BST → GMT).
  • تظهر الساعة 01:00:00 – 01:59:59 مرتين (مرة بتوقيت BST ومرة بتوقيت GMT)
  • يختار ClickHouse دائمًا الظهور الأول (BST)، مما يؤدي إلى نتائج غير متوقعة عند إضافة فواصل زمنية.
SELECT '2023-10-29 01:30:00'::DateTime('Europe/London') AS time, time + toIntervalHour(1) AS one_hour_later

┌────────────────time─┬──────one_hour_later─┐
2023-10-29 01:30:002023-10-29 01:30:00
└─────────────────────┴─────────────────────┘
وبالمثل، أثناء الانتقال من التوقيت القياسي إلى التوقيت الصيفي، قد يبدو كما لو أن ساعةً قد تم تجاوزها. على سبيل المثال:
  • في 26 مارس 2023، عند 00:59:59، تُقدَّم الساعة مباشرةً إلى 02:00:00 ‏(GMT → BST).
  • الساعة 01:00:0001:59:59 غير موجودة.
SELECT '2023-03-26 01:30:00'::DateTime('Europe/London') AS time, time + toIntervalHour(1) AS one_hour_later

┌────────────────time─┬──────one_hour_later─┐
2023-03-26 00:30:002023-03-26 02:30:00
└─────────────────────┴─────────────────────┘
في هذه الحالة، يعيد ClickHouse الوقت غير الموجود 2023-03-26 01:30:00 إلى 2023-03-26 00:30:00.

راجع أيضًا

آخر تعديل في ٢٥ يونيو ٢٠٢٦