Calculating Daylight Savings Time Boundary In PHP

I had an issue recently where I needed to calculate the Unix timestamp for the daylight savings time boundaries. According to the United States Naval Observatory, daylight savings time begins the Second Sunday of March and ends on the First Sunday of November.

Awkward date calculations if you don’t have the magical strtotime() function in PHP. strtotime() is able to do relativistic time conversions from the common “+1 hours” to the more complex (and more relevant) “Second Sunday March 0″.

Why do we do the ‘March 0′ in the above string to calculate the start boundary? Doing some tests with strtotime() reveals some behavior you should be aware of.

strtotime("March"); doesn’t actually give you the first of March, it gives you the current day in the month specified (date('D, F j, Y, g:i a', strtotime("March")); returns Tue, March 10, 2009, 12:00 am at the time of this post). Doing a similar test but substituting April for March results in the 10th of April (at 12 am).

Now in most cases doing a strtotime("March 1") will suffice (date('D, F j, Y, g:i a', strtotime("March 1")); results in Sun, March 1, 2009, 12:00 am). However, as you can tell, this month is going to be awkward because the first day of the month is a Sunday. strtotime(), when calculating the fuzzy “Second Sunday,” doesn’t include the current day. So calculating date('D, F j, Y, g:i a', strtotime("Second Sunday March 1")); will actually return the 3rd Sunday (Sun, March 15, 2009, 12:00 am).

So our solution is actually to take a step back and return the PREVIOUS day to the first day of March and then calculate the Second Sunday from there (since we know that starting from the next day will account for the first). Normally, dealing with the last day in February is a headache, BUT again thanks to PHP magic we don’t have to figure out if it’s February 28th or 29th, we merely do a “March 0″ which steps us back a month (date('D, F j, Y, g:i a', strtotime("March 0")); returns Sat, February 28, 2009, 12:00 am). From there we can calculate the Second Sunday with ease and eventually determine that the second sunday is March 8th, which is confirmed by the above USNO website.

Applying these lessons to calculating the first Sunday in November we come up with the following snippit:

<?php
$remove_hour = strtotime("Second Sunday March 0");
$add_hour = strtotime("First Sunday November 0");

$time  = time();

if( $time >= $remove_hour && $time < $add_hour )
{
    var_dump("Lost an hour");
}
else
{
    var_dump("Gained an hour");
}

Cheers!

Comments

  1. Well, what is the purpose of having those boundaries as timestamps? If you set the timezone, php date functions will calculate the hour shift accordingly. However,
    date(‘I’, $time)
    will tell you if dst is on at that time.

  2. The system I was working on was importing the timestamps and the DST information wasn’t being applied correctly.

    My solution may be a temporary hack but it was a fun exercise playing with strtotime() and realizing how good I have it with PHP’s date functions.

  3. volomike says:

    Does your code work for non-USA timezones like in the UK?

  4. Jesse says:

    Thanks for this script. The php docs just weren’t clear enough for me, plus Yahoo! hasn’t upgraded to php 5 yet, so this is an awesome hack around.

  5. haris says:

    nice post, it helped me a lot

  6. Matt says:

    @volomike: it depends on the underlying date/time libs that PHP uses. On most Linux distros, they’re using the standard tzdata tables, which have all worldwide time zone and DST rules, and are updated frequently to keep pace with countries changing their DST rules.

  7. Minway Hsu says:

    It’s helpful.Thanks a lot!

  8. David says:

    Bro, many thanks! This was a lifesaver.

  9. Jim Linder says:

    Not sure if it is the best way to do what I need, but I used this to determine how many hours to offset the server time for the apps I am building, so the user sees local time. It worked like a charm, thanks.

  10. Mike Jourard says:

    Thanks for the tip! This is really helpful for one of my programms. I have a newsletter that pulls events for the next four weeks out of a calendar system. The system stores the event timestamps as GMT/UTC, but we are in either EST or EDT. If the current newsletter straddles the time change, the times for events after the time change are shown an hour off! By checking the event date against the time change boundary calculation, I can compensate for the discrepancy.

  1. [...] Cousineau has written up some timely advice in a new post to his blog. It looks at pinpointing the time boundary for Daylight Savings Time in a PHP script [...]

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>