34

I'm trying to get the week range using Sunday as the start date, and a reference date, say $date, but I just can't seem to figure it out.

For example, if I had $date as 2009-05-01, I would get 2009-04-26 and 2009-05-02. 2009-05-10 would yield 2009-05-10 and 2009-05-16. My current code looks like this (I can't remember where I lifted it from, as I forgot to put down the url in my comments):

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));
}

I realized all it did was add 7 days to the current date. How would you do this?

Zahymaka
  • 6,523
  • 7
  • 31
  • 37

16 Answers16

93

I would take advantange of PHP's 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));
}

Tested on the data you provided and it works. I don't particularly like the whole reference thing you have going on, though. If this was my function, I'd have it be like this:

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)));
}

And call it like this:

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

I'm not a big fan of doing math for things like this. Dates are tricky and I prefer to have PHP figure it out.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • 2
    I used the following to get the last sunday date formatted: date('Y-m-d',strtotime('last sunday')) – John M Aug 17 '09 at 19:57
  • 3
    Give the PHP5 DateTime Class a try! – jjwdesign Jul 15 '14 at 12:23
  • @John M, see my comment below about how "last sunday" can be problematic if today is Sunday and you want __this__ week. – cdmo Feb 29 '16 at 13:18
  • if you want to start week from monday to sunday then some changes in code..function x_week_range($date) { $ts = strtotime($date); $start = (date('w', $ts) == 0) ? $ts : strtotime('monday this week', $ts); return date('Y-m-d', $start).' to '.date('Y-m-d', strtotime('sunday this week', $start)); } – Raushan Singh Feb 24 '20 at 06:54
24

To everyone still using mktime(), strtotime() and other PHP functions... give the PHP5 DateTime Class a try. I was hesitant at first, but it's really easy to use. Don't forget about using clone() to copy your objects.

Edit: This code was recently edited to handle the case where the current day is Sunday. In that case, we have to get the past Saturday and then add one day to get Sunday.

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

Then format as you need it.

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

Make sure to set your timezone early in your code.

date_default_timezone_set('America/New_York');
jjwdesign
  • 3,272
  • 8
  • 41
  • 66
  • 2
    Unless I'm reading this wrong, I'm not sure if this logic will work out if today is Sunday. If today is Sunday and you make a `DateTime` object of `last sunday`, PHP will return the previous Sunday, not the current one. So if today's date is 2/28/2016, the above code would echo `This week 2/21/2016 - 2/27/2016` (effectively the previous week. Monday through Saturday would hide this problem. I'd suggest something like `$dt_min = new DateTime("last Saturday + 24 hour");` – cdmo Feb 29 '16 at 13:15
10

Apparently 'w' formatting value of date() or the format method of a DateTime object will return the day of the week as a number (by default, 0=Sunday, 1=Monday, etc)

You could take this and subtract it's value as days from the current day to find the beginning of the week.

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

$start_date->modify("-$day_of_week day");

$start_date will now be equal to the Sunday of that week, from there you can add 7 days to get the end of the week or what-have-you.

Crazy Joe Malloy
  • 834
  • 6
  • 14
  • same can be done with the Date funciton: `$day_of_week date('w', strtotime($start_date));` `$sunday = date('Y-m-d', strtotime('-'.$day_of_week.' days', strtotime($start_date)));` – d.raev Mar 10 '15 at 12:14
4

Base on @jjwdesign's answer, I developed a function that can calculate the beginning and ending of a week for a specific date using the DateTime class. WILL WORK ON PHP 5.3.0++

The difference is you can set the day you want as the "beginning" between 0 (monday) and 6 (sunday).

Here's the function :

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')
        );
    }
}

Results :

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
)
David Bélanger
  • 7,400
  • 4
  • 37
  • 55
  • The function works. Thanks. However, your example is a little off. It has the date of 2013-08-11, so how does it return a date range of 7-25 through 8-06? Shouldn't the 11th of August be in there somewhere? – Jarom Apr 17 '18 at 16:34
