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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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 13:01:33 2025 UTC