اذهب إلى المحتوى

التعامل مع الوقت والتاريخ في PHP


سارة محمد2

الصنف Datetime

إنشاء نسخة Datetime ثابتة من متغير

يمكنك استخدام الشيفرة التالية لإنشاء ‎\DateTimeImmutable‎ في PHP الإصدار 5.6 وما بعده:

\DateTimeImmutable::createFromMutable($concrete);

أما في الإصدارات السابقة يمكنك استخدام:

\DateTimeImmutable::createFromFormat(\DateTime::ISO8601, $mutable->format(\DateTime::ISO8601), $mutable->getTimezone());

إضافة أو طرح تاريخ

نستخدم الصنف DateInterval لإضافة أو طرح فترة زمنية في كائن DateTime، إليك المثال التالي الذي نطرح فيه 7 أيام ونطبع رسالة على الشاشة:

// التعليمة التالية بدون وسيط تُرجع التاريخ الحالي
$now = new DateTime();

// الكائن التالي يمثل فترة زمنية مدتها 7 أيام
$interval = new DateInterval('P7D');

// DateTime التعليمة التالية ستُرجع كائن 
$lastDay = $now->add($interval);

// ويُرجع سلسلة نصية DateTime ينسّق هذا التابع كائن
$formatedLastDay = $lastDay->format('Y-m-d');
echo "Samara says: Seven Days. You'll be happy on $formatedLastDay.";

/*
عند تنفيذ هذه الشيفرة في 1-8-2016 يكون الخرج
Samara says: Seven Days. You'll be happy on 2016-08-08.
*/

نستطيع استخدام التابع الفرعي بطريقة مشابهة لطرح التواريخ:

$now->sub($interval);
echo "Samara says: Seven Days. You were happy last on $formatedLastDay.";

/*
عند تنفيذ هذه الشيفرة في 1-8-2016 يكون الخرج
Samara says: Seven Days. You were happy last on 2016-07-25.
*/

getTimestamp

getTimeStemp هو تمثيل unix لكائن من الصنف datetime.

$date = new DateTime();
echo $date->getTimestamp();

سيؤدي ذلك إلى وضع مؤشر صحيح للثواني التي انقضت منذ 00:00:00 UTC، الخميس، 1 كانون الثاني 1970.

setDate

تضبط هذه الدالة التاريخ لكائن من الصنف datetime.

$date = new DateTime();
$date->setDate(2016, 7, 25);

تضبط هذه الشيفرة التاريخ ليصبح 25 تموز، 2015 وخرجها:

2016-07-25 17:52:15.819442

إنشاء DateTime من تنسيق معين

إنّ PHP قادرة على تحليل عدة تنسيقات للتاريخ، يمكنك استخدام التابع الساكن DateTime::createFromFormat إذا أردت تحليل تنسيق غير معياري أو إذا أردت أن تحدد في شيفرتك تنسيق التاريخ المُستخدم بشكلٍ صريح:

نمط كائني التوجه

$format = "Y,m,d";
$time = "2009,2,26";
$date = DateTime::createFromFormat($format, $time);

نمط إجرائي

$format = "Y,m,d";
$time = "2009,2,26";
$date = date_create_from_format($format, $time);

طباعة DateTime

توفر PHP من الإصدار 4 وما بعده تابع تنسيق كائني التوجه يحول كائن DateTime إلى سلسلة نصية بالتنسيق الذي تريده:

public string DateTime::format ( string $format )

