echo date("W",strtotime('2010-01-01'));
This outputs 53. I would expect it to output 1. Can anyone else confirm this behavior, or maybe explain why? I couldn't find a bug report on it.
This isn't a bug at all, it's expected behaviour. From PHP's Date Page:
W: ISO-8601 week number of year, weeks starting on Monday
Jan 1, 2010, fell on a Friday, so its week number would belong to 2009, making it part of the 53rd week of 2009. Jan 4, 2010 would be week 1.
A week which begins in December and ends in January the following year belongs to the year where most of its days lie. Therefore a week with at least 4 days in December is the last week of that year and a week with at least 4 days in January is the first week in the new year.
So... the last week of a year always contains the 28th day of December. If you take date("W") on that day of a given year you always get the correct number of weeks for that year. The other end of that definition is that the 4th day of January always lies in the first week of a year.
It returns the ISO-8601 week number of year.
From Wikipedia:
There are mutually equivalent descriptions of week 01:
the week with the year's first Thursday in it (the formal ISO definition),
the week with 4 January in it,
the first week with the majority (four or more) of its days in the starting year, and
the week starting with the Monday in the period 29 December – 4 January.
Since 2010-01-01 was a Friday, non of the conditions is met.
Related
is there any parameter or configuratión to provide to a DateTime object to not consider week number in iso but taking the first day of january as the first week of the year?
As Datetime works with an ISO rule, the first week of the year is the week with the first thursday.
I need to make some operations with datetimes but i need it to consider the first day of January as the first week of the year, even if its a Sunday.
Is this possible? I tried everything.
Thank you.
Don’t think that is possible with the native DateTime, no - that only follows ISO 8601 rules. You’d have to handle that yourself, by taking the difference between Jan 1st vs Jan 4th as start of the first week into account in all places where you operate with those values.
You should consider using a date library such as Carbon - with the proper locale set, that should be able to do what you want.
https://carbon.nesbot.com/docs/#api-week:
Week methods follow the rules of the current locale (for example with en_US, the default locale, the first day of the week is Sunday, and the first week of the year is the one that contains January 1st)
There is no option to set the start weekday of first week.
You can only use following format for week number of the day:
%U - week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week
%V - The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week. (Use %G or %g for the year component that corresponds to the week number for the specified timestamp.)
%W - week number of the current year as a decimal number, starting with the first Monday as the first day of the first week
So if you want to calculate week number assuming 1st day of year as first week of year, then you have to make your own function to add 1 if 1st Jan is not Thursday or before.
Taken from my own answer and adjusted for dateTime and the year starting with week 1.
function get_week($date){
$w=(int)$date->format('W');
$m=(int)$date->format('n');
return $w==1?($m==12?53:1):($w>=51?($m==1?1:$w):$w);
}
2016-01-01 is officially week 53, but the function returns 1. Week 1 now has 10 days, till 2016-01-01. Week 2 starts at 2016-01-11
Function below provides week number 01-53 starting 1st of January. Note: in such way the first and the last week of the year could be less than 7 days.
function getWeekNumberStartingJan1(DateTime $date)
{
if ((clone $date)->modify('1 january')->format('W') !== '01') {
if ($date->format('o') !== $date->format('Y')) {
return '01';
}
return sprintf('%02d', (int)$date->format('W') + 1);
}
return $date->format('W'); //year started from Monday
}
date("YW", strtotime("2016-01-02")); returns “201653”
Year is OK
Week is from 2015
PHP is ISO-8601 compliant with dates:
The purpose of this standard is to provide an unambiguous and well-defined method of representing dates and times, so as to avoid misinterpretation of numeric representations of dates and times, particularly when data are transferred between countries with different conventions for writing numeric dates and times.
This means the first week of the year is defined as:
the week with the year's first Thursday in it
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year (there is no week 00).
This means January 2nd of 2016 is not in week one of 2016 as far as PHP is concerned.
If you use the o flag for date() you will get the ISO-8601 year which wilol return 2015:
echo date("oW", strtotime("2016-01-02"));
// outputs: 201553
Demo
One way you may want to consider is checking if the month is January and the week number is 53 then it is the first week of the new calendar year (not ISO-8601 year).
if (date('n') == 1 && date('W') == 53) {
// first calendar week of the year
}
Demo
PHP uses ISO-8601 week number of year, weeks starting on Monday. If January 1st of a year is not on a Monday, that particular week is deemed to be the final week of the previous year; week 53.
Because January 1st 2016 was a Friday, it is part of the week commencing December 28th 2015. If you run the code echo date('Y-W', strtotime('2015-12-31')); you will get the output '2015-53', so the days of the same week will also be week 53 according to ISO-8601.
PHP is using the ISO-8601 specification for week numbers.
Definition of the first week of the year (ISO 8601):
There are mutually equivalent descriptions of week 01:
the week with the year's first Thursday in it (the formal ISO definition),
the week with 4 January in it,
the first week with the majority (four or more) of its days in the starting year, and
the week starting with the Monday in the period 29 December – 4 January.
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01.
If 1 January is on a Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year (there is no week 00). 28 December is always in the last week of its year.
https://en.wikipedia.org/wiki/ISO_8601#Week_dates
Here a example:
echo date("YW", strtotime("2016-01-02")); //201653
echo date("YW", strtotime("2016-01-04")); //201601
Can someone explain why this is so?
<?php
echo date("W", strtotime("2015-01-01"))."<br>"; //returns 1
echo date("W", strtotime("2014-01-01"))."<br>"; //returns 1
echo date("W", strtotime("2016-01-01"))."<br>"; //returns 53
?>
When outputing the week number of the day in the month , result is incorrect for some cases. Here the output, week number is 1 which is true for first two cases but not in the third case.
The reason it outputs 53 and not 1 for "2016-01-01" is that it counts the first week of the year from the first monday of the year which in the year 2016 lies on the 4th of Jan ("2016-01-04").
W ISO-8601 week number of year, weeks starting on Monday (added in PHP
4.1.0) Example: 42 (the 42nd week in the year)
See full documentation for php date function here.
As mentioned, W ISO-8601 week number of year is the number that you get.
For more information on W ISO-8601 week number of year see below,
An ISO week-numbering year (also called ISO year informally) has 52 or
53 full weeks. That is 364 or 371 days instead of the usual 365 or 366
days. The extra week is referred to here as a leap week, although ISO
8601 does not use this term. Weeks start with Monday. The first week
of a year is the week that contains the first Thursday of the year
(and, hence, always contains 4 January). ISO week year numbering
therefore slightly deviates from the Gregorian for some days close to
1 January.
Source: Wiki
2016-01-01 belongs to the last week of year 2015, as the week begins in that year, so the result is correct.
I used this code to get the 1st date, of the 1st week, of the year:
echo date('Y-m-d',strtotime('2018W01')); #JAN 1 is Monday, returned 01/01
echo date('Y-m-d',strtotime('2013W01')); #JAN 1 is Tuesday, returned 12/31
echo date('Y-m-d',strtotime('2014W01')); #JAN 1 is Wednesday, returned 12/30
echo date('Y-m-d',strtotime('2015W01')); #JAN 1 is Thursday, returned 12/29
echo date('Y-m-d',strtotime('2016W01')); #JAN 1 is Friday, returned 01/04!? (shouldn't it be 12/28)
echo date('Y-m-d',strtotime('2022W01')); #JAN 1 is Saturday, returned 01/03!? (shouldn't it be 12/27)
echo date('Y-m-d',strtotime('2017W01')); #JAN 1 is Sunday, returned 01/02!? (shouldn't it be 12/26)
Since PHP, which is greater than 5.2.7, showing me that Monday is the 1st day of the week, then I was hoping that the year 2017, 1st day of week, should be 12/26. Is there a week number configuration somewhere for PHP to display 1st day, of the week, of the year correctly, for every year? TIA
echo date('Y-m-d',strtotime('2016W01'));
#JAN 1 is Friday, returned 01/04!? (shouldn't it be 12/28)
No, it shouldn't be 12/28, because first week of the year has this rules:
It is the first week with a majority (4 or more) of its days in January.
Its first day is the Monday nearest to 1 January.
It has 4 January in it. Hence the earliest possible dates are 29 December through 4 January, the latest 4 through 10 January.
It has the year's first working day in it, if Saturdays, Sundays and 1 January are not working days.
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, it is part of week 53 of the previous year; if on a Saturday, it is part of week 52 (or 53 if the previous year was a leap year); if on a Sunday, it is part of week 52 of the previous year.
Other examples are also correct. Read more here.
As the headline says, PHP's date("W") function gives back the calendar week (for the current day). Unfortunatly it gives back 52 or 53 for the first day(s) of most years. This is, in a simple thinking way, correct, but very annoying, as January 1st of 2012 is not calendar week 52, it's NOT a calendar week of the current year. Most calendars define this as week 0 or week 52 of the previous year.
This is very tricky when you group each day of the year by their calendar week: 1st of January 2012 and 31st of December 2012 are both put into the same calendar week group.
So my question is: Is there a (native) year-sensitive alternative to PHP's date("W") ?
EDIT: I think I wrote the first version of this question in a very unclear way, so this is my edit: I'm searching for a function that gives back the correct calendar week for the first day(s) of the year. PHP's date("W") gives back 52 for the 1st of January 2012, which is "wrong". It should be 0 or null. According to official sources, the first calendar week of a year starts on the first monday of the year. So, if the first day of a year is not a monday, it's not week 1 ! It's week 0. The wikipedia article says
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year.
This becomes tricky as the last days of the year are also in week 52/53. date("W") does not divide into current year and previous year.
This solution converts the excess of december to week 53 and everything in january prior to week 1 to week 0.
$w=(int)date('W');
$m=(int)date('n');
$w=$w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w);
echo "week $w in ".date('Y');
2013-12-31 ==> week 53 in 2013
2014-01-01 ==> week 1 in 2014
2015-12-31 ==> week 52 in 2015
2016-01-01 ==> week 0 in 2016
And a small test run, so you can see for yourself ;-)
$id=array(25,26,27,28,29,30,31,1,2,3,4,5,6,7,8);
for($iy=2013;$iy<2067;++$iy){foreach($id as $k=>$v){if($k<7){$im=12;}else{$im=1;}
if($k==7){++$iy;echo '====<br>';}$tme=strtotime("$im/$v/$iy");
echo date('d-m-Y',$tme),' * * ';
//THE ACTUAL CODE =================
$w=(int)date('W',$tme);
$m=(int)date('n',$tme);
$w=$w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w);
//THE ACTUAL CODE =================
echo '<b>WEEK: ',$w,' --- ','YEAR: ',date('Y',$tme),'</b><br>';}--$iy;
echo '----------------------------------<br>';}
Is there a (native) year-sensitive alternative to PHP's date("W") ?
No, there isn't.
According to official sources, the first calendar week of a year starts on the first monday of the year.
I'm not sure what official sources you're referring to.
PHP's date("W") returns the week number according to ISO 8601. As an international standard, ISO 8601 counts as one of possibly many "official sources". If its definition of week numbers doesn't fit your application, you're free to use anything else you like.
If you use a non-standard definition of "first week of the year", or if you use an official source that's not widely recognized, expect to have to write your own function to replace date("W"). (I'm pretty sure you'll need to write a function.)
The date 2012-01-01 was a Sunday. ISO 8601, Wikipedia, and php agree that the ISO week number for 2012-01-01 is 52.
ISO 8601 doesn't define a week 0.
So, if the first day of a year is not a monday, it's not week 1 !
Neither ISO nor Wikipedia say that. ISO 8601 defines week number 1 as the week that has the year's first Thursday in it. For 2012, the first Thursday was on Jan 5, so week number 1 was Jan 2 to Jan 8. 2012-01-01 was in the final week of the previous year, in terms of ISO weeks.
If you want something different, you can play with arithmetic, division, and so on. (Try dividing date("z") by 7, for example.) Or you can store that data in a database, and have your weeks any way you like.
If you're dealing with accounting periods, I'd almost certainly store that data in a table in a database. It's pretty easy to generate that kind of data with a spreadsheet.
The text of data in a table is much easier to audit than the text of a php function, no matter how simple that function is. And the data is certain to be the same for any program that accesses it, no matter what language it's written in. (So if your database someday has programs written in 5 different languages accessing it, you don't have to write, test, and maintain 5 different functions to get the week number.)
$d = new DateTime('first monday january '.date('Y'));
echo $d->format("W");
Google brought me here, and I wanted to post the following to help others like me...
I am in the US, and use DayPilot, and it works as follows:
Week starts on Sun, not Mon.
Jan 1st is always Week 1.
If Jan 1st is not a Sunday, Week 1 is less than 7 days.
This all makes a lot of since to me!
Here is my PHP function to copy that behavior:
function ProperWeekNum($inDate)
{$outNum = $inDate->format('W');
//Make week start on Sunday
if ($inDate->format('D') == 'Sun') {$outNum++;}
//Fix begining of year
if (($outNum >= 52) && ($inDate->format('M') == 'Jan')) {$outNum = 1;}
//Fix WEEK #1 is 1-day (Sat)
else //...without this 2022 was off by 1 all year
{$jan1st = new DateTime($inDate->format('Y').'-01-01');
if ($jan1st->format('D') == 'Sat') {$outNum++;}
}
//Return without leading zero
return ltrim($outNum, '0');
}
I use the function as follows, so when I click on DayPilot, my custom popup's Week # always matches DayPilot's Week #:
$weeknum = ProperWeekNum($startdate);
if ($weeknum != ProperWeekNum($enddate))
{$weeknum .= '-'.ProperWeekNum($enddate);}
Probably won't help the OP, but hopefully it helps someone.