What exactly is causing this time calculation error for one hour every six months?

Viewed 77

I have this code:

var_dump(strtotime('2020-10-25 02:05') > strtotime('-5 minutes'));

It was executed when my system clock was 2020-10-25 02:04. It answered false, even though that timestamp obviously was "greater than" ("younger") than "the current time minus 5 minutes" at the time it was executed. (It was only 1 minute ago.)

However, with zero code changes, it has answered true for that kind of query until a specific hour, which happens with six months apart.

You see, it's switched over to "winter time" where I live now. This means that at some point, I assume midnight UTC, time either goes back or forward one hour.

Since my timezone is two hours after the UTC, that "magic hour" is 01:00-02:00, or 02:00-03:00. Those details aren't the important part.

Just to make it clear: the same exact code stopped answering false, instead answering true, once it had "switched over" to winter time. It was returning the wrong answer for an entire hour.

I have one hour every six months to try to debug this, because there is no sane way (that I know of) to change the perceived system time to PHP, for an individual script, without changing the entire computer's time, which would mess all kinds of things up if I did that.

What exactly am I missing? It's obvious that it has to do with the winter/summer time nonsense, but why? Yes, strtotime converts a time to a Unix epoch, which has no concept of timezones, but it does count a fixed number of seconds since a specific historic moment, so why does it matter? My timestamps come from the same machine, the same PHP script, and it doesn't just happen briefly when it just switches over, but for (at least) an entire hour!

You have no idea how much hair I've been pulling away from my hair for years until I just now, before asking this, realized what causes this to happen. I thought I had gone insane when no changes in my code caused different answers from PHP. But I still don't understand why.

Can you explain why it would be so confused when both timestamps compared use the same timezone anyway?

1 Answers

The time 02:05 is available twice for the night of the changeover from summer to winter time. let's consider the timestamps and times:

for($ts = 1603580700; $ts <= 1603592300; $ts += 1800){
  echo 'ts: '.$ts.' date: '.date('Y-m-d H:i \s:I',$ts).'<br>';
}

/*
ts: 1603580700 date: 2020-10-25 01:05 s:1
ts: 1603582500 date: 2020-10-25 01:35 s:1
ts: 1603584300 date: 2020-10-25 02:05 s:1
ts: 1603586100 date: 2020-10-25 02:35 s:1
ts: 1603587900 date: 2020-10-25 02:05 s:0
ts: 1603589700 date: 2020-10-25 02:35 s:0
ts: 1603591500 date: 2020-10-25 03:05 s:0
*/

With the format I, 1 is output for summer time and 0 for winter time. The printout

echo strtotime ('2020-10-25 02:05'); //1603587900

however, always provides a time stamp for winter time. A relative expression like strtotime ('- 5 minutes') supplies a correct time stamp how the ts in the example.

Your comparison can give different results depending on whether you do your test at the same clock time before or after the time change.

Related