8

I cant understand this - why does the following occur?

echo date("d-m-Y", strtotime($str));

$str = '214454';  // Produces todays date
$str = '333333';  // Produces 1-1-1970
$str = 'a' (or ANY single char)  // Produces tomorrows date
$str = 'aa' (or ANY double char)  // Produces 1-1-1970

OR just returning the strtotime function

echo strtotime($str);

$str = '214454';  // Produces todays date
$str = '333333';  // returns false
$str = 'a' (or ANY single char)  // Produces tomorrows date
$str = 'aa' (or ANY double char)  // returns false

These values came from some testing I was doing, to try and work out how/why certain values were being returned from a specific function.

Its causing my function to fail - because you would assume "a" (or any single char) to be returned as a false incorrect date.

Laurence
  • 58,936
  • 21
  • 171
  • 212
  • Because single characters are treated as time zones. http://www.timeanddate.com/library/abbreviations/timezones/military/ This had to be a comment. – Leri Sep 03 '12 at 13:08
  • @PLB - thanks - but I cant find that in the strtotime() documentation anywhere? – Laurence Sep 03 '12 at 13:10
  • @TheShiftExchange Jon, has already answered to this question much better than I could. I had the same problem few months ago and solved it by checking before calling `strtotime`. – Leri Sep 03 '12 at 13:20
  • @PLB actually your table works ;) I would keep it as an answer – meze Sep 03 '12 at 13:25
  • 1
    @PLB: Your answer though is factually correct and was first. If you had expanded a little instead of deleting it I 'd definitely have upvoted. – Jon Sep 03 '12 at 13:37
  • @Jon I knew that because had the same problem but I am at work so I don't have enough time to look up for materials. By the way, thanks for nice formatted answer. – Leri Sep 03 '12 at 13:43

2 Answers2

8

Both single and double characters are interpreted as timezones (table "used symbols", row "tz"); six digits are interpreted as HHMMII (table "24 Hour Notation", row "Hour, minutes and seconds, no colon").

Valid formats

In the 1st and 3rd cases parsing succeeds, strtotime returns a timestamp and date prints whatever date it corresponds to. It's obvious why the 1st case succeeds; for the 3rd case, remember that military time zones can be referred to with a single letter, and then the results make sense. Let's follow this code:

$zones = range('a', 'z');
$last = null;

foreach($zones as $tz) {
    $ts = strtotime($tz);
    if ($last !== null) {
        echo "TZ $last[0] => TZ $tz: change = ".($ts - $last[1])."\n";
    }
    $last = array($tz, $ts);
}

This prints

TZ a => TZ b: change = -3600
TZ b => TZ c: change = -3600
TZ c => TZ d: change = -3600
TZ d => TZ e: change = -3600
TZ e => TZ f: change = -3600
TZ f => TZ g: change = -3600
TZ g => TZ h: change = -3600
TZ h => TZ i: change = -3600
TZ i => TZ j: change = -1346649725
TZ j => TZ k: change = 1346646125
TZ k => TZ l: change = -3600
TZ l => TZ m: change = -3600
TZ m => TZ n: change = 46800
TZ n => TZ o: change = 3600
TZ o => TZ p: change = 3600
TZ p => TZ q: change = 3600
TZ q => TZ r: change = 3600
TZ r => TZ s: change = 3600
TZ s => TZ t: change = 3600
TZ t => TZ u: change = 3600
TZ u => TZ v: change = 3600
TZ v => TZ w: change = 3600
TZ w => TZ x: change = 3600
TZ x => TZ y: change = 3600
TZ y => TZ z: change = -43200

You can see the continuity as we go from one time zone to the next; the discontinuity for timezone 'j' which does not exist (here parsing fails with the same results explained below); the discontinuity at timezone 'n' where we move from UTC+12 to UTC-1, etc.

Invalid formats

In the 2nd and 4th cases parsing fails, strtotime returns false and this has the same effect as if you had called date("d-m-Y", 0) -- it formats the start of the epoch (January 1st 1970, 00:00:00). This happens because false is converted to the integer 0 as per normal type juggling rules.

What does strtotime('x') really return?

It returns the current time at the timezone UTC-11 (this is the "x-ray" military time zone). Depending on your local time and timezone, this is usually either "today" or "tomorrow" from your point of view. If you happen to be at less than UTC-11 then it could even be "yesterday" (although that's not quite likely).

Jon
  • 428,835
  • 81
  • 738
  • 806
3
  • 214454 is treated as hour:minute:second
  • 333333 it's because there is no 33 hour
Peter
  • 16,453
  • 8
  • 51
  • 77
  • Where does it say "any single char is treated as tomorrow"? Because the first thing I did was check http://php.net/manual/en/function.strtotime.php - and it makes no mention of that? – Laurence Sep 03 '12 at 13:06
  • You can confirm meze's assertion by seeing that `a` and `x` produce different dates. – Jon Sep 03 '12 at 13:06