Следующий рабочий день данной даты в PHP
Есть ли у кого-нибудь PHP-фрагмент для вычисления следующего рабочего дня на определенную дату?
Как, например, нужно преобразовать YYYY-MM-DD, чтобы узнать следующий рабочий день?
Пример:
На 03.04.2011 (ДД-ММ-ГГГГ) следующий рабочий день - 04.04.2011.
На 08.04.2011 следующий рабочий день - 11.04.2011.
Это переменная, содержащая дату, которую мне нужно знать в следующий рабочий день для
$cubeTime['time'];
Переменная содержит: 2011-04-01
результат фрагмента должен быть: 2011-04-04
Ответы
Ответ 1
Следующий рабочий день
Это находит следующий будний день с определенной даты (не включая субботу или воскресенье):
echo date('Y-m-d', strtotime('2011-04-05 +1 Weekday'));
Вы также можете сделать это с переменной даты:
$myDate = '2011-04-05';
echo date('Y-m-d', strtotime($myDate . ' +1 Weekday'));
UPDATE: Или, если у вас есть доступ к PHP DateTime class (очень вероятно):
$date = new DateTime('2018-01-27');
$date->modify('+7 weekday');
echo $date->format('Y-m-d');
Хотите пропустить каникулы?:
Хотя оригинальный плакат упоминал "Мне не нужно учитывать праздники", если вы НЕ хотите игнорировать праздники, просто помните - "Праздники" - это всего лишь множество любых дат, которые вы не хотите включать и отличается по странам, регионам, компаниям, лицам... и т.д.
Проще говоря, приведенный выше код в функцию, которая исключает/петли мимо дат, которые вы не хотите включать. Что-то вроде этого:
$tmpDate = '2015-06-22';
$holidays = ['2015-07-04', '2015-10-31', '2015-12-25'];
$i = 1;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
while (in_array($nextBusinessDay, $holidays)) {
$i++;
$nextBusinessDay = date('Y-m-d', strtotime($tmpDate . ' +' . $i . ' Weekday'));
}
Я уверен, что вышеуказанный код можно упростить или сократить, если хотите. Я попытался написать это простым способом.
Ответ 2
В выходные дни в Великобритании вы можете использовать
https://www.gov.uk/bank-holidays#england-and-wales
Данные формата ICS легко анализировать. Мое предложение...
# $date must be in YYYY-MM-DD format
# You can pass in either an array of holidays in YYYYMMDD format
# OR a URL for a .ics file containing holidays
# this defaults to the UK government holiday data for England and Wales
function addBusinessDays($date,$numDays=1,$holidays='') {
if ($holidays==='') $holidays = 'https://www.gov.uk/bank-holidays/england-and-wales.ics';
if (!is_array($holidays)) {
$ch = curl_init($holidays);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$ics = curl_exec($ch);
curl_close($ch);
$ics = explode("\n",$ics);
$ics = preg_grep('/^DTSTART;/',$ics);
$holidays = preg_replace('/^DTSTART;VALUE=DATE:(\\d{4})(\\d{2})(\\d{2}).*/s','$1-$2-$3',$ics);
}
$addDay = 0;
while ($numDays--) {
while (true) {
$addDay++;
$newDate = date('Y-m-d', strtotime("$date +$addDay Days"));
$newDayOfWeek = date('w', strtotime($newDate));
if ( $newDayOfWeek>0 && $newDayOfWeek<6 && !in_array($newDate,$holidays)) break;
}
}
return $newDate;
}
Ответ 3
function next_business_day($date) {
$add_day = 0;
do {
$add_day++;
$new_date = date('Y-m-d', strtotime("$date +$add_day Days"));
$new_day_of_week = date('w', strtotime($new_date));
} while($new_day_of_week == 6 || $new_day_of_week == 0);
return $new_date;
}
Эта функция должна игнорировать выходные (6 = суббота и 0 = воскресенье).
Ответ 4
Что вам нужно сделать:
-
Преобразовать предоставленную дату в метку времени.
-
Используйте это вместе с форматировщиками или w
или N
для команды PHP date, чтобы рассказать вам, какой день недели.
-
Если это не "рабочий день", вы можете увеличить метку времени на один день (86400 секунд) и снова проверить, пока не нажмете рабочий день.
N.B.: Для этого действительно работа, вам также необходимо исключить любой банк или праздничные дни и т.д.
Ответ 5
Эта функция рассчитает рабочий день в будущем или в прошлом. Аргументы - это количество дней, вперед (1) или назад (0) и дата. Если дата не указана на сегодняшний день, будет использоваться:
// returned $date Y/m/d
function work_days_from_date($days, $forward, $date=NULL)
{
if(!$date)
{
$date = date('Y-m-d'); // if no date given, use todays date
}
while ($days != 0)
{
$forward == 1 ? $day = strtotime($date.' +1 day') : $day = strtotime($date.' -1 day');
$date = date('Y-m-d',$day);
if( date('N', strtotime($date)) <= 5) // if it a weekday
{
$days--;
}
}
return $date;
}
Ответ 6
Я наткнулся на эту тему, когда я работал на датском веб-сайте, где мне нужно было написать "Доставка на следующий день" PHP script.
Вот что я придумал (это покажет название следующего рабочего дня на датском языке, а следующая рабочая + 1, если текущее время больше заданного предела)
$day["Mon"] = "Mandag";
$day["Tue"] = "Tirsdag";
$day["Wed"] = "Onsdag";
$day["Thu"] = "Torsdag";
$day["Fri"] = "Fredag";
$day["Sat"] = "Lørdag";
$day["Sun"] = "Søndag";
date_default_timezone_set('Europe/Copenhagen');
$date = date('l');
$checkTime = '1400';
$date2 = date(strtotime($date.' +1 Weekday'));
if( date( 'Hi' ) >= $checkTime) {
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Saturday'){
$date2 = date(strtotime($date.' +2 Weekday'));
}
if (date('l') == 'Sunday') {
$date2 = date(strtotime($date.' +2 Weekday'));
}
echo '<p>Næste levering: <span>'.$day[date("D", $date2)].'</span></p>';
Как вы можете видеть в примерном коде $checkTime, я устанавливаю временной интервал, который определяет, будет ли доставка на следующий день +1 рабочим днем или +2 рабочими днями.
'1400' = 14:00 часов
Я знаю, что инструкции if можно сделать более сжатыми, но я показываю свой код, чтобы люди могли легко понять, как это работает.
Я надеюсь, что кто-то там может использовать этот маленький фрагмент.
Ответ 7
См. пример ниже:
$startDate = new DateTime( '2013-04-01' ); //intialize start date
$endDate = new DateTime( '2013-04-30' ); //initialize end date
$holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday
$interval = new DateInterval('P1D'); // set the interval as 1 day
$daterange = new DatePeriod($startDate, $interval ,$endDate);
foreach($daterange as $date){
if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday))
$result[] = $date->format("Y-m-d");
}
echo "<pre>";print_r($result);
За дополнительной информацией: http://goo.gl/YOsfPX
Ответ 8
Вы могли бы сделать что-то вроде этого.
/**
* @param string $date
* @param DateTimeZone|null|null $DateTimeZone
* @return \NavigableDate\NavigableDateInterface
*/
function getNextBusinessDay(string $date, ? DateTimeZone $DateTimeZone = null):\NavigableDate\NavigableDateInterface
{
$Date = \NavigableDate\NavigableDateFacade::create($date, $DateTimeZone);
$NextDay = $Date->nextDay();
while(true)
{
$nextDayIndexInTheWeek = (int) $NextDay->format('N');
// check if the day is between Monday and Friday. In DateTime class php, Monday is 1 and Friday is 5
if ($nextDayIndexInTheWeek >= 1 && $nextDayIndexInTheWeek <= 5)
{
break;
}
$NextDay = $NextDay->nextDay();
}
return $NextDay;
}
$date = '2017-02-24';
$NextBussinessDay = getNextBusinessDay($date);
var_dump($NextBussinessDay->format('Y-m-d'));
Вывод:
string(10) "2017-02-27"
\NavigableDate\NavigableDateFacade::create($date, $DateTimeZone)
, предоставляется библиотекой php, доступной по адресу https://packagist.org/packages/ishworkh/navigable-date. Вы должны сначала включить эту библиотеку в свой проект с помощью композитора или прямой загрузки.