Menu
flag Ar iconالعربيةdown icon

التواريخ في R: ‏as.Date وformat() وحساب التواريخ

صنف Date في R ما هو إلا عدّاد أيام يرتدي زيًّا. كيفية تحليل السلاسل النصية بـ as.Date، وتنسيق التواريخ للعرض، وطرحها، وبناء متتاليات منها، ومتى تحتاج إلى POSIXct بدلًا منها.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

التاريخ في R عدّاد أيام يرتدي زيًّا

لتحويل سلسلة نصية إلى تاريخ حقيقي استخدم as.Date()، وللحصول على تاريخ اليوم استخدم Sys.Date(). وخلف كلتيهما حيلة بسيطة: فصنف Date في R ليس سوى رقم، أي عدد الأيام منذ الأول من يناير 1970، يرتدي زيًّا يجعله يُطبع كتاريخ تقويمي. ويمكنك نزع الزي بـ unclass():

القيمة 20672 هي عدّاد الأيام الخام، وهي ما يجعل كل شيء آخر في هذه الصفحة يعمل: فالمقارنات والطرح والمتتاليات كلها حساب أعداد صحيحة في العمق. أما الزي فهو ما يجعله قابلًا للاستخدام، إذ يُطبع الرقم نفسه تاريخًا، ويُنسَّق تاريخًا، ويُرسم على محور تواريخ.

وتحلل as.Date() بسرور ترتيب ISO أي "YYYY-MM-DD" دون أي مساعدة، وهذا أحد أسباب عدة وجيهة لتخزين التواريخ بهذه الصيغة في ملفاتك. وعادة ينبغي بناؤها مبكرًا: التحليل الفاشل يُرجع NA بصمت لا خطأً، لذا ألقِ دائمًا نظرة على النتيجة بعد تحليل شيء جديد.

والسلاسل التي تبدو تواريخ تظل مجرد سلاسل نصية: فالمقارنة "2026-08-07" < "2026-11-01" تصادف أن تكون صحيحة لأن ترتيب ISO يوافق الترتيب الأبجدي، أما "07/08/2026" فترتيبها عبث. حوّل أولًا ثم قارن.

تحليل الترتيبات الأخرى بـ format =

لا يكتب العالم تواريخه بصيغة ISO. ولكل ما عدا ذلك، تأخذ as.Date() وسيطًا اسمه format =، وهو وصفة تصف السلسلة الواردة ومبنية من رموز %.

كلها الثلاثة تُحلَّل إلى اليوم نفسه. ويجب أن تطابق الوصفة السلسلة تمامًا بما فيها الفواصل: فـ "%d/%m/%Y" لن تحلل "07-08-2026". وهذه الرموز التي ستستخدمها فعلًا:

الرمزالمعنىمثال
%Yسنة من أربعة أرقام2026
%yسنة من رقمين26
%mرقم الشهر08
%dيوم الشهر07
%bاسم الشهر مختصرًاAug
%Bاسم الشهر كاملًاAugust
%aاسم اليوم مختصرًاFri
%Aاسم اليوم كاملًاFriday
%Hالساعة (00-23)14
%Mالدقيقة30
%Sالثانية05

والكمين الكلاسيكي هو "07/08/2026" نفسها: يوم/شهر/سنة في معظم العالم، وشهر/يوم/سنة في الولايات المتحدة، ولا يستطيع R تخمين أي منهما يقصد ملفك. والأسوأ أن التخمين الخاطئ "ينجح" غالبًا لأن القراءتين تاريخان صالحان، إلى أن يأتي اليوم الثالث عشر من شهر ما فيُحلَّل إلى NA (إذ لا يوجد شهر ثالث عشر). فاعرف عرف بياناتك قبل أن تكتب الوصفة.

تنسيق التواريخ للعرض

format() هي صورة as.Date() في المرآة: الرموز % نفسها لكن في الاتجاه المعاكس، إذ يدخل التاريخ وتخرج السلسلة.

