انتقل إلى محتوى الدرس
الدرس 58
دورة PHP

حساب الفروق الزمنية والفترات والمناطق الزمنية في PHP 8PHP Date Intervals Date Diff and Timezone Conversions

احسب الفروق الزمنية بدقة، وأضف واطرح الفترات عبر DateTimeImmutable وDateInterval، وحوّل التوقيت بين المناطق الزمنية المختلفة في PHP 8.
أقسام الدرس
6
الأمثلة
6
اللغة
العربية
تاريخ النشر
غير محدد
المشاهدات
0
محتوى الدرس
في هذا الدرس 6تصفّح المواضيع

تخزن تطبيقات PHP الاحترافية الأوقات بالتوقيت العالمي UTC، ثم تحولها عند العرض إلى المنطقة الزمنية للمستخدم عبر timezone_open() وdate_timezone_set().

  • اضبط المنطقة الزمنية الافتراضية للسكريبت عند بدء التشغيل عبر date_default_timezone_set("UTC") وتحقق منها عبر date_default_timezone_get().
  • أنشئ كائن المنطقة الزمنية بالدالة timezone_open("Asia/Riyadh") ومرّره إلى date_create_immutable() أو date_timezone_set().
  • بما أن date_create_immutable() تنشئ تاريخاً غير قابل للتعديل المباشر، فإن date_timezone_set($dt, $tz) تُرجع نسخة جديدة محولة دون تغيير الأصل.

يتم تحويل اللحظة الزمنية نفسها (12:00 +00:00 بتوقيت UTC) بدقة إلى 15:00 +03:00 بتوقيت الرياض.

مخطط توضيحي: محاكي الفترات الزمنية وحساب الفروق والمناطق الزمنية في PHP
PHP
<?php
date_default_timezone_set('UTC');
$utc = date_create_immutable('2026-05-01 12:00:00', timezone_open('UTC'));
$riyadh = date_timezone_set($utc, timezone_open('Asia/Riyadh'));
echo "UTC: " . date_format($utc, 'H:i P') . "\n";
echo "Riyadh: " . date_format($riyadh, 'H:i P') . "\n";

تحول الدالة strtotime() العبارات الزمنية النسبية مثل "+2 weeks" أو "first day of next month" إلى طابع زمني بالثواني (Unix Timestamp).

  • مرّر طابعاً زمنياً مرجعياً كمعامل ثانٍ strtotime("+10 days", $baseTs) لجعل الحسابات النسبية ثابتة وقابلة للاختبار.
  • تُرجع strtotime() القيمة false إذا تعذر تحليل النص المدخل كتاريخ صالح.
  • انتبه لفرق الفاصل النصي: الصيغة بالشرطة المائلة "05/04/2026" تُفسر كـ شهر/يوم/سنة، بينما الشرطة العادية "05-04-2026" تُفسر كـ يوم-شهر-سنة.

بالاعتماد على تاريخ الأساس 2026-03-15، تعطي إضافة 14 يوماً التاريخ 2026-03-29، ويعطي أول يوم في الشهر التالي 2026-04-01.

PHP
<?php
date_default_timezone_set('UTC');
$base = strtotime('2026-03-15 00:00:00');
$trialEnd = strtotime('+14 days', $base);
$nextMonth = strtotime('first day of next month', $base);
echo "Trial ends: " . date('Y-m-d', $trialEnd) . "\n";
echo "Next billing: " . date('Y-m-d', $nextMonth) . "\n";

استخدم الدالة date_interval_create_from_date_string() مع date_add() وdate_sub() لإضافة أو طرح الفترات الزمنية دون التأثير على التاريخ الأصلي.

  • تبني الدالة date_interval_create_from_date_string("1 month + 5 days") فترة زمنية مهيكلة من عبارة واضحة.
  • عند تطبيقها عبر date_add($dt, $interval) على تاريخ غير قابل للتعديل، يبقى المتغير الأصلي $dt ثابتاً وتُرجع الدالة تاريخاً جديداً.
  • يمكنك أيضاً إزاحة التاريخ مباشرة عبر الدالة date_modify($dt, "+3 hours").

