Работа с датами

Discussion in 'PHP' started by -=Zhenek=-, 5 Jan 2012.

  1. -=Zhenek=-

    -=Zhenek=- Elder - Старейшина

    Joined:
    31 Dec 2007
    Messages:
    271
    Likes Received:
    77
    Reputations:
    1
    Всем привет.

    Необходимо для личных целей написать скрипт подсчета выслуги лет у военных..
    Написал, но столкнулся с проблемой не точности..

    опишу вкратце что должно получиться..

    например человек служит год за год с 01/01/2011 по 01/01/2012 т.е ровно год или 365 дней
    и год за полтора с 01/01/2010 по 01/01/2011 т.е опять год. его делим на 2 (6 месяцев) и прибавляем к год-за-го итого выслуга лет 1 год и 6 месяцев. или ~547 дней

    вот скрипт :
    PHP:
    <script type='text/javascript' src='jquery-1.6.1.min.js'></script>
    <script>
    function AddItem() {
      $('#items').append('<tr><td>С</td><td><input type=text name=za_poltora_s[]></td><td>По</td><td><input type=text name=za_poltora_po[]> <input type=button value=+ id=add></td></tr>');
    }
    </script>
    <form method=post>
    <fieldset>
    <table>
    <tbody>
     <legend>Выбрать даты год за год</legend>
    <tr>
    <td>С</td><td><input type=text name=za_god_s value="<?=$_POST['za_god_s']?>"></td>
    <td>По</td><td><input type=text name=za_god_po value="<?=$_POST['za_god_po']?>"></td>
    </tr>
    </table>
    </fieldset>
    <fieldset>
    <table id=items>
     <legend>Выбрать даты год за полтора</legend>

    <tr>
    <td>С</td><td><input type=text name=za_poltora_s[]></td>
    <td>По</td><td><input type=text name=za_poltora_po[]> <input type=button value=+ id=add onclick="AddItem()"></td>
    </tr>
    </tbody>
    </table>
    </fieldset>
    <input type=submit>
    </form>
    PHP:
    function sekond ($date){ //некая функция переводящая дату с русского формата в секунды
    $ex explode("/",$date);  // делим на производные для английского формата
    $date mktime(000$ex[1], $ex[0], $ex[2]); // а тут уже эта дата в американском формате
    return $date;
    }

    $date_za_god sekond($_POST['za_god_po']) - sekond($_POST['za_god_s']); // разница в секундах между  год за год
    echo "$_POST[za_god_po] - $_POST[za_god_s]<br>";
    echo 
    "Дней год за год ".$date_za_god/(60*60*24); // количество дней год за год
    $itogo_god_za_god $date_za_god/(60*60*24); // тут получаем количество дней год-за-год
    $itogo_za_poltora=0;
    $za_poltora_s $_POST['za_poltora_s'];
    $za_poltora_po $_POST['za_poltora_po'];
    $count count($za_poltora_s);

    for(
    $i=0;$i<=$count-1;$i++){
    $itogo_za_poltora =$itogo_za_poltora + (sekond($za_poltora_po[$i]) - sekond($za_poltora_s[$i]));
    }
    $itogo_za_poltora $itogo_za_poltora/2// тут делим количество секунд год-за-полтора на 2. см ФЗ 306 от 1 января 2012
    $itogo_za_poltora $itogo_za_poltora/(60*60*24); // итого дней
    echo "<br> $itogo_za_poltora";
    $itogo_za_poltora $itogo_za_poltora $itogo_god_za_god// сумма дней год за год и год-за-полтора. Выслуга лет в днях!!!!
    echo "<br>Итого $itogo_za_poltora";
    $let floor($itogo_za_poltora/365); // переводим в года
    echo "<br>$let";
    if(
    $let 0){$itogo_za_poltora=$itogo_za_poltora - ($let*365);}
    $mon floor($itogo_za_poltora/30); // месяцы
    echo "<br>$mon";
    if(
    $mon 0){$itogo_za_poltora=$itogo_za_poltora - ($mon*30);}
    $day $itogo_za_poltora// остаток дни

    echo "<br> $let лет $mon месяцев и $day дней";


    но если в него задать те параметры на которых я привел пример выходит 1год 6 месяцев и 4 дня
    Откуда взялось 4 дня? О_о Это видимо некая погрешность.. Но черезчур она большая.. 4 дня на год. а за 10 лет?

    Операции проводил в секундах, потом переводил в дни.

    есть ли решение чтоб делать то-же самое но с учетом месяцев 30,31,28 дней
    вроде как наткнулся на date_diff но она тоже самое делает. просто разница в секундах.

    п.с сори за код. Но расписал все подробно для себя, чтоб легче ориентироваться. После отладки уменьшу и уберу лишние операции и переменные
     
    #1 -=Zhenek=-, 5 Jan 2012
    Last edited: 5 Jan 2012
  2. zifanchuck

    zifanchuck Elder - Старейшина

    Joined:
    27 Oct 2008
    Messages:
    396
    Likes Received:
    154
    Reputations:
    3
    Толком не вчитывался, но может косяк из-за того что не во всех месяцах 30 дней?
     
  3. -=Zhenek=-

    -=Zhenek=- Elder - Старейшина

    Joined:
    31 Dec 2007
    Messages:
    271
    Likes Received:
    77
    Reputations:
    1
    Вполне. Но тут то считается не по месяцам.. а просто грубо переводим в секунды, вычитаем.

    При просчете вручную столбиком тоже из года вычитают год, и месяцев месяц и дней дни.

    т.е ручной вариант просчета тоже не учитывает количество дней в месяце..

    Да и поидее тут по 30 дней а есть месяцы по 31. Значит наоборот меньше должно быть,а тут лишние дни рисует.

    В днях вроде все сходится.. а вот при переводе из дней в год,месяц,день уже погрешность.
     
  4. Чакэ

    Чакэ Elder - Старейшина

    Joined:
    15 Aug 2010
    Messages:
    260
    Likes Received:
    66
    Reputations:
    62
    может я не всё понял, но зачем столько мути для работы с датой? я имею ввиду зачем переводить в секунды etc. у каждого дня есть свой порядковый номер. от этого и отталкивайтесь.
     
  5. -=Zhenek=-

    -=Zhenek=- Elder - Старейшина

    Joined:
    31 Dec 2007
    Messages:
    271
    Likes Received:
    77
    Reputations:
    1
    Потому, что все мануалы, в том числе и офф работают с датами в секундах.

    Можно примерчик или имена функций (хотяб 1) для работы с датами вашим способом. покопаю в мануалах.

    Да и удобно если вот у меня будет 10 интервалов времени перевести повычитать,сложить поделить и обратно преобразовать =)
     
  6. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    -=Zhenek=- http://ru2.php.net/manual/en/class.datetime.php http://ru2.php.net/manual/en/class.dateinterval.php
     
    _________________________
  7. -=Zhenek=-

    -=Zhenek=- Elder - Старейшина

    Joined:
    31 Dec 2007
    Messages:
    271
    Likes Received:
    77
    Reputations:
    1
    Спасибо.
    Эта функция сокращает код, но толком мою проблему не решает..

    А именно момент, что полученную дату нужно поделить на 2.

    Мне или использовать $aa->diff($bb)->days и получать вывод в днях, делить его. А потом переводить.. Но те-же 4 дня для года и вылазят =)

    Вот :

    PHP:
    date_default_timezone_set("Asia/Vladivostok");
    function 
    rus_eng ($date){ //некая функция переводящая дату с русского формата в секунды
    $ex explode("/",$date);  // делим на производные для английского формата
    $date mktime(000$ex[1], $ex[0], $ex[2]); 
    return 
    date("m/d/Y",$date);// а тут уже эта дата в американском формате
    }
    $_POST['za_god_s'] = "01/01/2010";
    $_POST['za_god_po'] = "01/01/2011";
    $aa = new DateTime(rus_eng($_POST['za_god_s']));
    $bb = new DateTime(rus_eng($_POST['za_god_po']));
    $god_za_god_days $aa->diff($bb)->d;
    $god_za_god_mon $aa->diff($bb)->m;
    $god_za_god_years =  $aa->diff($bb)->y;
    echo 
    $aa->diff($bb)->y."год ".$aa->diff($bb)->m." месяцев ".$aa->diff($bb)->d." дней или всего это ".$aa->diff($bb)->days." дней" ;
    $all_days floor($aa->diff($bb)->days/2) ;
    echo 
    "<br>".$all_days." дней деленых на 2  ФЗ 306<br>";
    $let floor($all_days/365); // переводим в года
    if($let 0){$all_days=$all_days - ($let*365);}
    $mon floor($all_days/30); // месяцы
    if($mon 0){$all_days=$all_days - ($mon*30);}
    $day $all_days// остаток дни
    echo "<br> $let лет $mon месяцев и $day дней";
    или делить производные год,месяц и дни на 2
    Но тогда нужно проверять если год 1 при делении на 2 0,5 года переводить в месяцы и т.д вообще погрешность будет огромная.

    Или можно как-то прям сам результат $aa->diff($bb) поделить? сравнить знаю можно... но делить.
     
  8. barnaki

    barnaki Elder - Старейшина

    Joined:
    2 Nov 2008
    Messages:
    676
    Likes Received:
    130
    Reputations:
    4
    не так делать не вариант. пропиши массивчик к количеством дней.
     
  9. -=Zhenek=-

    -=Zhenek=- Elder - Старейшина

    Joined:
    31 Dec 2007
    Messages:
    271
    Likes Received:
    77
    Reputations:
    1
    Немного не понял..
    Просто загнать их в массив а не складывать? Тогда разницы то нет.