سؤال

كيف تؤدي في الواقع datetime العمليات مثل إضافة تاريخ العثور على الفرق ، معرفة كم عدد أيام باستثناء عطلة نهاية الأسبوع في فترة?أنا شخصيا بدأت لتمرير بعض هذه العمليات إلى كيو dbms كما عادة سوف تحتاج فقط إلى مسألة واحدة sql للحصول على إجابة ، ومع ذلك ، على أن تفعل ذلك في PHP الطريقة أود أن أكتب الكثير من رمز هذا يعني المزيد من فرص الأخطاء أن تحدث...

هل هناك أي المكتبات في PHP التي لا datetime العملية بطريقة لا تتطلب الكثير من الرموز ؟ أن يدق sql في الحالة التي تكون فيها 'نظرا تاريخين كم يوم عمل هناك بين اثنين من التواريخ ؟ تنفيذ في أي SQL, أو $pet_lang' التي يتم حلها من خلال جعل هذا الاستعلام?

SELECT  COUNT(*) AS total_days
FROM    (SELECT date '2008-8-26' + generate_series(0,
          (date '2008-9-1' - date '2008-8-26')) AS all_days) AS calendar
WHERE   EXTRACT(isodow FROM all_days) < 6;
هل كانت مفيدة؟

المحلول

PHP5+'s DateTime كائن مفيد لأنه هو قفزة الوقت ، التوقيت الصيفي علم ، ولكنه يحتاج إلى بعض الإرشاد حقا حل مشكلة.كتبت التالية لحل مشكلة مماثلة.على find_WeekdaysFromThisTo() أسلوب القوة الغاشمة ، لكنه يعمل بسرعة معقولة إذا كان لديك فترة زمنية أقل من 2 سنوات.

$tryme = new Extended_DateTime('2007-8-26');
$newer = new Extended_DateTime('2008-9-1');

print 'Weekdays From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_WeekdaysFromThisTo($newer) ."\n";
/*  Output:  Weekdays From 2007-08-26 To 2008-09-01: 265  */
print 'All Days From '.$tryme->format('Y-m-d').' To '.$newer->format('Y-m-d').': '.$tryme -> find_AllDaysFromThisTo($newer) ."\n";
/*  Output:  All Days From 2007-08-26 To 2008-09-01: 371   */
$timefrom = $tryme->find_TimeFromThisTo($newer);
print 'Between '.$tryme->format('Y-m-d').' and '.$newer->format('Y-m-d').' there are '.
      $timefrom['years'].' years, '.$timefrom['months'].' months, and '.$timefrom['days'].
      ' days.'."\n";
/*  Output: Between 2007-08-26 and 2008-09-01 there are 1 years, 0 months, and 5 days. */

class Extended_DateTime extends DateTime {

    public function find_TimeFromThisTo($newer) {
        $timefrom = array('years'=>0,'months'=>0,'days'=>0);

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $timefrom['years'] = $this->find_YearsFromThisTo($testnewer);
        $mod = '-'.$timefrom['years'].' years';
        $testnewer -> modify($mod);

        $timefrom['months'] = $this->find_MonthsFromThisTo($testnewer);
        $mod = '-'.$timefrom['months'].' months';
        $testnewer -> modify($mod);

        $timefrom['days'] = $this->find_AllDaysFromThisTo($testnewer);
        return $timefrom;
    } // end function find_TimeFromThisTo


    public function find_YearsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;
        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;

        $testnewer -> modify ('-1 year');
        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 year');
        }
        return $count;
    } // end function find_YearsFromThisTo


    public function find_MonthsFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 month');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 month');
        }
        return $count;
    } // end function find_MonthsFromThisTo


    public function find_AllDaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;
        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_AllDaysFromThisTo


    public function find_WeekdaysFromThisTo($newer) {
        /*
        If the passed is:
        not an object, not of class DateTime or one of its children,
        or not larger (after) $this
        return false
        */
        if (!is_object($newer) || !($newer instanceof DateTime) || $newer->format('U') < $this->format('U'))
            return FALSE;

        $count = 0;

        // Clone because we're using modify(), which will destroy the object that was passed in by reference
        $testnewer = clone $newer;
        $testnewer -> modify ('-1 day');

        while ( $this->format('U') < $testnewer->format('U')) {
            // If the calculated day is not Sunday or Saturday, count this day
            if ($testnewer->format('w') != '0' && $testnewer->format('w') != '6')
                $count ++;
            $testnewer -> modify ('-1 day');
        }
        return $count;
    } // end function find_WeekdaysFromThisTo

    public function set_Day($newday) {
        if (is_int($newday) && $newday > 0 && $newday < 32 && checkdate($this->format('m'),$newday,$this->format('Y')))
            $this->setDate($this->format('Y'),$this->format('m'),$newday);
    } // end function set_Day


    public function set_Month($newmonth) {
        if (is_int($newmonth) && $newmonth > 0 && $newmonth < 13)
            $this->setDate($this->format('Y'),$newmonth,$this->format('d'));
    } // end function set_Month


    public function set_Year($newyear) {
        if (is_int($newyear) && $newyear > 0)
            $this->setDate($newyear,$this->format('m'),$this->format('d'));
    } // end function set_Year
} // end class Extended_DateTime

نصائح أخرى

في حين أن معظم التاريخ والوقت العمليات عادة تحويل إلى Unixtime وأداء الطرح.... الخعلى Unixtime صحيح, قد ترغب في النظر في الإطار زند Zend_Date الدرجة.

