Начало и конец дней для заданной недели в PHP

Я пытаюсь получить диапазон недель, используя воскресенье в качестве даты начала, и контрольную дату, например, $date , но я просто не могу понять это.

Например, если бы у меня было $ date как 2009-05-01, я бы получил 2009-04-26 и 2009-05-02. 2009-05-10 выйдет 2009-05-10 и 2009-05-16. Мой текущий код выглядит так (я не могу вспомнить, откуда я его снял, поскольку я забыл указать URL-адрес в моих комментариях):

 function x_week_range(&$start_date, &$end_date, $date) { $start_date = ''; $end_date = ''; $week = date('W', strtotime($date)); $week = $week; $start_date = $date; $i = 0; while(date('W', strtotime("-$i day")) >= $week) { $start_date = date('Ym-d', strtotime("-$i day")); $i++; } list($yr, $mo, $da) = explode('-', $start_date); $end_date = date('Ym-d', mktime(0, 0, 0, $mo, $da + 6, $yr)); } 

Я понял, что все, что он сделал, добавило 7 дней к текущей дате. Как бы вы это сделали?

Я хотел бы воспользоваться преимуществами strtotime для PHP:

 function x_week_range(&$start_date, &$end_date, $date) { $ts = strtotime($date); $start = (date('w', $ts) == 0) ? $ts : strtotime('last sunday', $ts); $start_date = date('Ym-d', $start); $end_date = date('Ym-d', strtotime('next saturday', $start)); } 

Протестировано по предоставленным вами данным и работает. Тем не менее, мне не очень нравится вся эта ссылка. Если бы это была моя функция, у меня было бы так:

 function x_week_range($date) { $ts = strtotime($date); $start = (date('w', $ts) == 0) ? $ts : strtotime('last sunday', $ts); return array(date('Ym-d', $start), date('Ym-d', strtotime('next saturday', $start))); } 

И назовите это так:

 list($start_date, $end_date) = x_week_range('2009-05-10'); 

Я не большой поклонник математики для подобных вещей. Даты сложны, и я предпочитаю, чтобы PHP понял это.

Для всех, кто все еще использует mktime (), strtotime () и другие функции PHP … дайте PHP5 DateTime Class попробовать. Сначала я колебался, но он очень прост в использовании. Не забывайте об использовании clone () для копирования ваших объектов.

Изменить: этот код был недавно изменен, чтобы обрабатывать случай, когда текущий день – воскресенье. В этом случае мы должны получить прошлую субботу, а затем добавить один день, чтобы получить воскресенье.

 $dt_min = new DateTime("last saturday"); // Edit $dt_min->modify('+1 day'); // Edit $dt_max = clone($dt_min); $dt_max->modify('+6 days'); 

Затем отформатируйте его по мере необходимости.

 echo 'This Week ('.$dt_min->format('m/d/Y').'-'.$dt_max->format('m/d/Y').')'; 

Не забудьте установить часовой пояс на раннем этапе вашего кода.

 date_default_timezone_set('America/New_York'); 

По-видимому, значение форматирования 'w' даты () или метод формата объекта DateTime будет возвращать день недели в виде числа (по умолчанию 0 = воскресенье, 1 = понедельник и т. Д.).

Вы можете взять это и вычесть его значение как дни с текущего дня, чтобы найти начало недели.

 $start_date = new DateTime("2009-05-13"); $day_of_week = $start_date->format("w"); $start_date->modify("-$day_of_week day"); 

$ start_date теперь будет равен воскресенью той недели, оттуда вы можете добавить 7 дней, чтобы получить конец недели или что-то-то-то.

Я решил пойти с подходом на http://boonedocks.net/mike/archives/114-Figuring-the-Start-of-the-Week-with-PHP.html вместо этого.

Основываясь на ответе @ jjwdesign, я разработал функцию, которая может вычислять начало и конец недели для определенной даты с использованием класса DateTime. РАБОТАЕТ НА PHP 5.3.0 ++

Разница в том, что вы можете установить день, который вы хотите, в качестве «начала» между 0 (понедельник) и 6 (воскресенье).

