PHP « php алгоритм нахождения пересечений дат

есть 2 даты
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .php.geshi_code {font-family:monospace;} .php.geshi_code .imp {font-weight: bold; color: red;} .php.geshi_code .kw1 {color: #b1b100;} .php.geshi_code .kw2 {color: #000000; font-weight: bold;} .php.geshi_code .kw3 {color: #990000;} .php.geshi_code .co1 {color: #666666; font-style: italic;} .php.geshi_code .co2 {color: #666666; font-style: italic;} .php.geshi_code .co3 {color: #0000cc; font-style: italic;} .php.geshi_code .co4 {color: #009933; font-style: italic;} .php.geshi_code .coMULTI {color: #666666; font-style: italic;} .php.geshi_code .es0 {color: #000099; font-weight: bold;} .php.geshi_code .es1 {color: #000099; font-weight: bold;} .php.geshi_code .es2 {color: #660099; font-weight: bold;} .php.geshi_code .es3 {color: #660099; font-weight: bold;} .php.geshi_code .es4 {color: #006699; font-weight: bold;} .php.geshi_code .es5 {color: #006699; font-weight: bold; font-style: italic;} .php.geshi_code .es6 {color: #009933; font-weight: bold;} .php.geshi_code .es_h {color: #000099; font-weight: bold;} .php.geshi_code .br0 {color: #009900;} .php.geshi_code .sy0 {color: #339933;} .php.geshi_code .sy1 {color: #000000; font-weight: bold;} .php.geshi_code .st0 {color: #0000ff;} .php.geshi_code .st_h {color: #0000ff;} .php.geshi_code .nu0 {color: #cc66cc;} .php.geshi_code .nu8 {color: #208080;} .php.geshi_code .nu12 {color: #208080;} .php.geshi_code .nu19 {color:#800080;} .php.geshi_code .me1 {color: #004000;} .php.geshi_code .me2 {color: #004000;} .php.geshi_code .re0 {color: #000088;} .php.geshi_code span.xtra { display:block; }

$start = '2010-08-11 11:13:33';
$end = '2010-08-13 14:12:11';
 

За каждый час платят 100 рублей, но есть бонусные часы, например во вторник и среду с 22.00 - 06.00 в который платят 200 рублей.
В общем на основании этих дат(start и end) нужно посчитать зарплату за смену.

p.s. не прощу прям кода, можно словами как находить бонусные пересечения.

1 ответов



<?php
$start = '2010-08-10 21:13:33';
$end = '2010-08-13 22:12:11';
//задаем массив бонусных часов
//WARNING: периоды содержащие полночь задавать так : с 00:00 до 02:00 и с 23:00 до 24:00
$days_find = array(
                    array(2, 20, 22),//вторник, с 20:00 до 22:00
                    array(4, 19, 20),//четверг, с 19:00 до 20:00
                    array(5, 19, 20) //пятница, с 19:00 до 20:00
                    );
$result_days = 0;   //найдено бонусных дней
$result_hours = 0;  //найдено бонусных часов

$timestamp_start = strtotime($start);
$timestamp_end = strtotime($end);
$day_start = date('N', $timestamp_start);//определяем день недели по дате (1-Пн, 2-Вт.....7-Вс)
$day_end = date('N', $timestamp_end);
$hour_start = date('G', $timestamp_start);//определяем часы
$hour_end = date('G', $timestamp_end);

//проверяем содержат ли первый и последний дни бонусные часы
foreach($days_find as $day)
{
    if($day_end == $day[0])
    {
        $result_days++;
        //если 22:12:11 попадает в бонусные часы
        if($hour_end < $day[2] && $hour_end > $day[1])
                $result_hours += $day[2]-$hour_end;
        //если 22:12:11 полностью включает в себя бонусные часы
        elseif($hour_end >= $day[2])
            $result_hours += $day[2]-$day[1];
    }
    if($day_start == $day[0] && $day_start != $day_end)
    {
        $result_days++;
        if($hour_start < $day[2] && $hour_start > $day[1])
                $result_hours += $day[2]-$hour_start;
        elseif($hour_start <= $day[1])
            $result_hours += $day[2]-$day[1];
    }
}

//считаем кол-во дней в заданном периоде
$all_days = floor(($timestamp_end - $timestamp_start)/(24*60*60));
//период больше недели
if($all_days > 7)
{
    foreach($days_find as $day)
    {
        if($day_start < $day[0] && $day_end > $day[0])
        {
            $result_hours += $day[2]-$day[1];
            $result_days++;
        }
        $hour += $day[2]-$day[1];   //подсчитываем все бонусные часы, дабы потом их умножить на кол-во полных недель
    }
    $result_hours += floor($all_days/7)*$hour;
    $result_days += floor($all_days/7)*count($days_find);
}
//период меньше недели
elseif($all_days != 0)
{
    //период состоит из 2х недель
    if($day_end <= $day_start)
    {
         foreach ($days_find as $day)
            if($day[0] > $day_start)
            {
                $result_days++;
                $result_hours += $day[2]-$day[1];
            }
    }
    //период состоит из одной недели
    else
    {
        foreach($days_find as $day)
            if($day[0] < $day_end && $day[0] > $day_start)
            {
                $result_days++;
                $result_hours += $day[2]-$day[1];
            }
    }
}

echo 'day_start = '.$day_start.'
'
;
echo 'day_end = '.$day_end.'
'
;
echo 'all_days = '.$all_days.'
'
;
echo 'result_days = '.$result_days.'
'
;
echo 'result_hours = '.$result_hours.'
'
;
?>