إضافة شهر و5 أيام إلى 2026-01-10 تعطي 2026-02-15، وطرح 3 أيام يحدد موعد التذكير في 2026-02-12.

PHP
<?php
date_default_timezone_set('UTC');
$issued = date_create_immutable('2026-01-10 09:00:00');
$span = date_interval_create_from_date_string('1 month + 5 days');
$due = date_add($issued, $span);
$reminder = date_sub($due, date_interval_create_from_date_string('3 days'));
echo "Issued: " . date_format($issued, 'Y-m-d') . " | Due: " . date_format($due, 'Y-m-d') . " | Remind: " . date_format($reminder, 'Y-m-d') . "\n";

لا تطرح الطوابع الزمنية وتقسمها على 86400 عبر الشهور المختلفة؛ بل اعتمد على date_diff($start, $end) لحساب الفروق التقويمية بدقة.

  • تُرجع date_diff($d1, $d2) كائن فترة يحتوي على الخصائص y (السنوات) وm (الشهور) وd (الأيام المتبقية) وإجمالي الأيام الكلي days.
  • تعطي الخاصية $diff->days إجمالي عدد الأيام الكلي بين التاريخين، بينما تعطي $diff->d الأيام المتبقية فقط بعد خصم الشهور الكاملة.
  • نسّق الفارق عبر date_interval_format($diff, "%R%a days") حيث يطبع %R الإشارة (+ أو -) ويطبع %a إجمالي الأيام.

بين 1 يناير و5 مارس 2026، تحسب date_diff() التفصيل التقويمي (2 months, 4 days) وإجمالي الأيام الكلي (63 days).

مخطط تدفق التنفيذ العملي لقسم حساب الفارق الدقيق بين تاريخين عبر diff في لغة PHP
PHP
<?php
date_default_timezone_set('UTC');
$start = date_create_immutable('2026-01-01');
$end = date_create_immutable('2026-03-05');
$diff = date_diff($start, $end);
$breakdown = date_interval_format($diff, '%m months, %d days');
echo "$breakdown (Total: " . $diff->days . " days)\n";

لتوليد تواريخ الفوترة الدورية أو المواعيد الأسبوعية المتكررة بين تاريخين، تقدم بخطوات ثابتة باستخدام تاريخ البداية والفترة الزمنية.

  • في PHP 8.2+ يمكن توليد السلاسل الزمنية المتكررة وفق صيغة التكرار القياسية ISO-8601 أو بالتقدم الدوري عبر فترة ثابتة.
  • في السكريبتات الإجرائية، يتيح تحريك المؤشر الزمني عبر date_add($cursor, $step) داخل حلقة for أو while توليد المواعيد الدورية بدقة.
  • تحافظ الفترات التقويمية مثل "7 days" أو "1 month" على ثبات الساعة المحلية حتى عند تغير التوقيت الصيفي.

بدءاً من 2026-04-01، تسجل كل دورة التاريخ المنسق وتُقدم المؤشر $cursor بمقدار 7 أيام.

PHP
<?php
date_default_timezone_set('UTC');
$cursor = date_create_immutable('2026-04-01');
$step = date_interval_create_from_date_string('7 days');
$slots = [];
for ($i = 0; $i < 4; $i++) {
    $slots[] = date_format($cursor, 'Y-m-d');
    $cursor = date_add($cursor, $step);
}
echo implode(' -> ', $slots) . "\n";

تبدأ نصوص الفترات القياسية ISO 8601 بالحرف P لوحدات التاريخ، وتستخدم الحرف T للفصل قبل وحدات الوقت (الساعات والدقائق والثواني).

  • انتبه للفرق الدقيق بين P1M (شهر واحد في قسم التاريخ) وPT1M (دقيقة واحدة بعد فاصل الوقت T).
  • في دالة التنسيق date_interval_format() تبدأ الرموز بالعلامة % مثل %y للسنوات و%m للشهور و%d للأيام و%a لإجمالي الأيام.
  • فضّل دائماً التواريخ غير القابلة للتعديل المباشر (date_create_immutable()) لمنع التعديل الجانبي غير المقصود على التواريخ المشتركة.

