96

I want to take a date and work out its week number.

So far, I have the following. It is returning 24 when it should be 42.

<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[2], $duedt[1],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>

Is it wrong and a coincidence that the digits are reversed? Or am I nearly there?

Pang
  • 9,564
  • 146
  • 81
  • 122
AJFMEDIA
  • 2,093
  • 6
  • 29
  • 52

19 Answers19

210

Today, using PHP's DateTime objects is better:

<?php
$ddate = "2012-10-18";
$date = new DateTime($ddate);
$week = $date->format("W");
echo "Weeknummer: $week";

It's because in mktime(), it goes like this:

mktime(hour, minute, second, month, day, year);

Hence, your order is wrong.

<?php
$ddate = "2012-10-18";
$duedt = explode("-", $ddate);
$date  = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
$week  = (int)date('W', $date);
echo "Weeknummer: " . $week;
?>
Madara's Ghost
  • 172,118
  • 50
  • 264
  • 308
  • 4
    You can use Carbon, "https://github.com/briannesbitt/Carbon" to maximize your skills in Date manipulation. For carbon you can do that by: `Carbon::createFromFormat('Y-m-d H', '2012-10-18')->format('W');` – lukaserat May 04 '14 at 07:20
  • 28
    Actually, you're better off just using PHP's native DateTime objects. – Madara's Ghost May 04 '14 at 07:28
  • 5
    @lukaserat How is that any different from what the accepted answer uses (besides the fact OP has to include an external dependency for something that is already native in the language)? – PeeHaa Jul 27 '14 at 14:23
  • @PeeHaa In many times I don't want to DRY my codes, if there is already good one. – lukaserat Jul 28 '14 at 01:30
  • 1
    I would say that the order in `mktime()` is wrong, not the OP's order. Of course, the latter is easier to change. – beetstra Aug 07 '14 at 08:02
  • @beetstra I'd say that today, in 2014, if you use `mktime()` instead of `new DateTime`, it's most definitely **you** who are wrong :) – Madara's Ghost Aug 07 '14 at 09:14
  • As fedmich also suggested, use `new DateTime($date, new DateTimeZone('Europe/Amsterdam'));` for your own timezone :) – Refilon Apr 11 '17 at 14:14
  • 3
    If the last week of December is also the first week of next year, (like in 2019), then you will get week number as 1, for dates falling in that week (like 30, 31) – Shah Abaz Khan Mar 20 '19 at 06:56
  • @Shah Abaz Khan In such cases where you need the year information, you can use strftime(). I've added it as an answer to this question. – Drea58 Nov 02 '20 at 16:28
63
$date_string = "2012-10-18";
echo "Weeknummer: " . date("W", strtotime($date_string));
pbond
  • 1,888
  • 4
  • 19
  • 35
22

Use PHP's date function
http://php.net/manual/en/function.date.php

date("W", $yourdate)
Pang
  • 9,564
  • 146
  • 81
  • 122
cjtech
  • 459
  • 2
  • 8
14

This get today date then tell the week number for the week

<?php
 $date=date("W");
 echo $date." Week Number";
 ?>
user3133144
  • 177
  • 1
  • 2
9

Just as a suggestion:

<?php echo date("W", strtotime("2012-10-18")); ?>

Might be a little simpler than all that lot.

Other things you could do:

<?php echo date("Weeknumber: W", strtotime("2012-10-18 01:00:00")); ?>
<?php echo date("Weeknumber: W", strtotime($MY_DATE)); ?>
Andrew Myers
  • 451
  • 3
  • 13
4

Becomes more difficult when you need year and week.
Try to find out which week is 01.01.2017.
(It is the 52nd week of 2016, which is from Mon 26.12.2016 - Sun 01.01.2017).

After a longer search I found

strftime('%G-%V',strtotime("2017-01-01"))

Result: 2016-52


https://www.php.net/manual/de/function.strftime.php
ISO-8601:1988 week number of the given year, starting with the first week of the year with at least 4 weekdays, with Monday being the start of the week. (01 through 53)


The equivalent in mysql is DATE_FORMAT(date, '%x-%v') https://www.w3schools.com/sql/func_mysql_date_format.asp
Week where Monday is the first day of the week (01 to 53).


Could not find a corresponding solution with DateTime.
At least not without solutions like "+1day, last monday".


Edit: since strftime is now deprecated, maybe you can also use date. Didn't verify it though.

date('o-W',strtotime("2017-01-01"));
Drea58
  • 429
  • 2
  • 6
  • This is a neat solution for year and week, though unfortunately `strftime()` has been deprecated as of PHP 8.1.0 https://www.php.net/manual/en/function.strftime.php – S.Walsh Jan 09 '22 at 23:54