استخدم ذلك في عناوين التقارير والتسميات وأسماء الملفات، فـ format(Sys.Date(), "%Y-%m-%d") تنتج أسماء تُرتَّب زمنيًا. وتفصيلان يستحقان المعرفة: يضيف %d صفرًا بادئًا ("August 07")، وينتج %B/%A أسماءً بلغة إعدادات نظامك، فجلسة مضبوطة على الألمانية تطبع "Freitag" بدل "Friday". أبقِ التنسيق على أطراف سكربتك ومن أجل البشر، وأبقِ التواريخ داخليًا تواريخ.

حساب التواريخ والمتتاليات

لأن التاريخ عدّاد أيام، يعمل الحساب كما تتمنى. وطرح تاريخين يعطي كائن difftime:

ثلاث عادات تؤخذ من هذه الكتلة. أولًا، غلّف difftime بـ as.numeric() قبل إجراء حسابات عليه، فهو يحمل سمة وحدات قد تفاجئ الحسابات اللاحقة. ثانيًا، حين تهم الوحدات فصرّح بها عبر difftime(units = ) بدل قبول ما يختاره R. ثالثًا، إضافة رقم مجرد تعني إضافة أيام، فلا توجد صيغة + 1 month في base R لأن "شهرًا واحدًا" ليس عددًا ثابتًا من الأيام.

وللتنقل الواعي بالتقويم استخدم seq()، فهي تفهم "day" و"week" و"month" و"quarter" و"year":

ومتتاليات الأشهر هي الأداة المعيارية لفترات التقارير وعلامات المحاور. وثمة طرافة واحدة: ابدأ متتالية شهرية في اليوم 31 وسيواصل R عدّ الأيام الحقيقية عبر أشهر تفتقر إليه، فتقع مدخلة "فبراير" في أوائل مارس. لذا ثبّت المتتاليات الشهرية على اليوم الأول واشتق كل شيء آخر منه.

استخراج أجزاء التاريخ

يملك base R مستخرِجَين مريحين وصيغة عامة واحدة. تُرجع weekdays() وmonths() أسماءً، أما للأرقام فمرّ عبر format() ذهابًا وإيابًا:

تبدو حركة format() ثم as.integer() ملتوية، لكنها الصيغة المعيارية في base R، وهي متجهية، فمرّر إليها عمود تواريخ كاملًا تحصل على عمود سنوات كامل. وهذا بالضبط ما تريده بعد استيراد مجموعة بيانات مؤرخة من ملف CSV: حلّل عمود التاريخ مرة واحدة بـ as.Date()، ثم اشتق عمودَي السنة والشهر للتجميع.

حين لا تكفي الأيام: ‏POSIXct وlubridate

لا يعرف Date مفهوم الساعات. وفي اللحظة التي تحمل فيها بياناتك طوابع زمنية، كمدخلات السجلات وقراءات المستشعرات و"تم الطلب في 14:32"، تحتاج إلى POSIXct، وهو صنف التاريخ والوقت في R: عدد الثواني منذ 1970 بدل الأيام، مع إدراك المناطق الزمنية.

كل شيء ينتقل معه: فرموز % نفسها (وتشمل الآن %H و%M و%S) تصلح للتحليل ولـ format()، ويعطي الطرح كائنات difftime، وتمثل Sys.time() "الآن". والعبء الجديد هو المنطقة الزمنية، فمرّر tz = صراحةً عند التحليل، لأن جلستين في منطقتين مختلفتين ستقرآن السلسلة نفسها لحظتين مختلفتين لولا ذلك. وقاوم تخزين البيانات التقويمية بصيغة POSIXct "تحسبًا"، فعيد ميلاد مخزَّن كمنتصف ليل في منطقة ما قد يُطبع اليوم السابق في منطقة أخرى، وهو خلل بائس فعلًا في تتبعه. الأيام الكاملة: Date. واللحظات: POSIXct.