تأخذ الدالة date()‎ معاملًا واحدًا format بشكل سلسلة نصية ويستخدم محارف مفردة لتعريف التنسيق:

  • Y: أربعة أرقام تمثل السنة (2016 مثلًا).
  • y: رقمين يمثلان السنة (16 مثلًا).
  • m: يمثّل الشهر بتنسيق رقم (من 01 إلى 12).
  • M: يمثّل الشهر بثلاثة أحرف (مثل …Jan, Feb, Mar).
  • j: يمثّل يوم في الشهر دون أصفار بادئة (من 1 إلى 31).
  • D: يمثّل يوم في الأسبوع بثلاثة أحرف (مثل …Mon, Tue, Wed).
  • h: يمثّل الساعة بتنسيق 12-ساعة (01 إلى 12).
  • H: يمثّل الساعة بتنسيق 24-ساعة (00 إلى 23).
  • A: إما AM أو PM.
  • i: يمثّل الدقائق دون أصفار بادئة (من 00 إلى 59).
  • s: يمثّل الثواني دون أصفار بادئة (من 00 إلى 59).
  • يمكنك الاطلاع على اللائحة الكاملة هنا.

الاستخدام يمكن استخدام هذه المحارف في تركيبات مختلفة لعرض الوقت بأي تنسيق تريده، إليك بعض الأمثلة:

$date = new DateTime('2000-05-26T13:30:20'); 
/* Friday, May 26, 2000 at 1:30:20 PM */

$date->format("H:i");
/* 13:30 */

$date->format("H i s");
/* 13 30 20 */

$date->format("h:i:s A");
/* 01:30:20 PM */

$date->format("j/m/Y");
/* 26/05/2000 */

$date->format("D, M j 'y - h:i A");
/* Fri, May 26 '00 - 01:30 PM */

التنسيق الكائني التوجه:

$date->format($format)

التنسيق الإجرائي المشابه:

date_format($date, $format)

الحصول على الفرق بين تاريخين/وقتين

يعدّ استخدام الصنف DateTime الطريقة الأكثر عمليّة لنحصل على الفرق بين تاريخين أو وقتين، مثال:

<?php
// DateTime إنشاء كائن من الصنف
$twoYearsAgo = new DateTime("2014-01-18 20:05:56");

// DateTime إنشاء كائن ثاني من الصنف
$now = new DateTime("2016-07-21 02:55:07");

// حساب الفرق
$diff = $now->diff($twoYearsAgo);

// فرق السنوات بين التاريخين $diff->y يحتوي
$yearsDiff = $diff->y;

// فرق الدقائق بين التاريخين $diff->m يحتوي
$monthsDiff = $diff->m;

// فرق الأيام بين التاريخين $diff->d يحتوي
$daysDiff = $diff->d;

// فرق الساعات بين التاريخين $diff->h يحتوي
$hoursDiff = $diff->h;

// فرق الدقائق بين التاريخين $diff->i يحتوي
$minsDiff = $diff->i;

// فرق الثواني بين التاريخين $diff->s يحتوي
$secondsDiff = $diff->s;

// فرق الأيام بين التاريخين $diff->days يحتوي
$totalDaysDiff = $diff->days;

// $diff استخلاص معلومات المتغير
var_dump($diff);

يمكننا أيضًا استخدام عوامل الموازنة للموازنة بين تاريخين بشكلٍ أسهل:

<?php
// DateTime إنشاء كائن من الصنف
$twoYearsAgo = new DateTime("2014-01-18 20:05:56");

// DateTime إنشاء كائن ثاني من الصنف
$now = new DateTime("2016-07-21 02:55:07");

var_dump($now > $twoYearsAgo); 
// bool(true)

var_dump($twoYearsAgo > $now); 
// bool(false)

var_dump($twoYearsAgo <= $twoYearsAgo);
 // bool(true)

var_dump($now == $now); 
// bool(true)

تغيير التاريخ إلى تنسيق آخر

أسهل طريقة لتغيير تنسيق التاريخ إلى تنسيق آخر هي استخدام strtotime()‎ مع date()‎، إذ أنّ strtotime()‎ ستغير التاريخ إلى تنسيق الختم الزمني unix ثمّ يُمرَّر إلى date()‎ لتغييره إلى تنسيق جديد.

$timestamp = strtotime('2008-07-01T22:35:17.02');
$new_date_format = date('Y-m-d H:i:s', $timestamp);

يمكن كتابة الشيفرة السابقة بسطرٍ واحد:

