php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #40271 strtotime() produces unexpected results while using Day of week items
Submitted: 2007-01-29 11:20 UTC Modified: 2007-01-29 15:03 UTC
From: slomo at sonarkollektiv dot de Assigned:
Status: Not a bug Package: Date/time related
PHP Version: 5.2.0 OS: Mac OS X 10.4.8
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: slomo at sonarkollektiv dot de
New email:
PHP Version: OS:

 

 [2007-01-29 11:20 UTC] slomo at sonarkollektiv dot de
Description:
------------
I was looking for a neat solution for the task "get the date 
for a given weeknumber and weekyear". I thought I got it, but 
there is a strange behaviour if (and only if) week no. is 1 
and 4th of January is already a monday. See my code to 
reproduce the results, it's quite confusing.

The idea was:
- 4th of January is always in week no. 1
- add the missing weeks
- make it a monday of that week acording to the GNU Date Input 
Formats syntax descibed at http://www.gnu.org/software/tar/
manual/html_node/tar_114.html#SEC114

So either me or PHP still does not get it right.

Reproduce code:
---------------
function MondayOfWeek($year, $week) { 
	return strtotime("$year-01-04 UTC + " . ($week-1) . ' week last monday');
} 

for ($y = 1998; $y < 2012; $y++) {
	for ($w = 1; $w < 53; $w++) {
		$start = MondayOfWeek($y, $w);
		$end   = strtotime("+6 day", $start);
		
		echo "KW $w/$y: " . gmstrftime('%A, %x %X', $start) . ' - ' . gmstrftime('%A, %x %X', $end) . " ";
		echo '- reverse check (week/year): ' . gmstrftime('%V/%G', $start) . "\n";
		
		if ($w != gmstrftime('%V', $start) || $y != gmstrftime('%G', $start)) {
			echo "ERROR!\n";
		}
	}
	echo "<hr>\n";
}

Expected result:
----------------
accurate results for every week number and year with always 
the same behaviour ...

Actual result:
--------------
if week no. is 1 and 4th of January is already a monday, the 
function returns timestamps for the "previous week".

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-01-29 11:32 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.


 [2007-01-29 11:33 UTC] tony2001@php.net
And please do not forget about expected and actual results.
Thank you.
 [2007-01-29 11:50 UTC] derick@php.net
You can also just use "strtotime('2007W011')"; for Monday "1", of Week 1 ("01") of year 2007 ("2007").
 [2007-01-29 11:55 UTC] slomo at sonarkollektiv dot de
My "Reproduce code" was quite complete. Here it is again, 
this time it starts with <?php and ends with ?> :-)

I expect: using strtotime("last monday") should behave 
always the same. If you run my code you will see that it 
differs depending on the given date. My code is not complex, 
so I hope you get the point very soon.

This "Day of week items" are a little bit confusing, because 
if you have e.g. a $date for a monday and state strtotime
("$date last monday"), you get $date. I assume this is 
correct.

Anyway I would think it's just my fault if my function would 
be "off 1 week" for the whole year if the date is a monday 
every time. But this happens only for the first week, in any 
other week the result is like I learned strtotime() is doing 
it.

Can you follow?

<?php

