Я видел некоторые варианты по этому вопросу, но я считаю, что на этот пока не был дан ответ.
Мне нужно получить начальную дату и дату окончания недели, выбранную по номеру года и недели (а не дату)
пример:
вход:
getStartAndEndDate($week, $year);
вывод:
$return[0] = $firstDay; $return[1] = $lastDay;
Возвращаемое значение будет чем-то вроде массива, в котором первая запись – это дата начала недели, а вторая – дата окончания.
ДОПОЛНИТЕЛЬНО: пока мы на нем, формат даты должен быть Ynj
(нормальный формат даты, без Ynj
нулей.
Я пробовал редактировать существующие функции, которые почти делали то, что я хотел, но до сих пор мне не повезло.
Пожалуйста, помогите мне, спасибо заранее.
function getStartAndEndDate($week, $year) { $time = strtotime("1 January $year", time()); $day = date('w', $time); $time += ((7*$week)+1-$day)*24*3600; $return[0] = date('Yn-j', $time); $time += 6*24*3600; $return[1] = date('Yn-j', $time); return $return; }
Использование класса DateTime :
function getStartAndEndDate($week, $year) { $dto = new DateTime(); $dto->setISODate($year, $week); $ret['week_start'] = $dto->format('Ym-d'); $dto->modify('+6 days'); $ret['week_end'] = $dto->format('Ym-d'); return $ret; } $week_array = getStartAndEndDate(52,2013); print_r($week_array);
Возвращает:
Array ( [week_start] => 2013-12-23 [week_end] => 2013-12-29 )
Разъяснение:
Более короткая версия (работает в> = php5.3):
function getStartAndEndDate($week, $year) { $dto = new DateTime(); $ret['week_start'] = $dto->setISODate($year, $week)->format('Ym-d'); $ret['week_end'] = $dto->modify('+6 days')->format('Ym-d'); return $ret; }
Может быть сокращен доступ к классу при создании экземпляра в> = php5.4.
Немного опережающее решение, используя «[год] W [неделя] [день]» формат strtotime:
function getStartAndEndDate($week, $year) { // Adding leading zeros for weeks 1 - 9. $date_string = $year . 'W' . sprintf('%02d', $week); $return[0] = date('Yn-j', strtotime($date_string)); $return[1] = date('Yn-j', strtotime($date_string . '7')); return $return; }
Мы можем легко достичь этого без необходимости дополнительных вычислений, кроме тех, которые присущи классу DateTime .
function getStartAndEndDate($year, $week) { return [ (new DateTime())->setISODate($year, $week)->format('Ym-d'), //start date (new DateTime())->setISODate($year, $week, 7)->format('Ym-d') //end date ]; }
Функция setISODate()
принимает три аргумента: $year
, $week
и $day
соответственно, где $day
умолчанию – 1 – в первый день недели. Поэтому мы получаем 7, чтобы получить точную дату 7-го дня $week
.
Сначала нам нужен день с этой недели, поэтому, зная номер недели и зная, что в неделю семь дней мы собираемся сделать это
$pickADay = ($weekNo-1) * 7 + 3;
таким образом pickAday будет днем в нашу желаемую неделю.
Теперь, потому что мы знаем год, мы можем проверить, что это за день. вещи просты, если нам нужны только даты, более поздние, чем временная отметка unix. Мы получим временную метку unix в первый день года и добавим к этому 24*3600*$pickADay
и все просто отсюда, потому что у нас есть временная метка, которую мы можем знать, что день недели, и соответственно рассчитывать голову и хвост этой недели.
Если мы хотим выяснить то же самое, скажем, 12-я неделя 1848 года, мы должны использовать другой подход, поскольку мы не можем получить метку времени. Зная, что каждый год в день продвигается 1 день недели (1 ноября прошлого года было в воскресенье, в этом году – в понедельник, исключение за високосные годы, когда он продвигается через 2 дня, я считаю, вы можете это проверить). Что бы я сделал, если год старше 1970 года, чем разница между ним и необходимым годом, чтобы узнать, сколько лет там, рассчитать день недели, так как мой pickADay был частью 1970 года, сдвиньте его на один рабочий день за каждый , $shiftTimes = ($yearDifference + $numberOfLeapYears)%7
, в разнице. сдвиньте дневные бэкавы $ shiftTimes, тогда вы узнаете, какой день недели был в тот день тем годами назад, затем найдите неделю и неделю. То же самое можно использовать и в будущем, если это кажется более простым. Попробуйте, если это сработает и скажите мне, если это не так.
Расчет Рохама Рафия неверен. Вот короткое решение:
// week number to timestamp (first day of week number) function wn2ts($week, $year) { return strtotime(sprintf('%dW%02d', $year, $week)); }
если вы хотите номер последнего дня недели, вы можете добавить 6 * 24 * 3600
Это старый вопрос, но многие из вышеперечисленных ответов кажутся неправильными. Я придумал свое решение:
function getStartAndEndDate($week, $year){ $dates[0] = date("Ymd", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT))); $dates[1] = date("Ymd", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT).' +6 days')); return $dates; }
Вы пробовали относительные даты PHP ? Это может сработать.
Даже если вы не хотите использовать определенную дату, вы не сможете избежать этого. Вы можете рассчитать неделю на основе даты ТОЛЬКО.
шаги:
Я бы рекомендовал работать с последовательными датами, такими как Zend_Date или Pear Date .
function getStartAndEndDate($week, $year) { $week_start = new DateTime(); $week_start->setISODate($year,$week); $return[0] = $week_start->format('dM-Y'); $time = strtotime($return[0], time()); $time += 6*24*3600; $return[1] = date('dM-Y', $time); return $return; }
вfunction getStartAndEndDate($week, $year) { $week_start = new DateTime(); $week_start->setISODate($year,$week); $return[0] = $week_start->format('dM-Y'); $time = strtotime($return[0], time()); $time += 6*24*3600; $return[1] = date('dM-Y', $time); return $return; }
самый короткий способ сделать это:
function week_date($week, $year){ $date = new DateTime(); return "first day of the week is ".$date->setISODate($year, $week, "1")->format('Ym-d') ."and last day of the week is ".$date->setISODate($year, $week, "7")->format('Ym-d'); } echo week_date(12,2014);