[php] Get first day of week in PHP?

Given a date MM-dd-yyyy format, can someone help me get the first day of the week?

This question is related to php datetime

The answer is


Another way to do it....

$year = '2014';
$month = '02';
$day = '26';

$date = DateTime::createFromFormat('Y-m-d H:i:s', $year . '-' . $month . '-' . $day . '00:00:00');
$day = date('w', $date->getTimestamp());

// 0=Sunday 6=Saturday
if($day!=0){

   $newdate = $date->getTimestamp() - $day * 86400;  //86400 seconds in a day

   // Look for DST change 
   if($old = date('I', $date->getTimestamp()) != $new = date('I', $newdate)){
       if($old == 0){
           $newdate -= 3600;  //3600 seconds in an hour
       } else {
           $newdate += 3600;
       }
   }

   $date->setTimestamp($newdate);
}

echo $date->format('D Y-m-d H:i:s');

<?php
/* PHP 5.3.0 */

date_default_timezone_set('America/Denver'); //Set apprpriate timezone
$start_date = strtotime('2009-12-15'); //Set start date

//Today's date if $start_date is a Sunday, otherwise date of previous Sunday
$today_or_previous_sunday = mktime(0, 0, 0, date('m', $start_date), date('d', $start_date), date('Y', $start_date)) - ((date("w", $start_date) ==0) ? 0 : (86400 * date("w", $start_date)));

//prints 12-13-2009 (month-day-year)
echo date('m-d-Y', $today_or_previous_sunday);

?>