2

I have tried to solve this question for years now, I thought I found a shorter solution but had to come back again to the long story. This function gives back the right ISO week notation:

/**
 * calcweek("2018-12-31") => 1901
 * This function calculates the production weeknumber according to the start on 
 * monday and with at least 4 days in the new year. Given that the $date has
 * the following format Y-m-d then the outcome is and integer.
 *
 * @author M.S.B. Bachus
 *
 * @param date-notation PHP "Y-m-d" showing the data as yyyy-mm-dd
 * @return integer
 **/
function calcweek($date) {
  // 1. Convert input to $year, $month, $day
  $dateset      = strtotime($date);
  $year         = date("Y", $dateset);
  $month        = date("m", $dateset);
  $day          = date("d", $dateset);

  $referenceday = getdate(mktime(0,0,0, $month, $day, $year));
  $jan1day      = getdate(mktime(0,0,0,1,1,$referenceday[year]));

  // 2. check if $year is a  leapyear
  if ( ($year%4==0 && $year%100!=0) || $year%400==0) {
    $leapyear = true;
  } else {
    $leapyear = false;
  }

  // 3. check if $year-1 is a  leapyear
  if ( (($year-1)%4==0 && ($year-1)%100!=0) || ($year-1)%400==0 ) {
    $leapyearprev = true;
  } else {
    $leapyearprev = false;
  }

  // 4. find the dayofyearnumber for y m d
  $mnth = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
  $dayofyearnumber = $day + $mnth[$month-1];
  if ( $leapyear && $month > 2 ) { $dayofyearnumber++; }

  // 5. find the jan1weekday for y (monday=1, sunday=7)
  $yy = ($year-1)%100;
  $c  = ($year-1) - $yy;
  $g  = $yy + intval($yy/4);
  $jan1weekday = 1+((((intval($c/100)%4)*5)+$g)%7);

  // 6. find the weekday for y m d
  $h = $dayofyearnumber + ($jan1weekday-1);
  $weekday = 1+(($h-1)%7);

  // 7. find if y m d falls in yearnumber y-1, weeknumber 52 or 53
  $foundweeknum = false;
  if ( $dayofyearnumber <= (8-$jan1weekday) && $jan1weekday > 4 ) {
    $yearnumber = $year - 1;
    if ( $jan1weekday = 5 || ( $jan1weekday = 6 && $leapyearprev )) {
      $weeknumber = 53;
    } else {
      $weeknumber = 52;
    }
    $foundweeknum = true;
  } else {
    $yearnumber = $year;
  }

  // 8. find if y m d falls in yearnumber y+1, weeknumber 1
  if ( $yearnumber == $year && !$foundweeknum) {
    if ( $leapyear ) {
      $i = 366;
    } else {
      $i = 365;
    }
    if ( ($i - $dayofyearnumber) < (4 - $weekday) ) {
      $yearnumber = $year + 1;
      $weeknumber = 1;
      $foundweeknum = true;
    }
  }

  // 9. find if y m d falls in yearnumber y, weeknumber 1 through 53
  if ( $yearnumber == $year && !$foundweeknum ) {
    $j = $dayofyearnumber + (7 - $weekday) + ($jan1weekday - 1);
    $weeknumber = intval( $j/7 );
    if ( $jan1weekday > 4 ) { $weeknumber--; }
  }

  // 10. output iso week number (YYWW)
  return ($yearnumber-2000)*100+$weeknumber;
}

I found out that my short solution missed the 2018-12-31 as it gave back 1801 instead of 1901. So I had to put in this long version which is correct.

2

How about using the IntlGregorianCalendar class?

Requirements: Before you start to use IntlGregorianCalendar make sure that libicu or pecl/intl is installed on the Server. So run on the CLI:

php -m

If you see intl in the [PHP Modules] list, then you can use IntlGregorianCalendar.

DateTime vs IntlGregorianCalendar: IntlGregorianCalendar is not better then DateTime. But the good thing about IntlGregorianCalendar is that it will give you the week number as an int.

Example:

$dateTime = new DateTime('21-09-2020 09:00:00');
echo $dateTime->format("W"); // string '39'

$intlCalendar = IntlCalendar::fromDateTime ('21-09-2020 09:00:00');
echo $intlCalendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); // integer 39
Julian
  • 4,396
  • 5
  • 39
  • 51
1

To get the week number for a date in North America I do like this:

function week_number($n)
{
    $w = date('w', $n);
    return 1 + date('z', $n + (6 - $w) * 24 * 3600) / 7;
}

$n = strtotime('2022-12-27');
printf("%s: %d\n", date('D Y-m-d', $n), week_number($n));