وأخيرًا، حزمة lubridate هي الوجه الأودّ الذي تضعه معظم شيفرة tidyverse على كل ما سبق، وتستحق التبني بعد استيعاب آليات base:

library(lubridate)

ymd("2026-08-07")            # order-based parsing: no format string
mdy("08/07/2026")            # ...you just say which order the parts come in
dmy("7 August 2026")
floor_date(Sys.Date(), "month")   # snap to the start of the period

تستبدل ymd() وmdy() وdmy() بوصفات التنسيق تصريحًا بسيطًا بترتيب الأجزاء، وتحل floor_date() مسألة "جمّع هذه الطوابع الزمنية حسب الشهر" في استدعاء واحد. وتقوم lubridate على صنفَي Date/POSIXct نفسيهما في العمق، فهي مقود أفضل لا محرك مختلف.

الخلاصة

  • Date عدّاد أيام منذ 1970-01-01 مكسوّ بزي يجعله يُطبع كتاريخ، وتكشف unclass() عن الرقم.
  • تحلل as.Date("2026-08-07") صيغة ISO مباشرة، وأي صيغة أخرى تحتاج إلى وصفة format = من رموز %، والتحليل الفاشل يُرجع NA بصمت.
  • format(date, "...") هي العكس: الرموز نفسها لكنها تنتج سلاسل عرض.
  • يعطي الطرح كائن difftime، فحدّد units = صراحةً واستخدم as.numeric() قبل الحساب. وتضيف + n أيامًا، وللأشهر استخدم seq(by = "month").
  • تستخرج weekdays() وmonths() وصيغة as.integer(format(...)) الأجزاء، وكلها متجهية.
  • Date للأيام الكاملة، وPOSIXct (مع tz صريحة) للطوابع الزمنية، وlubridate تجعل كليهما أودّ.

في المستند التالي: ماذا تفعل حين يصرخ R في وجهك، أي قراءة رسائل الخطأ وتنقيحها بطريقة منهجية.

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

كيف تحوّل سلسلة نصية إلى تاريخ في R؟

باستخدام as.Date(). فإذا كانت السلسلة بصيغة ISO فالأمر يعمل مباشرة: as.Date("2026-08-07"). أما أي ترتيب آخر فيحتاج إلى وصفة format = مبنية من رموز %: ‏as.Date("07/08/2026", format = "%d/%m/%Y"). والتحليل الفاشل يُرجع NA لا خطأ، فتحقق من النتيجة.

كيف تحصل على تاريخ اليوم في R؟

تُرجع Sys.Date() تاريخ اليوم ككائن Date، وتُرجع Sys.time() التاريخ والوقت الحاليين ككائن POSIXct. وكلتاهما تعتمد على ساعة حاسوبك وإعدادات المنطقة الزمنية.

كيف تحسب الفرق بين تاريخين في R؟

اطرحهما: تعطي as.Date("2026-08-07") - as.Date("2026-01-01") كائن difftime بقيمة 218 يومًا. غلّفه بـ as.numeric() لاستخدام الرقم في الحسابات، أو استدعِ difftime(d1, d2, units = "weeks") لاختيار الوحدات بنفسك بدل ترك R يختارها.

ما الفرق بين Date وPOSIXct في R؟

يخزّن Date أيامًا كاملة (داخليًا: عدد الأيام منذ 1970-01-01) ولا يعرف شيئًا عن الساعات أو المناطق الزمنية. أما POSIXct فيخزّن لحظة زمنية (عدد الثواني منذ 1970) ويدرك المناطق الزمنية. استخدم Date للبيانات التقويمية مثل أعياد الميلاد والمواعيد النهائية، ولا تستخدم POSIXct إلا حين يهم وقت اليوم، كالطوابع الزمنية والسجلات.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن