Как бы я структурировал условия, чтобы добавить два часа только к датам между 08:30 утра до 18:30 вечера, за исключением субботы и воскресенья?
В случае, когда дается время около границы (например, 17:30 во вторник), время слева должно быть добавлено к началу следующего «действительного» периода времени.
Например: если данная дата была в 17:30 во вторник, добавление в течение двух часов приведет к 9:30 в среду (17:30 + 1 час = 18:30, 8:30 + остаток 1 час = 9: 30). Или, если указанная дата была в 17:00 в пятницу, результатом будет 9:00 в понедельник (17:00 пятница + 1,5 часа = 18:30, 8:30 понедельник + остаток 5 часов = 9:00)
Я знаю, как просто добавить два часа, следующим образом:
$idate1 = strtotime($_POST['date']); $time1 = date('Ymd G:i', strtotime('+120 minutes', $idate1)); $_POST['due_date'] = $time1;
Но что бы я добавил, чтобы выполнить вышеизложенное?
Используя «магические числа» и делая много математики с датами, ваш код становится менее читаемым, а также может вызывать проблемы – он не справляется с прыжками, летним временем, часовыми поясами или всей другой странностью, которая приходит с датами и время.
Когда это возможно, вы всегда должны использовать вспомогательные функции, такие как strtotime (), чтобы иметь дело с датами и избегать непосредственного выполнения математики.
Вот мой шанс сделать то, что вы хотите, это не идеально (вы не можете добавить период времени больше, чем разрыв между двумя периодами – то есть 14 часов с 18:30 до 8:30 – и он все еще использует некоторую исходную математику , но это улучшение:
<?php function addRollover($givenDate, $addtime) { $starttime = 8.5*60; //Start time in minutes (decimal hours * 60) $endtime = 18.5*60; //End time in minutes (decimal hours * 60) $givenDate = strtotime($givenDate); //Get just the day portion of the given time $givenDay = strtotime('today', $givenDate); //Calculate what the end of today's period is $maxToday = strtotime("+$endtime minutes", $givenDay); //Calculate the start of the next period $nextPeriod = strtotime("tomorrow", $givenDay); //Set it to the next day $nextPeriod = strtotime("+$starttime minutes", $nextPeriod); //And add the starting time //If it's the weekend, bump it to Monday if(date("D", $nextPeriod) == "Sat") { $nextPeriod = strtotime("+2 days", $nextPeriod); } //Add the time period to the new day $newDate = strtotime("+$addtime", $givenDate); //print "$givenDate -> $newDate\n"; //print "$maxToday\n"; //Get the new hour as a decimal (adding minutes/60) $hourfrac = date('H',$newDate) + date('i',$newDate)/60; //print "$hourfrac\n"; //Check if we're outside the range needed if($hourfrac < $starttime || $hourfrac > $endtime) { //We're outside the range, find the remainder and add it on $remainder = $newDate - $maxToday; //print "$remainder\n"; $newDate = $nextPeriod + $remainder; } return $newDate; } ?>
Я прокомментировал заявления печати, которые у меня были для отладки, вы можете раскомментировать их, если хотите посмотреть, как это работает (что я рекомендую!). Вы используете его как таковой:
<?php print date('Ymd H:i:s',addRollover('2013-01-01 17:30','2 hours')) . "\n"; print date('Ymd H:i:s',addRollover('2013-01-01 18:00','3 hours')) . "\n"; print date('Ymd H:i:s',addRollover('2013-01-04 17:00','150 minutes')) . "\n"; ?>
Результаты в:
2013-01-02 09:30:00 2013-01-02 11:00:00 2013-01-07 09:30:00
Этот код должен отлично справляться с большинством странностей дат, таких как часовые пояса, летнее время и т. Д. Это было бы еще лучше реализовано с помощью PHP- класса DateTime , но это довольно новое, и я не так хорошо знаком с ним, поэтому я придерживался strtotime ().
Функция date работает с отметками времени UNIX, поэтому я просто добавляю 86400 (секунды в день), затем делю на 24 и умножаю их на 2. Это ровно на 2 часа больше.
$time1 = date('Ymd G:i', strtotime($idate1)+86400/12);
Если вы хотите применить эти изменения только в определенный период, вы можете использовать формулу timestamp modulo 86400, чтобы получить часы и минуты.
if(($idate%86400)>=(86400/24*8.5)&&($idate%86400)<=(86400/24*18.5)) $time1 = date('Ymd G:i', strtotime($idate1)+86400/12);
Для фильтрации выходных дней date()
поможет вам:
if(date("D",$idate)=="Sun" || date("D",$idate)=="Sat)
Теперь объединим условия, и мы получим решение для первой части:
if(date("D",$idate)!="Sun" && date("D",$idate)!="Sat" && ($idate%86400)>=(86400/24*8.5)&&($idate%86400)<=(86400/24*18.5)) $time1 = date('Ymd G:i', strtotime($idate1)+86400/12);
Примечание. Для этого вы должны использовать часовой пояс UTC + 0 в сценарии.