$new_date_format = date('Y-m-d H:i:s', strtotime('2008-07-01T22:35:17.02'));

تذكّر أنّ الدالة strtotime()‎ تحتاج أن يكون التاريخ بتنسيقٍ صالح وإلا ستُرجع false وتصبح قيمة التاريخ 1969-12-31.

استخدام DateTime()‎

توفر PHP بدءًا من الإصدار 5.2 الصنف DateTime()‎ الذي يمنح أدوات قوية للعمل مع التاريخ والوقت، يمكننا استخدامه لكتابة الشيفرة السابقة كالتالي:

$date = new DateTime('2008-07-01T22:35:17.02');
$new_date_format = $date->format('Y-m-d H:i:s');

العمل مع الأختام الزمنية unix

تأخذ الدالة date()‎ معاملها الثاني بصيغة ختم زمني unix وتُرجع تاريخ منسّق:

$new_date_format = date('Y-m-d H:i:s', '1234567890');

يعمل DateTime()‎ مع الختم الزمني unix بإضافة @ قبل الختم الزمني:

$date = new DateTime('@1234567890');
$new_date_format = $date->format('Y-m-d H:i:s');

إذا كان الختم الزمني لديك مقدّر بأجزاء الثانية (قد تكون نهايته 000 و/أو يتكون من 13 محرف) ستحتاج أن تحوّله إلى الثواني قبل أن تستطيع تغيير تنسيقه، يوجد طريقتين للقيام بذلك:

  • حذف آخر 3 أرقام باستخدام substr()‎: يمكن حذف الأرقام الثلاثة الأخيرة بعدة طرق لكن أسهلها استخدام substr()‎:
$timestamp = substr('1234567899000', -3);
  • القسمة على 1000: يمكنك أيضًا تحويل الختم الزمني إلى الثواني عن طريق القسمة على 1000، يمكنك استخدام المكتبة BCMath للقيام بالعمليات الرياضية كسلاسل نصية لأنّ الختم الزمني كبير جدًا على أنظمة 32 بت:
$timestamp = bcdiv('1234567899000', '1000');

يمكنك استخدام strtotime()‎ للحصول على ختم زمني unix:

$timestamp = strtotime('1973-04-18');

يمكنك استخدام DateTime::getTimestamp()‎ مع DateTime()‎:

$date = new DateTime('2008-07-01T22:35:17.02');
$timestamp = $date->getTimestamp();

يمكنك بدلًا من ذلك استخدام خيار التنسيق U إذا كنت تستخدم الإصدار PHP 5.2:

$date = new DateTime('2008-07-01T22:35:17.02');
$timestamp = $date->format('U');

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

لسوء الحظ ليست كل التواريخ التي يحتاج المطور أن يتعامل معها تكون منسّقة بطريقة معيارية، لكن لحسن الحظ وفرت PHP 5.3 حلًّا لذلك، تسمح لنا DateTime::createFromFormat()‎ بأن نخبر PHP عن تنسيق التاريخ لذا يمكن تحليلها بنجاح إلى كائن DateTime لمزيد من المعالجة.

$date = DateTime::createFromFormat('F-d-Y h:i A', 'April-18-1973 9:48 AM');
$new_date_format = $date->format('Y-m-d H:i:s');

أعطتنا PHP 5.4 قابلة الوصول إلى عنصر في الصنف عند إنشاء نسخة مما يسمح لنا أن نكتب الشيفرة السابقة في سطر واحد:

$new_date_format = (new DateTime('2008-07-01T22:35:17.02'))->format('Y-m-d H:i:s');

لكن هذا لا يعمل مع DateTime::createFromFormat()‎ بعد.

تحليل وصف التاريخ باللغة الانكليزية إلى تنسيق تاريخ

يمكن تحليل نصوص مختلفة باللغة الانكليزية إلى تواريخ باستخدام الدالتين strtotime()‎ وdate()‎ معًا.‍