and get:

Tue 2022-12-27: 53

Kjeld
  • 131
  • 1
  • 3
1

for get week number in jalai calendar you can use this:

$weeknumber = date("W"); //number week in year
$dayweek = date("w"); //number day in week
if ($dayweek == "6")
{
    $weeknumberint = (int)$weeknumber;
    $date2int++; 
    $weeknumber = (string)$date2int;
}

echo $date2;

result:

15

week number change in saturday

Majid RigiZadeh
  • 116
  • 1
  • 3
  • 1
    Welcome to stackoverflow.com. Interesting side point that weeknumbers change differently in different calendars. However, please use a DateTime-object for your code. Furthermore you are not declaring variables before using them. It is allowed in PHP, but not considered best practice. Anyhow, thank you for your first contribution. – Loek Bergman Apr 10 '20 at 08:32
1

The most of the above given examples create a problem when a year has 53 weeks (like 2020). So every fourth year you will experience a week difference. This code does not:

$thisYear = "2020";
$thisDate = "2020-04-24"; //or any other custom date
$weeknr = date("W", strtotime($thisDate)); //when you want the weeknumber of a specific week, or just enter the weeknumber yourself

$tempDatum = new DateTime();
$tempDatum->setISODate($thisYear, $weeknr);
$tempDatum_start = $tempDatum->format('Y-m-d');
$tempDatum->setISODate($thisYear, $weeknr, 7);
$tempDatum_end = $tempDatum->format('Y-m-d');

echo $tempDatum_start //will output the date of monday
echo $tempDatum_end // will output the date of sunday
Jeffrey
  • 11
  • 1
1

Very simple Just one line:

<?php $date=date("W"); echo "Week " . $date; ?>"

You can also, for example like I needed for a graph, subtract to get the previous week like:

<?php $date=date("W"); echo "Week " . ($date - 1); ?>
Spinstaz
  • 287
  • 6
  • 12
1
<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>

You had the params to mktime wrong - needs to be Month/Day/Year, not Day/Month/Year

FreudianSlip
  • 2,870
  • 25
  • 24
0

To get Correct Week Count for Date 2018-12-31 Please use below Code

$day_count = date('N',strtotime('2018-12-31'));
$week_count = date('W',strtotime('2018-12-31'));    


if($week_count=='01' && date('m',strtotime('2018-12-31'))==12){
    $yr_count = date('y',strtotime('2018-12-31')) + 1;
}else{
    $yr_count = date('y',strtotime('2018-12-31'));
}
Bhushan D
  • 1
  • 1
0

You can use Carbon https://carbon.nesbot.com/docs/

<?php
$now = Carbon::now();
$weekOfYear = Carbon->weekOfYear;
liiker
  • 1
  • 2
0

The rule is that the first week of a year is the week that contains the first Thursday of the year.

I personally use Zend_Date for this kind of calculation and to get the week for today is this simple. They have a lot of other useful functions if you work with dates.

$now = Zend_Date::now();
$week = $now->get(Zend_Date::WEEK);
// 10
Elzo Valugi
  • 27,240
  • 15
  • 95
  • 114
0

Your code will work but you need to flip the 4th and the 5th argument.

I would do it this way

$date_string = "2012-10-18";
$date_int = strtotime($date_string);
$date_date = date($date_int);
$week_number = date('W', $date_date);
echo "Weeknumber: {$week_number}.";

Also, your variable names will be confusing to you after a week of not looking at that code, you should consider reading http://net.tutsplus.com/tutorials/php/why-youre-a-bad-php-programmer/

Jake
  • 4,134
  • 2
  • 16
  • 20
-1
function last_monday($date) 
{
    if (!is_numeric($date))
        $date = strtotime($date);
    if (date('w', $date) == 1)
        return $date;
    else
        return date('Y-m-d',strtotime('last monday',$date));
}
$date = '2021-01-04';  //Enter custom date
$year = date('Y',strtotime($date));
$date1 = new DateTime($date);
$ldate = last_monday($year."-01-01");
$date2 = new DateTime($ldate);
$diff = $date2->diff($date1)->format("%a");
$diff = $diff/7;
$week = intval($diff) + 1;
echo $week;
//Returns 2.
Muthu Kumar
  • 107
  • 1
  • 2
-1

try this solution

date( 'W', strtotime( "2017-01-01 + 1 day" ) );
Unamata Sanatarai
  • 6,475
  • 3
  • 29
  • 51
  • 2017-01-01 is a Sunday. Adding a day moves you into the next week, with weeks starting from Monday. 2017-01-01 is the 52th Week of 2016. – Drea58 Nov 02 '20 at 08:46