function MondayOfWeek($year, $week) { 
	return strtotime("$year-01-04 UTC + " . ($week-1) . ' 
week last monday');
} 

for ($y = 1998; $y < 2012; $y++) {
	for ($w = 1; $w < 53; $w++) {
		$start = MondayOfWeek($y, $w);
		$end   = strtotime("+6 day", $start);
		
		echo "KW $w/$y: " . gmstrftime('%A, %x %X', $start) 
. ' - ' . gmstrftime('%A, %x %X', $end) . ' - reverse check 
(week/year): ' . gmstrftime('%V/%G', $start) . "<br />\n";
		
		if ($w != gmstrftime('%V', $start) || $y != 
gmstrftime('%G', $start)) {
			echo '<span style="color: red;">Oops, 
EXCEPTIONAL ERROR!</span>' . "<br />\n";
		}
	}
	echo "<hr>\n";
}

?>

best regards,
  slomo
 [2007-01-29 12:01 UTC] tony2001@php.net
Could you please just paste something like this:
code :
strftime("<something>")

actual result:
<something you can actually see>

expected result:
<something you expected to see>

I really don't think those functions, cycles and HTML output are required to demonstrate a problem with strftime().

 [2007-01-29 12:02 UTC] slomo at sonarkollektiv dot de
thanks derick@php.net, that's brilliant :)

and it seems to be bug free. I still think my code produced a 
bug in PHP and I do not get why this happens.
 [2007-01-29 12:22 UTC] slomo at sonarkollektiv dot de
code :
strtotime('1999-01-04 UTC + 1 week last monday');
strtotime('1999-01-11 UTC + 0 week last monday');

actual result:
916012800
915408000

expected result:
at least the same value

Another example

code :
strtotime('1999-01-04 UTC + 0 week last monday');
strtotime('1999-01-04 UTC + 1 week last monday');
strtotime('1999-01-04 UTC + 2 week last monday');

actual result:
914803200
916012800
916617600

expected result:
at least always the same gap (604800 is a week), but it 
differs
 [2007-01-29 13:20 UTC] slomo at sonarkollektiv dot de
Just to point out why I think somethings weird, compare the 
previous code and result to this one.

code:
strtotime('2000-01-04 UTC + 1 week last monday');
strtotime('2000-01-11 UTC + 0 week last monday');

actual result:
947462400
947462400

expected result:
947462400
947462400

> same value, fine.

And the same for

code:
strtotime('2000-01-04 UTC + 0 week last monday');
strtotime('2000-01-04 UTC + 1 week last monday');
strtotime('2000-01-04 UTC + 2 week last monday');

actual result:
946857600
947462400
948067200

expected result:
946857600
947462400
948067200

> always the same gap (604800 is a week), fine.
 [2007-01-29 13:25 UTC] tony2001@php.net
code :
>strtotime('1999-01-04 UTC + 1 week last monday');
>strtotime('1999-01-11 UTC + 0 week last monday');

>actual result:
>916012800
>915408000

>expected result:
>at least the same value

Your expectation is wrong.
1999-01-04 is Monday, so "last monday" for 1999-01-04 is "1999-01-04 minus 1 week" and "last monday" 1999-01-11 is 1999-01-04.

>expected result:
>at least always the same gap (604800 is a week), but it 
>differs

See previous explanation.
No bug here.

 [2007-01-29 14:38 UTC] slomo at sonarkollektiv dot de
> Your expectation is wrong.
> 1999-01-04 is Monday, so "last monday" for 1999-01-04 is 
"1999-01-04
> minus 1 week" and "last monday" 1999-01-11 is 1999-01-04.

I still do not agree. I expect:

code :
strtotime("1999-01-04 UTC + 1 week last monday");
strtotime("1999-01-11 UTC + 0 week last monday");

1999-01-04 is monday
1999-01-11 is monday too

If you say:
"1999-01-04 UTC + 1 week last monday" means "1999-01-04 
minus 1 week" (because 1999-01-04 is monday) 
you forgot to mention the "+ 1 week" in the expression, this 
makes "1999-01-04 minus 1 week plus 1 week" for me
= 1999-01-04 , or?

following you explanation
"1999-01-11 UTC + 0 week last monday" then means "1999-01-11 
minus 1 week" (because 1999-01-11 is monday too)
and again we have to consider "+ 0 week", this makes 
"1999-01-11 minus 1 week plus 0 week" for me
= 1999-01-04 , or do I miss something?


Next test:


code :
strtotime("1999-01-04 UTC + 0 week last monday");
strtotime("1999-01-04 UTC + 1 week last monday");
strtotime("1999-01-04 UTC + 2 week last monday");

actual result:
914803200
916012800
916617600

expected result:
at least always the same gap (604800 is a week), but it 
differs

> See previous explanation.
> No bug here.

This answer is even more confusing for me.
1999-01-04 is monday, correct?

no matter how you turn it, either
"1999-01-04 last monday" = 1998-12-28    + X weeks    = 
something with always the same gap
or
"1999-01-04" + X weeks = a date, and a monday too -> now 
apply "last monday"    = something with always the same gap

(we are working with a monday, no matter how you turn it, so 
I expect strtotime() to behave alike, the only differing 
value is the "+ X weeks")

I still expect "something with always the same gap". Sorry 
for my stubbornness :(

At the moment I see that 
strtotime("1999-01-11 UTC last monday + 1 week")
and
strtotime("1999-01-11 UTC + 1 week last monday")
are giving different results ... now I give up :)

Thank you for your support even more for the neat solution 
using strtotime('2007W011').
 [2007-01-29 14:45 UTC] tony2001@php.net
It should be 
"1999-01-04 UTC + **0** week last monday" means "1999-01-04 minus 1 week" (because 1999-01-04 is monday).
 [2007-01-29 14:54 UTC] slomo at sonarkollektiv dot de
Ok, I think I got that and I did not claim anything else :-/

Are we talking about your code or my code now?

If we are talking about my example comparing strtotime
("1999-01-04 UTC + 1 week last monday") to strtotime
("1999-01-11 UTC + 0 week last monday") someone may fully 
read or comment my stressed post.

If we are talking about the meaning of "1999-01-04 UTC + 
**0** week last monday" I think we now just agree with each 
other.
 [2007-01-29 15:03 UTC] slomo at sonarkollektiv dot de
I'm sorry tony2001, but I still think I could not express 
myself.

You say (and I agree):
"1999-01-04 UTC + 0 week last monday" means "1999-01-04 
minus 1 week" (because 1999-01-04 is monday).
I add:
"1999-01-04 UTC + 1 week last monday" then means "1999-01-04 
plus 1 week minus 1 week"


I say (and I think you have to agree):
"1999-01-11 UTC + 0 week last monday" means "1999-01-11 
minus 1 week" (because 1999-01-11 is monday).


I expect:
"1999-01-04 plus 1 week minus 1 week" to be equivalent to
"1999-01-11 minus 1 week"

I expect the same value. But I don't get it.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 03 12:01:33 2025 UTC