// طباعة التاريخ الحالي
echo date("m/d/Y", strtotime("now")), "\n"; 

// m/d/Y طباعة تاريخ 10 أيلول، 2000 بالتنسيق
echo date("m/d/Y", strtotime("10 September 2000")), "\n";

// طباعة تاريخ الأمس
echo date("m/d/Y", strtotime("-1 day")), "\n";

// طباعة نتيجة تاريخ اليوم + أسبوع
echo date("m/d/Y", strtotime("+1 week")), "\n";

// طباعة نتيجة تاريخ اليوم + أسبوع ويومين و4 ساعات وثانيتين

echo date("m/d/Y", strtotime("+1 week 2 days 4 hours 2 seconds")), "\n";

// طباعة تاريخ يوم الخميس القادم
echo date("m/d/Y", strtotime("next Thursday")), "\n";

// طباعة تاريخ الاثنين الماضي
echo date("m/d/Y", strtotime("last Monday")), "\n";

// طباعة تاريخ اليوم الأول من الشهر القادم
echo date("m/d/Y", strtotime("First day of next month")), "\n";

// طباعة تاريخ اليوم الأخير من الشهر القادم
echo date("m/d/Y", strtotime("Last day of next month")), "\n";

// طباعة تاريخ اليوم الأول من الشهر الماضي
echo date("m/d/Y", strtotime("First day of last month")), "\n";

// طباعة تاريخ اليوم الأخير من الشهر الماضي 
echo date("m/d/Y", strtotime("Last day of last month")), "\n";

استخدام ثوابت معرّفة مسبقًا لتنسيق التاريخ

بدءًا من الإصدار PHP 5.1.0 يمكننا استخدام ثوابت معرّفة مسبقًا لتنسيق التاريخ في الدالة date()‎ بدلًا من السلاسل النصية.

ثوابت تنسيق التاريخ المعرّفة مسبقًا المتاحة:

DATE_ATOM
// (2016-07-22T14:50:01+00:00) (ATOM) الذرة 

DATE_COOKIE
// ‏(Friday, 22-Jul-16 14:50:01 UTC) HTTP ملفات تعريف الارتباط

DATE_RSS
// (Fri, 22 Jul 2016 14:50:01 +0000) ‏RSS

DATE_W3C
// (2016-07-22T14:50:01+00:00) اتحاد شبكة الويب العالمية

DATE_ISO8601
// ‏(2016-07-22T14:50:01+0000) ISO-8601

DATE_RFC822
// (Fri, 22 Jul 16 14:50:01 +0000) RFC 822

DATE_RFC850
// ‏(Friday, 22-Jul-16 14:50:01 UTC) RFC 850

DATE_RFC1036
// ‏(Fri, 22 Jul 16 14:50:01 +0000) RFC 1036

DATE_RFC1123
// ‏(Fri, 22 Jul 2016 14:50:01 +0000) RFC 1123

DATE_RFC2822
// (Fri, 22 Jul 2016 14:50:01 +0000) RFC 2822

DATE_RFC3339
// ‏(2016-07-22T14:50:01+00:00) DATE_ATOM ‏‏نفس

أمثلة:

echo date(DATE_RFC822);
// Fri, 22 Jul 16 14:50:01 +0000

echo date(DATE_ATOM,mktime(0,0,0,8,15,1947));
// 1947-08-15T00:00:00+05:30

ترجمة -وبتصرف- للفصول [Datetime Class - Working with Dates and Time] من كتاب PHP Notes for Professionals book

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

شكرا على هذه المقالة الجميلة والممتعة في قراءتها.

أرغب في هذا السياق أن أشير إلى النسخ العربية من دوال date و mktime و strtotime والمتاحة ضمن مكتبة Ar-PHP التي تتيح للمطور التعامل التواريخ الهجرية والأسماء العربية للأيام والأشهر بأكثر من صيغة شائعة في المشرق أو المغرب العربي.

رابط هذا التعليق
شارك على الشبكات الإجتماعية



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...