Вот функция:

 if(function_exists('grk_Week_Range') === FALSE){ function grk_Week_Range($DateString, $FirstDay=6){ # Valeur par défaut si vide if(empty($DateString) === TRUE){ $DateString = date('Ym-d'); } # On va aller chercher le premier jour de la semaine qu'on veut $Days = array( 0 => 'monday', 1 => 'tuesday', 2 => 'wednesday', 3 => 'thursday', 4 => 'friday', 5 => 'saturday', 6 => 'sunday' ); # On va définir pour de bon le premier jour de la semaine $DT_Min = new DateTime('last '.(isset($Days[$FirstDay]) === TRUE ? $Days[$FirstDay] : $Days[6]).' '.$DateString); $DT_Max = clone($DT_Min); # On renvoie les données return array( $DT_Min->format('Ym-d'), $DT_Max->modify('+6 days')->format('Ym-d') ); } } 

Результаты :

 print_r(grk_Week_Range('2013-08-11 16:45:32', 0)); print_r(grk_Week_Range('2013-08-11 16:45:32', 1)); print_r(grk_Week_Range('2013-08-11 16:45:32', 2)); print_r(grk_Week_Range('2013-08-11 16:45:32', 3)); print_r(grk_Week_Range('2013-08-11 16:45:32', 4)); print_r(grk_Week_Range('2013-08-11 16:45:32', 5)); print_r(grk_Week_Range('2013-08-11 16:45:32', 6)); Array ( [0] => 2013-07-29 [1] => 2013-08-04 ) Array ( [0] => 2013-07-30 [1] => 2013-08-05 ) Array ( [0] => 2013-07-31 [1] => 2013-08-06 ) Array ( [0] => 2013-07-25 [1] => 2013-07-31 ) Array ( [0] => 2013-07-26 [1] => 2013-08-01 ) Array ( [0] => 2013-07-27 [1] => 2013-08-02 ) Array ( [0] => 2013-07-28 [1] => 2013-08-03 ) 

Вот моя версия, которая использует аналогичное понятие для Clay's:

 /** * Start of the week * * 0 = Sun, 1 = Mon, etc. */ define( 'WEEK_START', 0 ); /** * Determine the start and end dates for * the week in which the specified date * falls * * @param $date Date in week * @param $start Week start (out) * @param $end Week end (out) */ function week_bounds( $date, &$start, &$end ) { $date = strtotime( $date ); // Find the start of the week, working backwards $start = $date; while( date( 'w', $start ) > WEEK_START ) { $start -= 86400; // One day } // End of the week is simply 6 days from the start $end = date( 'Ym-d', $start + ( 6 * 86400 ) ); $start = date( 'Ym-d', $start ); } 

Легко протестированы. Код не может быть пуленепробиваемым или обрабатывать даты в далеком прошлом или будущем. Используйте на свой риск. Не погружайте код в воду. Не показывайте код тем нервным расстройствам, или с ненавистью к знаку доллара. Не тестировалось на животных. Безопасен для использования вегетарианцами. Автор гарантирует, что код никогда не будет говорить с вами. В маловероятном случае, когда код пытается привлечь вас к разговору, автор советует вам игнорировать любые советы, которые он дает.

Пытаясь найти более оптимизированную версию принятого ответа Паоло Бергантино, я обнаружил действительно хороший способ сделать это:

 function x_week_range2($date) { $ts = strtotime($date); $start = strtotime('sunday this week -1 week', $ts); $end = strtotime('sunday this week', $ts); return array(date('Ym-d', $start), date('Ym-d', $end)); } 

Строка «воскресенье на этой неделе» всегда означает «Воскресенье в конце этой недели». Если он используется на отметке времени, которая выпадает на воскресенье, это будет в следующее воскресенье. Это позволяет избежать необходимости использования тройного оператора в решении Паолы.

Используйте это, чтобы получить «недельный» номер с любой даты.

 //October 29, 2009 is my birthday echo $week date('W', strtotime('2009-10-29')); //OUTPUT: 44 //October 29 is the 44th week in the year 2009 

Теперь передайте параметры функции getWeekDates как «год (2009)» и «$ week».

 function getWeekDates($year, $week, $start=true){ $from = date("Ymd", strtotime("{$year}-W{$week}-1")); //Returns the date of monday in week $to = date("Ymd", strtotime("{$year}-W{$week}-7")); //Returns the date of sunday in week if($start) { return $from; } else { return $to; } //return "Week {$week} in {$year} is from {$from} to {$to}."; } 

Для получения дополнительной информации см. Эту ссылку http://blog.ekini.net/2009/07/09/php-get-start-and-end-dates-of-a-week-from-datew/

Теперь вы можете использовать DateTime для получения дат начала и окончания недели (ов)

 function getDateRangeForAllWeeks($start, $end){ $fweek = getDateRangeForWeek($start); $lweek = getDateRangeForWeek($end); $week_dates = []; while($fweek['sunday']!=$lweek['sunday']){ $week_dates [] = $fweek; $date = new DateTime($fweek['sunday']); $date->modify('next day'); $fweek = getDateRangeForWeek($date->format("Ymd")); } $week_dates [] = $lweek; return $week_dates; } function getDateRangeForWeek($date){ $dateTime = new DateTime($date); $monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week'); $sunday = clone $dateTime->modify('Sunday this week'); return ['monday'=>$monday->format("Ymd"), 'sunday'=>$sunday->format("Ymd")]; } в function getDateRangeForAllWeeks($start, $end){ $fweek = getDateRangeForWeek($start); $lweek = getDateRangeForWeek($end); $week_dates = []; while($fweek['sunday']!=$lweek['sunday']){ $week_dates [] = $fweek; $date = new DateTime($fweek['sunday']); $date->modify('next day'); $fweek = getDateRangeForWeek($date->format("Ymd")); } $week_dates [] = $lweek; return $week_dates; } function getDateRangeForWeek($date){ $dateTime = new DateTime($date); $monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week'); $sunday = clone $dateTime->modify('Sunday this week'); return ['monday'=>$monday->format("Ymd"), 'sunday'=>$sunday->format("Ymd")]; } 

Применение

 print_r( getDateRangeForWeek("2016-05-07") ); print_r( getDateRangeForAllWeeks("2015-11-07", "2016-02-15") ); 

Честно говоря, мне трудно понять код, который вы опубликовали;)

Я думаю, что-то вроде этого должно сделать трюк:

 function get_week($date) { $start = strtotime($date) - strftime('%w', $date) * 24 * 60 * 60; $end = $start + 6 * 24 * 60 * 60; return array('start' => strftime('%Y-%m-%d', $start), 'end' => strftime('%Y-%m-%d', $end)); } 

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

 function getDateRange(&$start, &$end, $date) { $seconds_in_day = 86400; $day_of_week = date("w", $date); $start = $date - ($day_of_week * $seconds_in_day); $end = $date + ((6 - $day_of_week) * $seconds_in_day); } 

Основанный на версии Дэвида Белангера (к сожалению, мой представитель не разрешит мне оставлять комментарий как реакцию на его пост ..).

Когда дата ввода в понедельник и первый день недели устанавливается как понедельник, исходная версия возвращает предыдущую неделю, а не текущую. Вот небольшое исправление (с остальной функцией оригинала):

 if(function_exists('grk_Week_Range') === FALSE){ function grk_Week_Range($DateString, $FirstDay=6){ if(empty($DateString) === TRUE){ $DateString = date('Ym-d'); } # fix $dayOfWeek = date('N', strtotime($DateString)); if ($dayOfWeek == ($FirstDay +1)) { $whichWeek = 'this '; } else { $whichWeek = 'last '; } $Days = array( 0 => 'monday', 1 => 'tuesday', 2 => 'wednesday', 3 => 'thursday', 4 => 'friday', 5 => 'saturday', 6 => 'sunday' ); # fix $DT_Min = new DateTime( $whichWeek.(isset($Days[$FirstDay]) === TRUE ? $Days[$FirstDay] : $Days[6]).' '.$DateString); $DT_Max = clone($DT_Min); return array( $DT_Min->format('Ym-d'), $DT_Max->modify('+6 days')->format('Ym-d') ); } } 

из PHP DateTime doc:

 <?php $date = new DateTime(); $date->setISODate(2008, 2); $startDay = $date->format('Ym-d'); $date->setISODate(2008, 2, 7); $endDay = $date->format('Ym-d'); ?>