- рассчитать рабочее время между двумя датами в PHP
- Количество выходных между датами php
- Фильтрация данных с помощью zend-filter
- Контекстное экранирование с помощью zend-escaper
- Подключение Zend модулей к Expressive
- Совет: отправка информации в Google Analytics через API
- Подборка PHP песочниц
- Совет: активация отображения всех ошибок в PHP
- Посчитать выходные между 2 датами
- 1 ответ
- Узнать, сколько выходных в диапазоне дат
- 3 ответа
- узнать, сколько выходных в диапазоне дат
- Решение
- Другие решения
рассчитать рабочее время между двумя датами в PHP
Есть ли простой способ сделать это, т. Е. Вычислять процент рабочих часов в неделю и делить разницу с помощью вышеперечисленной функции – я играл с этой идеей и получал некоторые очень странные цифры …
Этот пример использует встроенные в PHP классы DateTime для выполнения математики даты. Как я подошел к этому, нужно было начать с подсчета числа полных рабочих дней между двумя датами, а затем умножить это на 8 (см. Примечания). Затем он получает часы, отработанные в частичные дни, и добавляет их в общее количество отработанных часов. Включение этого в функцию было бы достаточно простым.
- Не учитывает временные метки. Но вы уже знаете, как это сделать.
- Не обрабатывает праздники. (Это можно легко добавить, используя множество праздников и добавив их туда, где вы отфильтровываете субботы и воскресенья).
- Требует PHP 5.3.6+
- Предполагается 8-часовой рабочий день. Если сотрудники не берут обед, замените $hours = $days * 8; до $hours = $days * 8.5;
modify('+1 day'); $start->modify('midnight'); // Set second datetime to midnight of that day $end = clone $date2; $end->modify('midnight'); // Count the number of full days between both dates $days = 0; // Loop through each day between two dates $interval = new DateInterval('P1D'); $period = new DatePeriod($start, $interval, $end); foreach ($period as $dt) < // If it is a weekend don't count it if (!in_array($dt->format('l'), array('Saturday', 'Sunday'))) < $days++; >> // Assume 8 hour workdays $hours = $days * 8; // Get the number of hours worked on the first day $date1->modify('5:30 PM'); $diff = $date1->diff($start); $hours += $diff->h; // Get the number of hours worked the second day $date1->modify('8 AM'); $diff = $date2->diff($end); $hours += $diff->h; echo $hours;
Смотрите это в действии
Мое решение проверяет время начала и окончания исходных дат и настраивает их в соответствии с фактическим временем начала и окончания рабочего дня (если исходное время начала до начала работы, оно устанавливает его в последнее).
После этого, как для начала, так и для окончания, время сравнивается с получением параметра DateInterval , вычислением общих дней, часов и т. Д. Затем диапазон дат проверяется на выходные дни, и если найден, общий день уменьшается от diff.
Наконец, часы вычисляются как прокомментированные. 🙂
Приветствия Джону за то, что он вдохновил некоторые из этих решений, особенно DatePeriod чтобы проверить выходные.
Золотая звезда для всех, кто нарушает это; Я буду рад обновить, если кто-нибудь найдет лазейку!
Золотая звезда для себя, я сломал ее! Да, выходные по-прежнему не работают (попробуйте начать в 16:00 в субботу и заканчивая в 13:00 понедельника). Я покорю вас, проблема рабочих часов!
Ninja edit # 2: Я думаю, что я позаботился о ошибках выходных дней, возвращая время начала и окончания к самому последнему соответствующему буднему дню, если они выпадают на выходные. Получил хорошие результаты после тестирования нескольких диапазонов дат (начиная и заканчивая на тех же выходных барах, как и ожидалось). Я не совсем убежден, что это так же оптимизировано / просто, как могло бы быть, но по крайней мере теперь это работает лучше.
// Settings $workStartHour = 9; $workStartMin = 0; $workEndHour = 17; $workEndMin = 30; $workdayHours = 8.5; $weekends = ['Saturday', 'Sunday']; $hours = 0; // Original start and end times, and their clones that we'll modify. $originalStart = new DateTime('2012-03-22 11:29:16'); $start = clone $originalStart; // Starting on a weekend? Skip to a weekday. while (in_array($start->format('l'), $weekends)) < $start->modify('midnight tomorrow'); > $originalEnd = new DateTime('2012-03-24 03:58:58'); $end = clone $originalEnd; // Ending on a weekend? Go back to a weekday. while (in_array($end->format('l'), $weekends)) < $end->modify('-1 day')->setTime(23, 59); > // Is the start date after the end date? Might happen if start and end // are on the same weekend (whoops). if ($start > $end) throw new Exception('Start date is AFTER end date!'); // Are the times outside of normal work hours? If so, adjust. $startAdj = clone $start; if ($start < $startAdj->setTime($workStartHour, $workStartMin)) < // Start is earlier; adjust to real start time. $start = $startAdj; >else if ($start > $startAdj->setTime($workEndHour, $workEndMin)) < // Start is after close of that day, move to tomorrow. $start = $startAdj->setTime($workStartHour, $workStartMin)->modify('+1 day'); > $endAdj = clone $end; if ($end > $endAdj->setTime($workEndHour, $workEndMin)) < // End is after; adjust to real end time. $end = $endAdj; >else if ($end < $endAdj->setTime($workStartHour, $workStartMin)) < // End is before start of that day, move to day before. $end = $endAdj->setTime($workEndHour, $workEndMin)->modify('-1 day'); > // Calculate the difference between our modified days. $diff = $start->diff($end); // Go through each day using the original values, so we can check for weekends. $period = new DatePeriod($start, new DateInterval('P1D'), $end); foreach ($period as $day) < // If it's a weekend day, take it out of our total days in the diff. if (in_array($day->format('l'), ['Saturday', 'Sunday'])) $diff->d--; > // Calculate! Days * Hours in a day + hours + minutes converted to hours. $hours = ($diff->d * $workdayHours) + $diff->h + round($diff->i / 60, 2);
Как говорится в старой поговорке, «если вы хотите, чтобы что-то сделано правильно, сделайте это сами». Не сказать, что это оптимально, но по крайней мере, вернуло мне правильное количество часов.
function biss_hours($start, $end)< $startDate = new DateTime($start); $endDate = new DateTime($end); $periodInterval = new DateInterval( "PT1H" ); $period = new DatePeriod( $startDate, $periodInterval, $endDate ); $count = 0; foreach($period as $date)< $startofday = clone $date; $startofday->setTime(8,30); $endofday = clone $date; $endofday->setTime(17,30); if($date > $startofday && $date format('l'), array('Sunday','Saturday'))) < $count++; >> //Get seconds of Start time $start_d = date("Ymd H:00:00", strtotime($start)); $start_d_seconds = strtotime($start_d); $start_t_seconds = strtotime($start); $start_seconds = $start_t_seconds - $start_d_seconds; //Get seconds of End time $end_d = date("Ymd H:00:00", strtotime($end)); $end_d_seconds = strtotime($end_d); $end_t_seconds = strtotime($end); $end_seconds = $end_t_seconds - $end_d_seconds; $diff = $end_seconds-$start_seconds; if($diff!=0): $count--; endif; $total_min_sec = date('i:s',$diff); return $count .":".$total_min_sec; > $start = '2014-06-23 12:30:00'; $end = '2014-06-27 15:45:00'; $go = biss_hours($start,$end); echo $go;
Количество выходных между датами php
В этом разделе помещены уроки по PHP скриптам, которые Вы сможете использовать на своих ресурсах.
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Совет: активация отображения всех ошибок в PHP
При поднятии PHP проекта на новом рабочем окружении могут возникнуть ошибки отображение которых изначально скрыто базовыми настройками. Это можно исправить, прописав несколько команд.
Посчитать выходные между 2 датами
Я пишу калькулятор цен, где выходные имеют специальную цену. Для этого мне нужно знать, сколько выходных между двумя датами.
Обратите внимание, что под выходными я подразумеваю, что если они хотят, чтобы четверг был вторником, суббота и воскресенье — это не 2 дня с выходным, а 1 выходной с единым. Таким образом, для четверга -> вторника это будет считаться за 1 уик-энд.
Для субботы -> субботы это будет считаться за 2 выходных, поскольку первая суббота не совпадает с следующей субботой. То же самое можно сказать и о воскресеньях и воскресеньях, здесь учитываются выходные дни, независимо от того, являются ли они полными выходными или частичными выходными. До тех пор, пока часть или любая часть выходных дней попадает в этот диапазон дат, она считается 1 выходной. Лучшая аналогия, которую я могу придумать, — это рассматривать выходные дни как один день, который длится 48 часов, а не 2, который длится 24.
Итак, как я могу определить, сколько «полных или частичных выходных» между двумя датами в php?
1 ответ
Мы должны начать с определения количества дней между датами. Это было бы что-то вроде
$n = floor((timestamp_end - timestamp_start)/86400);
Если вы скажете, что суббота -> суббота = 2, то, если наш начальный день не суббота, а количество дней не является произведением 7, количество выходных будет $n/7, в противном случае $n/7+1. Таким образом, мы могли бы начать с.
if (date("N", timestamp_start) == 6 && $n%7 == 0 )
Узнать, сколько выходных в диапазоне дат
Например у меня есть две даты 2015-10-28 а также 2015-12-31 , из них я хочу знать, сколько субботы и воскресенья в данном диапазоне дат. Я могу найти разницу между этими датами, но я не могу найти, сколько выходных.
кто-нибудь когда-нибудь делал это?
function createDateRange($maxDate, $cell, $lead, $offArray = array())< $dates = []; --$cell; --$lead; $edate = date('Y-m-d', strtotime($maxDate." -$lead day")); $sdate = date('Y-m-d', strtotime($edate." -$cell day")); $start = new DateTime($sdate); $end = new DateTime($edate); $end = $end->modify('+1 day'); $interval = DateInterval::createFromDateString('1 day'); $period = new DatePeriod($start, $interval, $end); foreach($period as $d)< $dt = $d->format('Y-m-d'); if(!in_array($dt, $dates)) < $dates[] = $dt; >> return $dates; >
в основном я хочу добавить подсчет + солнце к диапазону дат.
3 ответа
Хитрость заключается в использовании алгоритма типа O(1) для решения этой проблемы.
- Учитывая вашу дату начала, перейдите в первую субботу. Позвони from
- Учитывая дату окончания, вернитесь к предыдущей пятнице. Позвони to
- Если у вас нет крайнего случая (где to меньше чем from ), вычислить (to — from) * 2 / 7 как число выходных дней, и добавьте это к любым выходным дням, пропущенным в шагах (1) и (2).
Вот как я делаю это в производстве, хотя обобщено на произвольные выходные дни.
узнать, сколько выходных в диапазоне дат
например у меня есть две даты 2015-10-28 а также 2015-12-31 , из них я хочу знать, сколько субботы и воскресенья в данном диапазоне дат. Я могу найти разницу между этими датами, но я не могу найти, сколько выходных.
кто-нибудь когда-нибудь делал это?
function createDateRange($maxDate, $cell, $lead, $offArray = array())< $dates = []; --$cell; --$lead; $edate = date('Y-m-d', strtotime($maxDate." -$lead day")); $sdate = date('Y-m-d', strtotime($edate." -$cell day")); $start = new DateTime($sdate); $end = new DateTime($edate); $end = $end->modify('+1 day'); $interval = DateInterval::createFromDateString('1 day'); $period = new DatePeriod($start, $interval, $end); foreach($period as $d)< $dt = $d->format('Y-m-d'); if(!in_array($dt, $dates)) < $dates[] = $dt; >> return $dates; >
в основном я хочу добавить подсчет + солнце к диапазону дат.
Решение
Хитрость заключается в использовании алгоритма типа O (1) для решения этой проблемы.
- Учитывая вашу дату начала, перейдите в первую субботу. Позвони from
- Учитывая дату окончания, вернитесь к предыдущей пятнице. Позвони to
- Если у вас нет крайнего случая (где to меньше чем from ), вычислить (to — from) * 2 / 7 как число выходных дней, и добавьте это к любым выходным дням, пропущенным в шагах (1) и (2).
Вот как я делаю это в производстве, хотя обобщено на произвольные выходные дни.
Другие решения
function getDateForSpecificDayBetweenDates($startDate, $endDate, $weekdayNumber) < $startDate = strtotime($startDate); $endDate = strtotime($endDate); $dateArr = array(); do < if(date("w", $startDate) != $weekdayNumber) < $startDate += (24 * 3600); // add 1 day >> while(date("w", $startDate) != $weekdayNumber); while($startDate return($dateArr); >
Вызов функции для получения дат всех воскресений 2015 года:
$dateArr = getDateForSpecificDayBetweenDates('2015-01-01', '2015-12-31', 0); print ""; print_r($dateArr);
//周日0 周一1 . $data = 4;//周四 $t1 ='2015-10-28'; $t2 = '2015-12-31'; $datetime1 = date_create($t1); $datetime2 = date_create($t2); $interval = date_diff($datetime1, $datetime2); $day = $interval->format('%a'); $result = ($day)/7; $start = getdate(strtotime($t1))['wday']; $end = getdate(strtotime($t2))['wday']; if($data>=$start && $data<=$end)< echo floor($result)+1; >else