DateTimeZone and DST in PHP

2017-12-03

I ran into something a little unexpected a few days ago at work and I thought I'd share (possibly in case I end up Googling this again myself later). I have a function like this:

function isDaylightSavingDifferent(DateTimeInterface $dt1, DateTimeInterface $dt2): bool
{
    return $dt1->format('I') !== $dt2->format('I');
}

It mostly does its job just fine, but I ran into some puzzling behavior when attempting to feed some data into it. The dates were in Atom (i.e. PHP's broken ISO-8601) format, ex. 2017-11-01T15:00:00-0500.

class DateTime#4319 (3) {
  public $date =>
  string(26) "2017-11-01 15:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-05:00"
}

However, if I sent in another date after the DST switch (11-05 this year), the code dependent on that above function didn't fire. Why not?

class DateTime#4319 (3) {
  public $date =>
  string(26) "2017-11-06 15:00:00.000000"
  public $timezone_type =>
  int(1)
  public $timezone =>
  string(6) "-06:00"
}

The first one returns "0" for the "is DST" check, and the second returns... "0"??

wat

It turns out, PHP has 3 different ways to represent a DateTimeZone object, represented by $timezone_type in the var dump above. You can create one with a UTC offset (type 1, ex. -0500), a timezone abbreviation (type 2, ex. CDT), or a timezone name (type 3, ex. America/Chicago). All 3 are valid, and all represent the same moment in time, but only one of them contains enough context for PHP to understand DST. So while I knew it was CDT when I created the time string, when the code under test received it, it was formatted with a UTC offset, so the consuming code couldn't tell if DST had changed or not.

I ended up filling in the gaps using the context of the user, but when I initially tested it at the unit level, that wasn't there. Hence, the problem.

Checking In

2016-04-14

So far the Twitter hiatus is going surprisingly well. I've read two books and am starting on a different one that was recommended to me before finishing out the trilogy (The Black Magician, for those curious). I've made multiple contributions to open source, completed a few arduous and nagging pieces of adulting, did some devops-ish things to some side projects (HSTS and LetsEncrypt for everything!) and I've even had to start sending browser tabs from my desktop my phone (thanks Pushbullet!). Surprisingly, I'm also less angry. That takes a bit of unpacking though. I do subscribe to the "if you're not angry, you're not paying attention" idea, but honestly, rage is not a clean-burning fuel source. There will always be things wrong with the world, but that doesn't obligate me to steep myself in them. In several ways I feel like this is a more healthy choice. I do still read what comes through my RSS feeds, so I'm not completely out of touch, but there's definitely nothing from mainstream news organizations there.

I miss being able to share random thoughts, wry observations, and stories about my son, but I like the way this experiment is going. I still intend to come back to Twitter in two more weeks, but hopefully as a more deliberate consumer instead of just pointing the firehose at my brain.

Twitter Break

2016-04-02

I think this has been awhile coming, but I've decided to take a break from Twitter. I'm going to give it a month and see how it goes. I've been spending a lot of time consuming things but not nearly as much creating, and I think this will help bring that back into balance. Also, a sizable amount of what I've been seeing lately has been pretty depressing. I don't know if it's world events, politics, racism, or what, but the jokes, cute animal pictures, tech content, and other stuff just doesn't seem to be balancing it out lately.

Hopefully this will lead to more writing here, reading the 200 or so open tabs I've racked up, some side coding, reading more books, maybe even starting an exercise plan. Or it could be an abject failure and I'll be back in 3 days, we'll see. I'll still likely respond to mentions and DMs if you need to reach me. See you in May!