(Note: MM, dd and yyyy in the Question are not standard php date format syntax - I can't be sure what is meant, so I set the $start_date with ISO year-month-day)


Here is what I am using...

$day = date('w');
$week_start = date('m-d-Y', strtotime('-'.$day.' days'));
$week_end = date('m-d-Y', strtotime('+'.(6-$day).' days'));

$day contains a number from 0 to 6 representing the day of the week (Sunday = 0, Monday = 1, etc.).
$week_start contains the date for Sunday of the current week as mm-dd-yyyy.
$week_end contains the date for the Saturday of the current week as mm-dd-yyyy.


Here I am considering Sunday as first & Saturday as last day of the week.

$m = strtotime('06-08-2012');  
$today =   date('l', $m);  
$custom_date = strtotime( date('d-m-Y', $m) );   
if ($today == 'Sunday') {  
   $week_start = date("d-m-Y", $m);  
} else {  
  $week_start = date('d-m-Y', strtotime('this week last sunday', $custom_date));  
}  

if ($today == 'Saturday') {  
  $week_end = date("d-m-Y", $m);
} else {  
  $week_end = date('d-m-Y', strtotime('this week next saturday', $custom_date));  
}
echo '<br>Start: '. $week_start;  
echo '<br>End: '. $week_end;  

Output :

Start: 05-08-2012
End: 11-08-2012


strtotime('this week', time());

Replace time(). Next sunday/last monday methods won't work when the current day is sunday/monday.


The easiest way to get first day(Monday) of current week is:

strtotime("next Monday") - 604800;

where 604800 - is count of seconds in 1 week(60*60*24*7).

This code get next Monday and decrease it for 1 week. This code will work well in any day of week. Even if today is Monday.


This question needs a good DateTime answer:-

function firstDayOfWeek($date)
{
    $day = DateTime::createFromFormat('m-d-Y', $date);
    $day->setISODate((int)$day->format('o'), (int)$day->format('W'), 1);
    return $day->format('m-d-Y');
}

var_dump(firstDayOfWeek('06-13-2013'));

Output:-

string '06-10-2013' (length=10)

This will deal with year boundaries and leap years.


A smart way of doing this is to let PHP handle timezone differences and Daylight Savings Time (DST). Let me show you how to do this.

This function will generate all days from Monday until Friday, inclusive (handy for generating work week days):

class DateTimeUtilities {
    public static function getPeriodFromMondayUntilFriday($offset = 'now') {
        $now = new \DateTimeImmutable($offset, new \DateTimeZone('UTC'));
        $today = $now->setTime(0, 0, 1);

        $daysFromMonday = $today->format('N') - 1;

        $monday = $today->sub(new \DateInterval(sprintf('P%dD', $daysFromMonday)));
        $saturday = $monday->add(new \DateInterval('P5D'));

        return new \DatePeriod($monday, new \DateInterval('P1D'), $saturday);
    }
}

foreach (DateTimeUtilities::getPeriodFromMondayUntilFriday() as $day) {
    print $day->format('c');
    print PHP_EOL;
}

This will return datetimes Monday-Friday for current week. To do the same for an arbitrary date, pass a date as a parameter to DateTimeUtilities ::getPeriodFromMondayUntilFriday, thus:

foreach (DateTimeUtilities::getPeriodFromMondayUntilFriday('2017-01-02T15:05:21+00:00') as $day) {
    print $day->format('c');
    print PHP_EOL;
}

//prints 
//2017-01-02T00:00:01+00:00
//2017-01-03T00:00:01+00:00
//2017-01-04T00:00:01+00:00
//2017-01-05T00:00:01+00:00
//2017-01-06T00:00:01+00:00

Only interested in Monday, as the OP asked?

$monday = DateTimeUtilities::getPeriodFromMondayUntilFriday('2017-01-02T15:05:21+00:00')->getStartDate()->format('c');
print $monday;
// prints
//2017-01-02T00:00:01+00:00

This is the shortest and most readable solution I found:

    <?php
    $weekstart = strtotime('monday this week');
    $weekstop = strtotime('sunday this week 23:59:59');
    //echo date('d.m.Y H:i:s', $weekstart) .' - '. date('d.m.Y H:i:s', $weekstop);
    ?>

strtotime is faster than new DateTime()->getTimestamp().


Here's a one liner for the first day of last week, and the last day of last week as a DateTime object.

$firstDay = (new \DateTime())->modify(sprintf('-%d day', date('w') + 7))
                             ->setTime(0, 0, 0);
$lastDay = (new \DateTime())->modify(sprintf('-%d day', date('w') + 1))
                            ->setTime(23, 59, 59);

You can use Carbon library as well

$dateString = '02-21-2015'; // example in format MM-dd-yyyy
$date = Carbon::createFromFormat('m-d-Y', $dateString);
$date->hour(0)->minute(0)->second(0)->startOfWeek();
$dateString = $date->Format('m-d-Y'); // and you have got a string value "02-16-2015"

In order to have the simplest code and have weeks starting on monday, I used this method:

$day = (date('w')+6)%7; //transform week start from sunday to monday
$time = strtotime('-'.$day.' days');

I found this solution helpful. Just subtract if it isn't monday to get the previous Monday. I am using $lower_date as the date I pulled from a query that I then need to reconcile to the previous Monday.

//set this up to go backwards until you find monday
while(date('D',strtotime($lower_date))!='Mon'){
    $lower_date = date('Y-m-d', strtotime($lower_date . ' - 1 day')); //increase the upper spec
}

Given PHP version pre 5.3 following function gives you a first day of the week of given date (in this case - Sunday, 2013-02-03):

<?php
  function startOfWeek($aDate){
    $d=strtotime($aDate);
    return strtotime(date('Y-m-d',$d).' - '.date("w",$d).' days');
  }

  echo(date('Y-m-d',startOfWeek("2013-02-07")).'
');
?>

Keep it simple :

<?php    
$dateTime = new \DateTime('2020-04-01');
$monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week');
$sunday = clone $dateTime->modify('Sunday this week');    
?>

Source : PHP manual

NB: as some user commented the $dateTime value will be modified.


I've come against this question a few times and always surprised the date functions don't make this easier or clearer. Here's my solution for PHP5 that uses the DateTime class:

/**
 * @param DateTime $date A given date
 * @param int $firstDay 0-6, Sun-Sat respectively
 * @return DateTime
 */
function getFirstDayOfWeek(DateTime $date, $firstDay = 0) {
    $offset = 7 - $firstDay;
    $ret = clone $date;
    $ret->modify(-(($date->format('w') + $offset) % 7) . 'days');
    return $ret;
}

Necessary to clone to avoid altering the original date.


just simply oneline answer ;)

$mondayThisWeek = new Date($date . 'this week monday');

I found this quite frustrating given that my timezone is Australian and that strtotime() hates UK dates.

If the current day is a Sunday, then strtotime("monday this week") will return the day after.

To overcome this:

Caution: This is only valid for Australian/UK dates

$startOfWeek = (date('l') == 'Monday') ? date('d/m/Y 00:00') : date('d/m/Y', strtotime("last monday 00:00"));
$endOfWeek = (date('l') == 'Sunday') ? date('d/m/Y 23:59:59') : date('d/m/Y', strtotime("sunday 23:59:59"));

What about:

$date = "2013-03-18"; 
$searchRow = date("d.m.Y", strtotime('last monday',strtotime($date." + 1 day")));
echo "for date " .$date ." we get this monday: " ;echo $searchRow; echo '<br>';

Its not the best way but i tested and if i am in this week i get the correct monday, and if i am on a monday i will get that monday.


How about this?

$day_of_week = date('N', strtotime($string_date));
$week_first_day = date('Y-m-d', strtotime($string_date . " - " . ($day_of_week - 1) . " days"));
$week_last_day = date('Y-m-d', strtotime($string_date . " + " . (7 - $day_of_week) . " days"));

Just use date($format, strtotime($date,' LAST SUNDAY + 1 DAY'));


$givenday = date("w", mktime(0, 0, 0, MM, dd, yyyy));

This gives you the day of the week of the given date itself where 0 = Sunday and 6 = Saturday. From there you can simply calculate backwards to the day you want.


$string_date = '2019-07-31';
echo $day_of_week = date('N', strtotime($string_date));
echo $week_first_day = date('Y-m-d', strtotime($string_date . " - " . ($day_of_week - 1) . " days"));
echo $week_last_day = date('Y-m-d', strtotime($string_date . " + " . (7 - $day_of_week) . " days"));

If you want Monday as the start of your week, do this:

$date = '2015-10-12';
$day = date('N', strtotime($date));
$week_start = date('Y-m-d', strtotime('-'.($day-1).' days', strtotime($date)));
$week_end = date('Y-m-d', strtotime('+'.(7-$day).' days', strtotime($date)));

This is what I am using to get the first and last day of the week from any date. In this case, monday is the first day of the week...

$date = date('Y-m-d') // you can put any date you want
$nbDay = date('N', strtotime($date));
$monday = new DateTime($date);
$sunday = new DateTime($date);
$monday->modify('-'.($nbDay-1).' days');
$sunday->modify('+'.(7-$nbDay).' days');

this one is prepared for today is monday

function lastMonday(\DateTime $date) {

    $timestamp = $date->getTimestamp();

    $monday = ( 1 == date( 'N', $timestamp ));

    if ($monday) {
        return $timestamp;
    } else {
        return strtotime( 'last monday', $timestamp );
    }
}

if you want it to get timestamp instead of DateTime change first two lines (get rid of date->getTimestamp) change them to just this

function lastMonday($timestamp) {

and if you want it to input string change first two lines to this

function lastMonday($dateString) {

    $timestamp = strtotime($dateString);

Should work:

/**
 * Returns start of most recent Sunday.
 * 
 * @param null|int $timestamp
 * @return int
 */
public static function StartOfWeek($timestamp = null) {
    if($timestamp === null) $timestamp = time();
    $dow = idate('w', $timestamp); // Sunday = 0, Monday = 1, etc.
    return mktime(0, 0, 0, idate('m', $timestamp), idate('d', $timestamp) - $dow, idate('Y', $timestamp));
}

Input and output are unix timestamps. Use date to format.


Very simple to use strtotime function:

echo date("Y-m-d", strtotime('monday this week')), "\n";   

echo date("Y-m-d", strtotime('sunday this week')), "\n";

It differs a bit across PHP versions:

Output for 5.3.0 - 5.6.6, php7@20140507 - 20150301, hhvm-3.3.1 - 3.5.1

2015-03-16
2015-03-22

Output for 4.3.5 - 5.2.17

2015-03-23
2015-03-22

Output for 4.3.0 - 4.3.4

2015-03-30
2015-03-29

Comparing at Edge-Cases

Relative descriptions like this week have their own context. The following shows the output for this week monday and sunday when it's a monday or a sunday:

$date = '2015-03-16'; // monday
echo date("Y-m-d", strtotime('monday this week', strtotime($date))), "\n";   
echo date("Y-m-d", strtotime('sunday this week', strtotime($date))), "\n";

$date = '2015-03-22'; // sunday
echo date("Y-m-d", strtotime('monday this week', strtotime($date))), "\n";   
echo date("Y-m-d", strtotime('sunday this week', strtotime($date))), "\n";

Againt it differs a bit across PHP versions:

Output for 5.3.0 - 5.6.6, php7@20140507 - 20150301, hhvm-3.3.1 - 3.5.1

2015-03-16
2015-03-22
2015-03-23
2015-03-29

Output for 4.3.5 - 5.0.5, 5.2.0 - 5.2.17

2015-03-16
2015-03-22
2015-03-23
2015-03-22

Output for 5.1.0 - 5.1.6

2015-03-23
2015-03-22
2015-03-23
2015-03-29

Output for 4.3.0 - 4.3.4

2015-03-23
2015-03-29
2015-03-30
2015-03-29

How about this?

$first_day_of_week = date('m-d-Y', strtotime('Last Monday', time()));
$last_day_of_week = date('m-d-Y', strtotime('Next Sunday', time()));

The following code should work with any custom date, just uses the desired date format.

$custom_date = strtotime( date('d-m-Y', strtotime('31-07-2012')) ); 
$week_start = date('d-m-Y', strtotime('this week last monday', $custom_date));
$week_end = date('d-m-Y', strtotime('this week next sunday', $custom_date));
echo '<br>Start: '. $week_start;
echo '<br>End: '. $week_end;

I tested the code with PHP 5.2.17 Results:

Start: 30-07-2012
End: 05-08-2012

I was searching for a solution similar to this and I finally came up with something that will return each day of the current week.

//set current timestamp
$today = time();
//calculate the number of days since Monday
$dow = date('w', $today);
  $offset = $dow - 1;
if ($offset < 0) {
  $offset = 6;
  }
//calculate timestamp for Monday and Sunday
$monday = $today - ($offset * 86400);
$tuesday = $monday + (1 * 86400);
$wednesday = $monday + (2 * 86400);
$thursday = $monday + (3 * 86400);
$friday = $monday + (4 * 86400);
$saturday = $monday + (5 * 86400);
$sunday = $monday + (6 * 86400);
//print dates for Monday and Sunday in the current week
print date("Y-m-d", $monday) . "\n";
print date("Y-m-d", $tuesday) . "\n";
print date("Y-m-d", $wednesday) . "\n";
print date("Y-m-d", $thursday) . "\n";
print date("Y-m-d", $friday) . "\n";
print date("Y-m-d", $saturday) . "\n";
print date("Y-m-d", $sunday) . "\n";

Thank you to dbunic who posted this here: http://www.redips.net/php/week-list-current-date/#comments


I use it:

$firstDate = date( 'Y-m-d', strtotime( 'Last Monday', strtotime('-1 week') ));
$lastDate = date( 'Y-m-d', strtotime( 'First Sunday', strtotime('-1 week') ));

Hope this help you!


$monday = date('d-m-Y',strtotime('last monday',strtotime('next monday',strtotime($date))));

You have to get next monday first then get the 'last monday' of next monday. So if the given date is monday it will return the same date not last week monday.


You parse the date using strptime() and use date() on the result:

date('N', strptime('%m-%d-%g', $dateString));

EDIT: the below link is no longer running on the version of PHP stated. It is running on PHP 5.6 which improves the reliability of strtotime, but isn't perfect! The results in the table are live results from PHP 5.6.

For what it's worth, here is a breakdown of the wonky behavior of strtotime when determining a consistent frame of reference:

http://gamereplays.org/reference/strtotime.php

Basically only these strings will reliably give you the same date, no matter what day of the week you're currently on when you call them:

strtotime("next monday");
strtotime("this sunday");
strtotime("last sunday"); 

Try this:

function week_start_date($wk_num, $yr, $first = 1, $format = 'F d, Y')
{
    $wk_ts  = strtotime('+' . $wk_num . ' weeks', strtotime($yr . '0101'));
    $mon_ts = strtotime('-' . date('w', $wk_ts) + $first . ' days', $wk_ts);
    return date($format, $mon_ts);
}

$sStartDate = week_start_date($week_number, $year);
$sEndDate   = date('F d, Y', strtotime('+6 days', strtotime($sStartDate)));

(from this forum thread)


Assuming Monday as the first day of the week, this works:

echo date("M-d-y", strtotime('last monday', strtotime('next week', time())));

$today_day = date('D'); //Or add your own date
$start_of_week = date('Ymd');
$end_of_week = date('Ymd');

if($today_day != "Mon")
    $start_of_week = date('Ymd', strtotime("last monday"));

if($today_day != "Sun")
                    $end_of_week = date('Ymd', strtotime("next sunday"));