3

I have decided to go with the approach at http://boonedocks.net/mike/archives/114-Figuring-the-Start-of-the-Week-with-PHP.html instead.

Iiridayn
  • 1,747
  • 21
  • 43
2

Use this to get the "week" number from any given date.

//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

Now pass the parameters for getWeekDates function as "year (2009)" and "$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}.";
    }

For More Info Please refer this link http://blog.ekini.net/2009/07/09/php-get-start-and-end-dates-of-a-week-from-datew/

Vinit Kadkol
  • 1,221
  • 13
  • 12
2

Here's my version, which uses a similar notion to 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 );
}

Lightly tested. Code may not be bulletproof, or handle dates in the far past or future. Use at your own risk. Do not immerse the code in water. Do not show the code to those of a nervous disposition, or with a hatred of the dollar sign. Not tested on animals. Safe for use by vegetarians. Author warrants that the code will never, ever speak to you. In the unlikely event that the code does try to engage you in conversation, the author advises you to disregard any and all advice it gives.

Rob
  • 47,999
  • 5
  • 74
  • 91
1

In trying to find a more streamlined version of the accepted answer by Paolo Bergantino, I discovered a really nice way to get this done:

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));
}

The 'sunday this week' string always means "The Sunday at the end of this week." If used on a timestamp that falls on a Sunday, it will be the following Sunday. This lets you avoid the need for the ternary operator in Paola's solution.

coredumperror
  • 8,471
  • 6
  • 33
  • 42
1

You can now use DateTime to get start/end dates of week(s)

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")];
}

Usage

print_r( getDateRangeForWeek("2016-05-07") );

print_r( getDateRangeForAllWeeks("2015-11-07", "2016-02-15") );
Waqas
  • 714
  • 5
  • 13
0

Based on David Bélanger's version (unfortunatelly, my rep. won't allow me to post comment as reaction to his post..).

When input date is monday and first day of week is set as monday, original version returns previous week, not current. Here's the little fix (with the rest of orig. function):

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')
    );
}
}
b3da
  • 573
  • 1
  • 5
  • 12
0

A simple code to return the days from start DateTime and end DateTime. Using gmdate() method you can format date/time.

$start_str_date = strtotime($start_date);
$end_str_date = strtotime($end_date);
$interval_days = $end_str_date - $start_str_date;
$days = gmdate('d',$interval_days);
echo $days;
PramodA
  • 110
  • 2
  • 8
0

I noticed that most of the answers here make use of strtotime/DateTime. While correct, personally I rather calculating dates without using English words.

Here's a simple solution that makes use of mtkime :

$now = time();
$day_of_week = (int)date('w', $now);

$week_start = mktime(0, 0, 0, date('n', $now), date('j', $now)-$day_of_week, date('Y', $now));
$week_end = mktime(23, 59, 59, date('n', $week_start), date('j', $week_start)+6, date('Y', $week_start));
Littm
  • 4,923
  • 4
  • 30
  • 38
0
function weekRange($year, $week){
        $dateFrom = new \DateTime();
        $dateFrom->setISODate($year, $week);
        $dateTo = new \DateTime();
        $dateTo->setISODate($year, $week, 7);

        return array(
            'week' => $dateFrom->format('Y-W'),
            'start'=> $dateFrom->format('Y-m-d'),
            'end' => $dateTo->format('Y-m-d')
        );
    }

Example:

$weekInformation = weekRange(2020, 38);

echo $weekInformation['start']; 
// Display: 2020-09-14

echo $weekInformation['end']; 
// Display: 2020-09-20
Bialy7
  • 87
  • 4
0

To be honest, I have trouble understanding the code you posted ;)

I guess something like this should do the trick:

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));
}
rodion
  • 6,087
  • 4
  • 24
  • 29
0

Without doing so much string manipulation, you can do some simple math on the timestamps.

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);
}
Clay
  • 2,932
  • 2
  • 18
  • 16
-1

from 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');
?>
Rybus
  • 651
  • 6
  • 15