« Why You Should Replace ENUM With Something Else | Designing Databases: Picking The Right Data Types » |
This morning, I was reviewing the weekly list of topics with the most comments throughout the PHP manual, and I stumbled upon the following code in the documentation for the date() function. This code is designed to tell you the day of the week for any valid date you give it:
<?php function return_day_of_week($date){ <span id="more-1045"></span> $sy=substr($date, 0, 4); $sm=substr($date, 5, 2); $sd=substr($date, 8, 2); $date_utc=mktime(0,0,0,$sm, $sd, $sy); $today_utc=mktime(0,0,0,date("m"), date("d"), date("Y")); if($date_utc>$today_utc){ $future_date=1; $temp=$date_utc; $date_utc=$today_utc; $today_utc=$temp; } $utc_difference=$today_utc-$date_utc; $weeks_count=($utc_difference)/604800; if($weeks_count<10) $weeks_count=substr($weeks_count, 0, 1); else if($weeks_count<100) $weeks_count=substr($weeks_count, 0, 2); else if($weeks_count<1000) $weeks_count=substr($weeks_count, 0, 3); $days_rest_count=substr(($utc_difference-$weeks_count*604800)/86400, 0, 1); $was_day_of_week=date("w")-$days_rest_count; if($was_day_of_week < 0){ if($future_date==1) $was_day_of_week=0-$was_day_of_week; else $was_day_of_week+=7; } return $was_day_of_week; } ?>
I’m sure that this user put a lot of work and effort into this function. I’m sure they were excited to share it with the PHP community. I’m sure they thought they had stumbled on a solution to a problem that everyone needed to solve. I’m sure they had no idea that this code is a great example of using PHP precisely the wrong way.
The example wouldn’t be so bad, except for the fact that it’s a user-contributed note. This means that PHP developers from all over the world (at least those that speak English and read the English version of the PHP manual) might see and, God forbid, implement this function.
There are a number of ways to rewrite this function that would make it shorter and more efficient. For example:
Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP
Posted on 11/23/2009 at 1:00 am
Ivo (@Ijansch) wrote at 11/23/2009 2:28 am:
You judge too hastily. The contributor is aware of date(“w”), he’s using it in his code AND he mentioned it in his comment (but you only showed the code). date(“w”) works from 1901 to 2038. The code this contributor wrote supposedly (I haven’t tested it) works for dates before and beyond that.
Andris wrote at 11/23/2009 2:33 am:
Maybe some voting system would be in order? That way the most useful comments (that get many upvotes) would be on top. Or maybe let the comments be handled by a 3d party, something like stackoverflow.com for example.
Maarten wrote at 11/23/2009 2:50 am:
If you’re running a new enough PHP check out http://www.php.net/manual/en/datetime.format.php to implement something similar in less code then the contributors’ note.
I only just discovered that PHP had that functionality (and it hasn’t been there for a very long time afaik) but it’s a lot nicer then having to work around the 1901-2038 problem using external classes/functions.
Florian (@anderiasch) wrote at 11/23/2009 3:59 am:
>In programming, flaws can be dangerous, and so, developers should be wary, but not ignorant, of the user-contributed notes in documentation like the PHP manual.
What about the manual itself? Aren’t we all users as well who contribute there? :)
User notes aren’t just shown like posted, there’s a team that has to review and explicitly approve them, just like people scanning commit notes to docs.
Brandon Savage (@brandonsavage) wrote at 11/23/2009 6:11 am:
I actually DID test it, and here are the results that I got:
$date1 = ‘2009-11-23’;
$date2 = ‘1940-11-23’;
$date3 = ‘2040-11-23’;
$date4 = ‘2009-12-25’;echo $date1 . ‘ Theirs: ‘ . return_day_of_week($date1) . ‘Mine: ‘ . getDayOfWeek($date1) . ”;
echo $date2 . ‘ Theirs: ‘ . return_day_of_week($date2) . ‘Mine: ‘ . getDayOfWeek($date2) . ”;
echo $date3 . ‘ Theirs: ‘ . return_day_of_week($date3) . ‘Mine: ‘ . getDayOfWeek($date3) . ”;
echo $date4 . ‘ Theirs: ‘ . return_day_of_week($date4) . ‘Mine: ‘ . getDayOfWeek($date4) . ”;Results:
2009-11-23
Theirs: 1
Mine: 11940-11-23
Theirs: 1
Mine: 62040-11-23
Theirs: 1
Mine: 52009-12-25
Theirs: 3
Mine: 5I’m not sure why you get a 1 from his function; you shouldn’t. My function, on the other hand, on a 64-bit system, works 100% properly under PHP 5.3.
Peter wrote at 11/23/2009 8:15 am:
I’m not sure why you get a 1 from his function; you shouldn’t. My function, on the other hand, on a 64-bit system, works 100% properly under PHP 5.3.
For dates beyond 1000 weeks ago (beyond 24 Sep 1990 at the time of writing this), all return values will be 1. This is because the $days_rest_count calculation results in 0 for those dates. Perhaps if the note author gave a reasoning for choosing this over any other method of generating the week day, their particularly convoluted approach might make sense. Or perhaps not.
Ray Paseur (@Ray_Paseur) wrote at 11/23/2009 8:27 am:
I think there are some Julian Date functions that span long periods of time with fairly consistent date results. But a problem that lurks in any of these date questions is the foundation calendar. Over human history it has changed a few times, and that can leave us with odd questions. Was Jesus really crucified on Friday, for example? As a matter of faith the answer is Yes, however as a matter of historical calendar record, the answer is less clear. I completely agree with the comment from Andris – the PHP community can, and should, police its user-contributed notes. Something more like a wiki comes to mind.
Jon wrote at 11/23/2009 9:06 am:
To say that user contributed notes is bad is a bit hypocritical since you fall in that same category (of user contributions). I think it’s good to point out errors, but to tell people to “beware of user contributed notes” in general is an extremely bad philosophy.
Brandon Savage (@brandonsavage) wrote at 11/23/2009 11:42 am:
Peter, the note didn’t explain. Here is the full text of the note:
“Function which simply returns numeric specification what day of week was(or will be) at given date (same schema as date(“w”)). Works both for future and past dates. Counting starts from 0 for Sunday and ends at 7 for Saturday. Hope it will help anybody. ;)
Here’s the function: ”I removed the function as it’s in the post above.
Tommy Smith (@tommysmithbb) wrote at 11/23/2009 11:49 am:
Nice article Brandon. I agree that developers need to be reminded now and then that user contributed code is very much “use at your own risk”. I have seen a ton of code on php.net that is NOT optimal – but poorly written code does a lot to train php newbies and keep non-newbies thinking. When I see verbose code, it serves two purposes. It helps me to remember how a new programmer thinks. And, it takes my mind outside the box. My first thought was the same as yours, just use ‘w’ to get day of week. Then, as I realized the developer was trying to do more – my thoughts expanded into better ways to do write the same code. For those of us that are senior developers – code like this fine tunes our ability to evaluate and criticize code. I say – let the newbees add stuff like this – then, if a senior programmer thinks of a better way – let him/her contribute it too :-)
Marat Denenberg wrote at 11/23/2009 2:14 pm:
A more robust comment system will resolve issues like this. As someone mentioned, voting comments up/down, replies to comments, etc. Then again, I’m grateful that you CAN leave comments. Being able to comment on a manual is still pretty damn great and beats a wiki. Sometimes things are useful, but don’t belong in a manual.
fqqdk (@fqqdk) wrote at 12/10/2009 6:54 pm:
I like user contributed snippets, especially those of the “array_*_recursive” kind; almost every single array_* function which doesn’t have a native “recursive” version will have a user-contributed implementation. It just never gets boring.
BTW, can you provide a formatting option to this comment-box so that we can use http://www.glennmcanally.com/sarcastic/ ? :)
« Why You Should Replace ENUM With Something Else | Designing Databases: Picking The Right Data Types » |