2011-02-01 4 views
34

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

мне нужно получить дату начала и дату окончания недели, выбранный года и номер недели (не даты)

пример:

вход:

getStartAndEndDate($week, $year); 

выход:

$return[0] = $firstDay; 
$return[1] = $lastDay; 

Возвращаемое значение будет чем-то вроде массива, в котором первая запись дата начала недели, а вторая - дата окончания.

ВАРИАНТ: в то время как мы в этом, формат даты должен быть Y-n-j (обычный формат даты, без ведущих нулей

Я пытался редактировать существующие функции, которые почти сделал то, что я хотел, но у меня не было никакой удачи. до сих пор.

Пожалуйста, помогите мне, спасибо заранее.

+1

StackOverflow не собирается получать как можно больше вариантов. Если вы можете найти решение из вариантов, не задавайте вопрос. Если вы не можете понять это, вам следует объяснить, насколько далеко вы получили от вариантов. – Gordon

ответ

32
function getStartAndEndDate($week, $year) 
{ 

    $time = strtotime("1 January $year", time()); 
    $day = date('w', $time); 
    $time += ((7*$week)+1-$day)*24*3600; 
    $return[0] = date('Y-n-j', $time); 
    $time += 6*24*3600; 
    $return[1] = date('Y-n-j', $time); 
    return $return; 
} 
+8

Неточная информация. Неделя 1 из 2014 года с 2013 по 2013 год до '2014-01-05', а не с '2014-01-06' до '2014-01-12', это на самом деле неделя 2. –

+2

действительно это происходит одна неделя. –

+0

Неверно, потому что Day Light Saving был проигнорирован. –

0

вы пробовали PHP relative dates? Это может сработать.

+0

, то какая команда вы предлагаете использовать? 'strtotime ('первый день недели 12')'? – Pieter888

+0

@ Pieter888 это не работает и не основано на году –

+1

Возможно, вы можете их связать. Попробуйте '+ n недель ', чтобы получить неделю. Затем снова взгляните на документы. Существует также способ получить будний день. – Mikel

1

Сначала нужно день с этой недели, поэтому, зная номер недели и KNO крыло, что за неделю семь дней мы будем делать так

таким образом pickAday будет день в нашей желаемой неделе.

Теперь, поскольку мы знаем год, мы можем проверить, что это за день. вещи просты, если нам нужны только даты, более поздние, чем временная отметка unix. Мы получим временную отметку unix для первого дня года и добавим к этому 24*3600*$pickADay, и все просто отсюда, потому что у нас есть отметка времени, которую мы можем знать, какой день неделю это и вычислить голову и хвост той недели соответственно.

Если мы хотим узнать то же самое, скажем, 12-я неделя 1848 года, мы должны использовать другой подход, поскольку мы не можем получить метку времени. Зная, что каждый год в день продвигается 1 день недели (1 ноября прошлого года было в воскресенье, в этом году - в понедельник, исключение за високосные годы, когда он продвигается через 2 дня, я считаю, вы можете это проверить). Что бы я сделал, если год старше 1970 года, чем разница между ним и необходимым годом, чтобы узнать, сколько лет там, рассчитать день недели, так как мой pickADay был частью 1970 года, сдвиньте его на один рабочий день за каждый , $shiftTimes = ($yearDifference + $numberOfLeapYears)%7, с отличием. сдвиньте дневные бэкавы $ shiftTimes, тогда вы узнаете, какой день недели был в тот день тем годами назад, затем найдите неделю и неделю. То же самое можно использовать и в будущем, если это кажется более простым. Попробуйте, если это сработает и скажите мне, если это не так.

+0

Спасибо, он наверняка прояснил некоторые из моих замешательств в отношении этих дат. Ответ, данный Рохамом Рафием, подтверждает вашу теорию, и я благодарю вас обоих! – Pieter888

0

Даже если вы не хотите использовать определенную дату, вы не сможете избежать этого. Вы можете рассчитать неделю на основе даты ТОЛЬКО.

Шаги:

  1. получить первый день года
  2. решить, когда первые старты недели (есть некоторые правила, которые включают в первый четверг, если я помню.
  3. добавить несколько недель (ваш первый параметр). Zend_Date имеет функцию add(), где вы можете добавить несколько недель, например. Это даст вам первый день недели.
  4. смещение и получить последний день.

Я бы рекомендовал работать с последовательными датами, такими как Zend_Date или Pear Date.

9

Слегка аккуратнее решение, используя "[год] W [неделю] [день]" Формат StrToTime:

function getStartAndEndDate($week, $year) { 
    // Adding leading zeros for weeks 1 - 9. 
    $date_string = $year . 'W' . sprintf('%02d', $week); 
    $return[0] = date('Y-n-j', strtotime($date_string)); 
    $return[1] = date('Y-n-j', strtotime($date_string . '7')); 
    return $return; 
} 
-1
function getStartAndEndDate($week, $year) 
    { 
     $week_start = new DateTime(); 
     $week_start->setISODate($year,$week); 
     $return[0] = $week_start->format('d-M-Y'); 
     $time = strtotime($return[0], time()); 
     $time += 6*24*3600; 
     $return[1] = date('d-M-Y', $time); 
     return $return; 
    } 
+0

объясните, что вы сделали немного дальше, чем просто разместили код –

118

Использование DateTime класса:

function getStartAndEndDate($week, $year) { 
    $dto = new DateTime(); 
    $dto->setISODate($year, $week); 
    $ret['week_start'] = $dto->format('Y-m-d'); 
    $dto->modify('+6 days'); 
    $ret['week_end'] = $dto->format('Y-m-d'); 
    return $ret; 
} 

$week_array = getStartAndEndDate(52,2013); 
print_r($week_array); 

возвращения :

Array 
(
    [week_start] => 2013-12-23 
    [week_end] => 2013-12-29 
) 

Разъяснение:

  • Создать новый объект DateTime, который по умолчанию сейчас()
  • Вызова setISODate изменять объект в первый день $ недели $ года вместо NOW()
  • даты Формата как ' Ymd 'и положить в $ ret [' week_start ']
  • Изменить объект, добавив 6 дней, который будет равен концу недели
  • Формат даты как «Ymd» и положить в $ ret [' week_end ']

Более короткая версия (работает в> = php5.3):

function getStartAndEndDate($week, $year) { 
    $dto = new DateTime(); 
    $ret['week_start'] = $dto->setISODate($year, $week)->format('Y-m-d'); 
    $ret['week_end'] = $dto->modify('+6 days')->format('Y-m-d'); 
    return $ret; 
} 

Может быть сокращен с class member access on instantiation в> = php5.4.

+8

Это должен быть принятый ответ, руки вниз. Это быстрее, чище и использует внутренний класс DateTime(). – BizLab

+0

Следует отметить, что если вы решите передать объект DateTime, вам нужно добавить клон перед тем, как это сделать, или вы всегда будете возвращать измененную дату. '$ ret ['week_start'] = clone $ dto;' – Styledev

+1

Потому что иногда нам это нужно для mysql, нам тоже нужно время. Поэтому я немного изменил это. Сбросьте время, добавьте 7 дней и уменьшите на 1 сек. $ dto = new DateTime(); \t $ dto-> setISODate ($ year, $ week); \t $ dto-> setTime (0,0,0); \t $ ret ['week_start'] = $ dto-> format ('Y-m-d H: i: s'); \t $ dto-> изменить ('+ 7 дней'); \t $ dto-> modify ('- 1 sec'); \t $ ret ['week_end'] = $ dto-> format ('Y-m-d H: i: s'); –

1

Расчет Roham Rafii неверен. Вот краткое решение:

// week number to timestamp (first day of week number) 
function wn2ts($week, $year) { 
    return strtotime(sprintf('%dW%02d', $year, $week)); 
} 

, если вы хотите в последний день недели числа, вы можете добавить до 6 * 24 * 3600

1

Это старый вопрос, но многие ответы, размещенные выше, как представляется, неправильно , я пришел с моим собственным решением:

function getStartAndEndDate($week, $year){ 
    $dates[0] = date("Y-m-d", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT))); 
    $dates[1] = date("Y-m-d", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT).' +6 days')); 
    return $dates; 
} 
0

кратчайший путь, чтобы сделать это:

function week_date($week, $year){ 
    $date = new DateTime(); 
    return "first day of the week is ".$date->setISODate($year, $week, "1")->format('Y-m-d') 
    ."and last day of the week is ".$date->setISODate($year, $week, "7")->format('Y-m-d'); 
} 
echo week_date(12,2014); 
7

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

function getStartAndEndDate($year, $week) 
{ 
    return [ 
     (new DateTime())->setISODate($year, $week)->format('Y-m-d'), //start date 
     (new DateTime())->setISODate($year, $week, 7)->format('Y-m-d') //end date 
    ]; 
} 

setISODate() функция принимает три аргумента: $year, $week и $day соответственно, где $day по умолчанию 1 - первый день недели. Поэтому мы проезжаем 7, чтобы получить точную дату 7-го дня $week.

+0

Лучшее решение, приятно! – nights

Смежные вопросы