Начало и конец дней для заданной недели в 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('Y-m-d', strtotime("-$i day"));
$i++;
}
list($yr, $mo, $da) = explode('-', $start_date);
$end_date = date('Y-m-d', mktime(0, 0, 0, $mo, $da + 6, $yr));
}
Я понял, что все это означало добавление 7 дней к текущей дате. Как вы это сделаете?
Ответы
Ответ 1
Я хотел бы воспользоваться преимуществами PHP strtotime awesomeness:
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('Y-m-d', $start);
$end_date = date('Y-m-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('Y-m-d', $start),
date('Y-m-d', strtotime('next saturday', $start)));
}
И назовите его следующим образом:
list($start_date, $end_date) = x_week_range('2009-05-10');
Я не большой поклонник математики для таких вещей. Даты сложны, и я предпочитаю, чтобы PHP понял это.
Ответ 2
Для всех, кто все еще использует mktime(), strtotime() и другие функции PHP... дайте PHP5 DateTime класс попробовать. Сначала я колебался, но он очень прост в использовании. Не забывайте об использовании 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');
Ответ 3
По-видимому, значение форматирования '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 дней, чтобы получить конец недели или что-то делать.
Ответ 4
Я решил пойти с подходом http://boonedocks.net/mike/archives/114-Figuring-the-Start-of-the-Week-with-PHP.html вместо этого.
Ответ 5
Основы на ответе @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('Y-m-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('Y-m-d'),
$DT_Max->modify('+6 days')->format('Y-m-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
)
Ответ 6
Здесь моя версия, которая использует аналогичное понятие для 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( 'Y-m-d', $start + ( 6 * 86400 ) );
$start = date( 'Y-m-d', $start );
}
Слегка протестирован. Код не может быть пуленепробиваемым или обрабатывать даты в далеком прошлом или будущем. Используйте на свой риск. Не погружайте код в воду. Не показывайте код тем нервным расстройствам, или с ненавистью к знаку доллара. Не тестировалось на животных. Безопасен для использования вегетарианцами. Автор гарантирует, что код никогда не будет говорить с вами. В маловероятном случае, когда код пытается привлечь вас к разговору, автор советует вам игнорировать любые советы, которые он дает.
Ответ 7
Пытаясь найти более оптимизированную версию принятого ответа Паоло Бергантино, я обнаружил действительно хороший способ сделать это:
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('Y-m-d', $start), date('Y-m-d', $end));
}
Строка "воскресенье на этой неделе" всегда означает "воскресенье в конце на этой неделе". Если он используется на отметке времени, которая выпадает на воскресенье, это будет в следующее воскресенье. Это позволяет избежать необходимости использования тройного оператора в решении Паолы.
Ответ 8
Используйте это, чтобы получить "недельный" номер с любой даты.
//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("Y-m-d", strtotime("{$year}-W{$week}-1")); //Returns the date of monday in week
$to = date("Y-m-d", 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/
Ответ 9
Теперь вы можете использовать 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("Y-m-d"));
}
$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("Y-m-d"), 'sunday'=>$sunday->format("Y-m-d")];
}
Использование
print_r( getDateRangeForWeek("2016-05-07") );
print_r( getDateRangeForAllWeeks("2015-11-07", "2016-02-15") );
Ответ 10
Честно говоря, мне трудно понять код, который вы отправили;)
Я думаю, что-то вроде этого должно сделать трюк:
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));
}
Ответ 11
Не делая так много манипуляций с строками, вы можете сделать простую математику на отметках времени.
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);
}
Ответ 12
Основываясь на версии Дэвида Беланже (к сожалению, мой представитель не разрешит мне оставлять комментарий как реакцию на его пост..).
Когда дата ввода находится в понедельник и первый день недели устанавливается как понедельник, исходная версия возвращает предыдущую неделю, а не текущую.
Здесь небольшое исправление (с остальной функцией orig.):
if(function_exists('grk_Week_Range') === FALSE){
function grk_Week_Range($DateString, $FirstDay=6){
if(empty($DateString) === TRUE){
$DateString = date('Y-m-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('Y-m-d'),
$DT_Max->modify('+6 days')->format('Y-m-d')
);
}
}
Ответ 13
из PHP DateTime doc:
<?php
$date = new DateTime();
$date->setISODate(2008, 2);
$startDay = $date->format('Y-m-d');
$date->setISODate(2008, 2, 7);
$endDay = $date->format('Y-m-d');
?>