تنسق الدالة date_interval_format() الفارق الزمني بين التاريخين على صورة 2 days, 6 hrs, 30 mins.

رمز ISO 8601 / التنسيقالمعنىمثال عمليالخطأ الشائع
P1Y2M10D1 Year, 2 Months, 10 DaysDate period unitsMissing leading P
PT4H30M4 Hours, 30 MinutesTime units after TWriting P30M (30 months!) instead of PT30M
%a vs %dTotal days vs Remainder days63 vs 4Using %d when total days is needed
%RSign (+ or -)%R%a -> +63Forgetting to check if $diff->invert === 1

PHP
<?php
date_default_timezone_set('UTC');
$d1 = date_create_immutable('2026-06-01 08:00:00');
$d2 = date_create_immutable('2026-06-03 14:30:00');
$diff = date_diff($d1, $d2);
echo date_interval_format($diff, '%a days, %h hrs, %i mins') . "\n";
خلاصة المعرفة ومحطة الانتقال

ملخص الدرس

حصاد الدرس

مراجعة مركّزة لأهم المفاهيم والقواعد الهندسية التي أتقنتها في هذا الدرس قبل التطبيق العملي

ماذا تعلّمت في هذا الدرس؟

تبدأ نصوص الفترات القياسية ISO 8601 بالحرف P لوحدات التاريخ، وتستخدم الحرف T للفصل قبل وحدات الوقت (الساعات والدقائق والثواني). انتبه للفرق الدقيق بين P1M (شهر واحد في قسم التاريخ) وPT1M (دقيقة واحدة بعد فاصل الوقت T). في دالة التنسيق date_interval_format() تبدأ الرموز بالعلامة % مثل %y للسنوات و%m للشهور و%d للأيام و%a لإجمالي الأيام. فضّل دائماً التواريخ غير القابلة للتعديل المباشر (date_create_immutable()) لمنع التعديل الجانبي غير المقصود على التواريخ المشتركة.

مشاركة

هل كان هذا الدرس مفيدًا؟

جارٍ تحميل الآراء…

ابنِ لغتك البرمجية

المصطلحات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 Date Diff & Timezones الفروق والمناطق الزمنية
احسب الفروق الزمنية بدقة، وأضف واطرح الفترات عبر DateTimeImmutable وDateInterval، وحوّل التوقيت بين المناطق الزمنية المختلفة في PHP 8.
للمراجعة
02 Configuring Timezones with DateTimeZone ضبط وتحويل المناطق الزمنية عبر DateTimeZone
المفهوم الأساسي لقسم ضبط وتحويل المناطق الزمنية عبر DateTimeZone في لغة PHP الحديثة.
للمراجعة
03 Parsing Relative Dates with strtotime تحليل التواريخ النسبية والنصية بدالة strtotime
الصياغة البرمجية والتطبيق العملي المباشر لقسم تحليل التواريخ النسبية والنصية بدالة strtotime.
للمراجعة
04 Adding and Subtracting with DateInterval إضافة وطرح الفترات الزمنية بـ DateInterval
قواعد التحقق وأفضل الممارسات القياسية الخاصة بقسم إضافة وطرح الفترات الزمنية بـ DateInterval.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

حروف قليلة. معنى كامل.

الاختصارات4

راجع المعنى، اشرحه لنفسك، ثم علّم البطاقة كمفهومة.

