Всем привет. Необходимо для личных целей написать скрипт подсчета выслуги лет у военных.. Написал, но столкнулся с проблемой не точности.. опишу вкратце что должно получиться.. например человек служит год за год с 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(0, 0, 0, $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 но она тоже самое делает. просто разница в секундах. п.с сори за код. Но расписал все подробно для себя, чтоб легче ориентироваться. После отладки уменьшу и уберу лишние операции и переменные
Вполне. Но тут то считается не по месяцам.. а просто грубо переводим в секунды, вычитаем. При просчете вручную столбиком тоже из года вычитают год, и месяцев месяц и дней дни. т.е ручной вариант просчета тоже не учитывает количество дней в месяце.. Да и поидее тут по 30 дней а есть месяцы по 31. Значит наоборот меньше должно быть,а тут лишние дни рисует. В днях вроде все сходится.. а вот при переводе из дней в год,месяц,день уже погрешность.
может я не всё понял, но зачем столько мути для работы с датой? я имею ввиду зачем переводить в секунды etc. у каждого дня есть свой порядковый номер. от этого и отталкивайтесь.
Потому, что все мануалы, в том числе и офф работают с датами в секундах. Можно примерчик или имена функций (хотяб 1) для работы с датами вашим способом. покопаю в мануалах. Да и удобно если вот у меня будет 10 интервалов времени перевести повычитать,сложить поделить и обратно преобразовать =)
-=Zhenek=- http://ru2.php.net/manual/en/class.datetime.php http://ru2.php.net/manual/en/class.dateinterval.php
Спасибо. Эта функция сокращает код, но толком мою проблему не решает.. А именно момент, что полученную дату нужно поделить на 2. Мне или использовать $aa->diff($bb)->days и получать вывод в днях, делить его. А потом переводить.. Но те-же 4 дня для года и вылазят =) Вот : PHP: date_default_timezone_set("Asia/Vladivostok"); function rus_eng ($date){ //некая функция переводящая дату с русского формата в секунды $ex = explode("/",$date); // делим на производные для английского формата $date = mktime(0, 0, 0, $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) поделить? сравнить знаю можно... но делить.