strtotime() considered harmful?
strtotime()
is suggested because it's been in PHP since the v4.x days, so is basically guaranteed to be available. Availability trumps the odd time (no pun intended) that it'll turn around and bite you in the butt with a mis-parsed date.
The current "proper" way to do date math would be using the DateTime/DateInterval objects, but those are more recent additions to PHP (5.2/5.3, I think) and therefore not always available - there's plenty of hosts out there still on 4.x.
I'll start off by saying that I am a big advocate for using the DateTime object, which allows you to use the DateTime::createFromFormat()
function. The DateTime object makes the code much more readable and avoids the need to do the whole Unix timestamp modification using 60 * 60 * 24 to advance the date days.
That being said, the arbitrary string that strtotime() takes is not very hard to predict. Supported Date and Time Formats lists the formats that are supported.
As per your example of not being able to differentiate between MM/DD/YYYY and DD/MM/YYYY it does differentiate based on the Date Formats. Dates that use slashes are always read as American format. So a date in the format 00/00/0000 will always be read as MM/DD/YYYY. Alternatively using dashes or periods will be DMY. e.g. 00-00-0000 will always be read as DD-MM-YYYY.
Here are some examples:
<?php
$dates = array(
// MM DD YYYY
'11/12/2013' => strtotime('2013-11-12'),
// Using 0 goes to the previous month
'0/12/2013' => strtotime('2012-12-12'),
// 31st of November (30 days) goes to 1st December
'11/31/2013' => strtotime('2013-12-01'),
// There isn't a 25th month... expect false
'25/12/2013' => false,
// DD MM YYYY
'11-12-2013' => strtotime('2013-12-11'),
'11.12.2013' => strtotime('2013-12-11'),
'31.12.2013' => strtotime('2013-12-31'),
// There isn't a 25th month expect false
'12.25.2013' => false,
);
foreach($dates as $date => $expected) {
assert(strtotime($date) == $expected);
}
As you can see a couple of key examples are 25/12/2013
and 12.25.2013
which would both be valid if read the with the opposite format, however they return false
as they are invalid according the the Suported Date and Time Formats...
So as you can see the behaviour is quite predictable. As always if you are receiving a date from use input you should be validating that input first. No method will work if you are not validating the input first.
If you want to be very specific about the date being read, or the format you are being given isn't a supported format, then I recommend using DateTime::createFromFormat()
.
I use strtotime()
frequently. Thing is, you shouldn't use it as a crutch, but you should be aware of its limitations.
If you wanted to enforce a standard, then I suppose you should go with the c-based mktime()
. For instance, to get 1 week later:
date('Y-m-d', mktime(0, 0, 0, date('n'), date('j') + 7);