0 / 4 مفهومةأول بطاقة، أول خطوة
01 PHP PHP
PHP: Hypertext Preprocessor
لغة البرمجة النصية على جانب الخادم لبناء تطبيقات الويب الديناميكية وواجهات البرمجة.
للمراجعة
02 CLI CLI
Command-Line Interface
واجهة سطر الأوامر التي تتيح تشغيل ملفات PHP مباشرة عبر الطرفية.
للمراجعة
03 FPM FPM
FastCGI Process Manager
مدير عمليات FastCGI عالي الأداء لمعالجة طلبات خادم الويب في PHP.
للمراجعة
04 HTML HTML
HyperText Markup Language
لغة الترميز القياسية التي يولدها محرك PHP ويرسلها إلى متصفح العميل بعد التنفيذ.
للمراجعة

اقرأ البطاقات بحرية. سجّل الدخول لحفظ تقدم مراجعتك.

من الفهم للتطبيق

مهامك قبل الاختبار

خطوة صغيرة كل مرة. وإنجاز تقدر ترجع له.

0/2مهام منجزة
  1. أنشئ ملف PHP محلياً ونفّذ المثال البرمجي المشروح في قسم ضبط وتحويل المناطق الزمنية عبر DateTimeZone للتحقق من المخرجات.

  2. بدّل بين الحالات الثلاث في المحاكي التفاعلي ضمن قسم تحليل التواريخ النسبية والنصية بدالة strtotime وقارن مخرجات التنفيذ.

تأشير المهمة إقرار منك بإتمامها، وليس تصحيحًا آليًا للكود. يُحفظ تقدمك في حسابك.

مساحة التحدي

اختبر فهمك.
ووصلها للإتقان.

كل سؤال خطوة لقدّام. اختار، اكتب كود، وشوف نتيجتك فورًا.

8أسئلة 1أنواع تحديات 100%هدف الإتقان
تصحيح تلقائي. فرص بلا حدود.

أكمل المهام، واجمع كل الإجابات الصحيحة. أقل من 100%؟ راجع وأعد المحاولة.

الأسئلة متاحة للاطلاع. سجّل الدخول للتفاعل وحفظ تقدمك.

لمحة عن التحدي8 أسئلة تنتظرك
01

لماذا يجب تخزين الأوقات في قاعدة البيانات بتوقيت UTC وتحويلها للمنطقة الزمنية المحلية عند العرض فقط؟

توقيت UTC ثابت عالمياً ولا يتغير بالتوقيت الصيفي مما يضمن دقة الترتيب والحسابات.

02

ما الميزة الجوهرية للدالة date_create_immutable() مقارنةً بـ date_create() عند استدعاء date_add() أو date_timezone_set()؟

عدم القابلية للتعديل يمنع الأخطاء الجانبية الخفية عند تمرير التواريخ بين أجزاء الكود.

03

في نتيجة الدالة date_diff($d1, $d2)، ما الفرق بين الخاصية $diff->days والخاصية $diff->d؟

في فترة شهرين و4 أيام، تكون $diff->days مساوية لـ 63 بينما $diff->d تساوي 4 فقط.

04

في صيغة الفترات القياسية ISO 8601، ما الفرق بين "P5M" و"PT5M"؟

حرف M قبل T يرمز للشهور، وبعد فاصل الوقت T يرمز للدقائق.

05

ماذا تُرجع الدالة strtotime("invalid date text") عند تمرير نص لا يمثل تاريخاً صالحاً؟

تُرجع الدالة strtotime() القيمة false عند فشل التحليل.

06

أي رمز تنسيق في دالة date_interval_format() يطبع إجمالي عدد الأيام الكلي بين تاريخين؟

يطبع الرمز %a إجمالي عدد الأيام الكلي المحسوب عبر date_diff().

07

كيف تفسر الدالة strtotime() التاريخ "10/04/2026" (بالشرطة المائلة) مقابل "10-04-2026" (بالشرطة العادية)؟

تعتمد strtotime() على نوع الفاصل، ولذلك يُنصح دائماً بصيغة ISO القياسية YYYY-MM-DD.

08

ما الدالة التي تضبط المنطقة الزمنية الافتراضية لجميع دوال التاريخ والوقت في السكريبت الحالي؟

تضبط date_default_timezone_set() المنطقة الزمنية الافتراضية وقت التشغيل.