هذه لديها الكثير من الوظائف يمكنك وصف.على الرغم من زند وصفت بأنها "إطار" انه يعمل بشكل جيد للغاية كما مكتبة فئة لاختيار واختار العناصر.نحن عادة تدرج في المشاريع و من ثم سحب في بت عندما كنا في حاجة إليها.

strtotime() مفيد ولكن لديها بعض السلوكيات الفردية التي يمكن المنبثقة من وقت لآخر إذا كنت لا تستخدم فقط إلى تحويل تنسيق التاريخ/الوقت على السلسلة.

أشياء مثل "+1 الشهر" أو "-3 أيام" يمكن في بعض الأحيان لا تعطيك ما كنت تتوقع أن الإخراج.

إضافة تاريخ ، يمكنك استخدام الأسلوب التاريخ والوقت::إضافة (يضيف مبلغ من الأيام والشهور والسنوات ساعات والدقائق والثواني إلى التاريخ والوقت كائن) ، متاح php 5.3.0 فصاعدا.

إلى العثور على الفرق بين تاريخين ، هناك التاريخ والوقت::مهرجان دبي السينمائي الدولي الأسلوب ؛ ولكن هناك لا يبدو أن طريقة احتساب أيام العمل بين تاريخين.

PEAR::Date يبدو أنه قد يكون بعض وظائف مفيدة.

PEAR::Calendar قد يكون من المفيد أيضا.

أسهل طريقة هي استخدام الطابع الزمني يمثل عدد الثواني منذ 1 كانون الثاني / يناير 2008.مع الطابع الزمني نوع, يمكنك أن تفعل أشياء مثل...

now = time();
tomorrow = now + 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds

تحقق من وثائق الوقت(), تاريخ() و mktime() على php صفحات الويب.هذه هي الطرق الثلاث التي أنا أميل إلى استخدام معظم الأحيان.

يمكنك استخدام مزيج من strtotime, mktime و تاريخ todo الحسابي

هنا هو مثال الذي يستخدم السرد todo بعض العمليات الحسابية http://rushi.wordpress.com/2008/04/13/php-print-out-age-of-date-in-words/ سوف تتكاثر رمز هنا عن البساطة

if ($timestamp_diff < (60*60*24*7)) {
   echo floor($timestamp_diff/60/60/24)." Days";
} elseif ($timestamp_diff > (60*60*24*7*4)) {
   echo floor($timestamp_diff/60/60/24/7)." Weeks";
} else {
   $total_months = $months = floor($timestamp_diff/60/60/24/30);
   if($months >= 12) {
      $months = ($total_months % 12);
      $years&nbsp; = ($total_months - $months)/12;
      echo $years . " Years ";
   }
   if($months > 0)
      echo $months . " Months";
}
?>

@Rushi أنا لا أحب strtotime() شخصيا..أنا لا أعرف لماذا لكني اكتشفت هذا الصباح أن تمر سلسلة مثل هذا 2008-09-11 الساعة 9:5 صباحا إلى strtotime بإرجاع false...

لا أعتقد أن القانون الذي قدمته حل المثال المشكلة نظرا تاريخين كم يوم عمل هناك بين اثنين من التواريخ ؟ تنفيذ في أي SQL, أو $pet_lang' و لم تنظر إذا كان لدي قائمة من عطلة عامة...

يمكنك الحصول على عدد الأيام بين تاريخين مثل هذا:

$days = (strtotime("2008-09-10") - strtotime("2008-09-12")) / (60 * 60 * 24);

و يمكنك جعل وظيفة شيء مثل هذا (ليس لدي php المثبتة في الكمبيوتر الخاص بك في العمل لذلك أنا لا يمكن أن تضمن بناء الجملة هو الصحيح 100%)

function isWorkDay($date)
{
 // check if workday and return true if so
}

function numberOfWorkDays($startdate, $enddate)
{
  $workdays = 0;
  $tmp = strtotime($startdate);
  $end = strtotime($enddate);
  while($tmp <= $end)
  {
    if ( isWorkDay( date("Y-m-d",$tmp) ) ) $workdays++;
    $tmp += 60*60*24;
  }
  return $workdays;
}

إذا كنت لا تحب strtotime و دائما يكون لديك موعد في نفس الشكل يمكنك استخدام تنفجر وظيفة مثل

list($year, $month, day) = explode("-", $date);

وأود أن نوصي بشدة باستخدام PHP 5.2 هو التاريخ والوقت الكائنات, بدلا من استخدام الطوابع يونيكس ، عندما تفعل حسابات التاريخ.عند استخدام PHP تاريخ وظائف عودة الطوابع يونيكس, لديك مجموعة محدودة جدا للعمل مع (مثلا ، لا شيء قبل عام 1970).

إذا كان لديك نظرة على http://php.net/date سوف تجد بعض الأمثلة على استخدام mktime() لتنفيذ عمليات.

مثال بسيط سيكون تمرين الغد ما تاريخ.يمكنك القيام بذلك ببساطة عن طريق إضافة 1 إلى يوم القيمة في mktime() على النحو التالي:

$tomorrow = date("Y-m-d", mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")));

حتى هنا, سوف تتلقى التاريخ في شكل YYYY-MM-DD تحتوي الغد تاريخ.يمكنك أيضا طرح أيام ببساطة عن طريق استبدال '+' مع '-'. mktime() يجعل الحياة أسهل و يوفر لك من الاضطرار إلى القيام عبارات if المتداخلة وغيرها من مثل هذه مزعجة الترميز.

للحصول على العمل أيام العطل كيو CTE ftw -- انظر http://osssmb.wordpress.com/2009/12/02/business-days-working-days-sql-for-postgres-2/

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top