PHP and Timezones

Helpful Scripting from NicholasSolutions

A common problem PHP developers run into is working with the current local time in the user's locale rather than that of the server. For example, you may want mktime() to return the timestamp for the user's location. In this tutorial we'll learn a little about how to do this, and explore a method for determining users' timezones from their IP addresses. At the end, you'll hopefully have learned something new about PHP and how to approach problems using it as a tool. I'm assuming your OS is Unix/Linux, and that your webserver Apache, but these instructions may work in other setups as well with slight modifications.

Setting the current time zone

If you know your users will all be from a certain area, you can set the timezone using the PHP putenv() function.

<?php
 putenv('TZ=Continent/Region');
 echo date('M j Y, H:m:s');
?>

To find what values to use for Continent/Region, have a look Here, or you can look in your own zone.tab file, which is located at /usr/share/zoneinfo/zone.tab (at least on Redhat and Debian systems). For example, for New York City, USA, you would look on the chart for the US country code, and then find the line that says:

US     +404251-0740023     America/New_York     Eastern Time

and you would use:

<?php
 putenv('TZ=America/New_York');
 echo date('M j Y, H:m:s');
?>

If you don't see the exact region you are looking for, just use a region that has the same timezone, or look for one that you know is close by.

Dynamically setting the timezone

Maybe you need your script to know the current local time for the user, but you don't know where the user will be from. This Site offers a solution using PHP and Javascript, but I'd like to find a way using PHP alone, and I think this will make a good tutorial to demonstrate the types of things you can do with PHP combined with a little research on Google. Please note that the purpose of this tutorial is meant more as a proof of concept than a ready-to-go solution for an enterprise website: I'll show you how I am approaching this problem, and hopefully you might learn a thing or two on the way and have a little fun. You might also want to use this technique as a method to fall back on if a user doesn't have javascript installed.

To make this work, we need to know the user's location. Then, we need to figure out the timezone given that location. One option is to ask the users their location and or timezone. But that's boring. Instead, let's use IP address geolocation to find out where they are.

There are several services that offer IP geolocation to web developers. Most of the good ones charge a small fee. I'm no expert on this particular set of products, but DNSStuff (one of my favorite sites by the way) uses IP2Location, so I'll recommend that one, I guess. For this tutorial, though, we'll use hostip.info because it's free and it's the type of community-driven software project we like to see. Hopefully sometime soon it will be able to compete with the commercial services.

hostip.info offers a simple GET API for IP geolocation. However, you should read through their API Documentation and use the downloadable feed/database instead if you plan to be doing a lot of lookups (this will save their bandwidth, your bandwidth, their server resources, and your server resources...plus it will make the queries faster). Using the example from their site, entering the URL http://api.hostip.info/get_html.php?ip=12.215.42.19&position=true (i.e. to look up the address 12.215.42.19) yields the following output:


Country: UNITED STATES (US)
City: Sugar Grove, IL
Latitude: 41.7696
Longitude: -88.4588

Timezones are dictated by longitude, so if we're able to get the users' longitudes, we should be able to find their timezones. So, let's start by making a simple script to get a user's longitude. First we need their IP address. The easiest place to get that is from the superglobal $_SERVER array: $_SERVER['REMOTE_ADDR']. This is not 100% reliable (i.e. it can be modified by the user, so it may not be their real IP, or it could be the IP of a proxy server rather than the real user), but it's what we've got, so let's go with it ;-)


<?php
 $record = file('http://api.hostip.info/get_html.php?ip='
               . $_SERVER['REMOTE_ADDR'].'&position=true');

 $longitude = substr($record[3], 11);
?>

Now, a little research turns up how to determine timezone from longitude. Namely (quoting from linked reference):

For every 15° east or west of the Greenwich meridian civil time changes by 1 hour forwards and backwards respectively. To find the appropriate time zone, in hours, divide the longitude, in degrees, by 15. For example:

In our results, negative numbers will correspond to West, and the offset will automatically be negative also, so that part should be easy -- just add the offset we calculate by dividing $longitude by 15. We can use gmmktime() to get current GMT timestamp. So, let's put it all together:


<?php
 $offset = $longitude / 15;
 $true_local_time = gmmktime() + ($offset * 3600);  //there are 3600 seconds in an hour
?>

That's it. Our finished script looks like this:


<?php
 $record = file('http://api.hostip.info/get_html.php?ip='
               . $_SERVER['REMOTE_ADDR'].'&position=true');

 $longitude = substr($record[3], 11);
 $offset = $longitude / 15;
 $true_local_time = gmmktime() + ($offset * 3600); 
 
 echo date('M j Y, H:m:s', $true_local_time);
?>

Some important parting thoughts

Go ahead and try it out, but remember: if you want this to be as reliable as possible, it's probably a good idea to subscribe to one of the paying services mentioned above, at least until the free ones are able to compete. Speaking of which, if the time doesn't come up right for you, you can help out hostip.info by going to their site and making a correction to your IP's city location.

One final thing that may be obvious, but is worth mentioning nevertheless: For this to work, the time needs to be set correctly on your server, including daylight savings. Equally important, and perhaps somewhat less obvious, your server needs to know where it's located; that is, what timezone it is in. Even if you have the time set right, if your server is in Alabama but it thinks it's in Paris, it is going to calculate GMT incorrectly, and that will cause everything else to be incorrect as well.


post to Dzone Digg this! Add to del.icio.us Googleize this Add to reddit Save to myYahoo Add to furl Add to Netvouz! Spurl this! Add to Linkroll! Save to Simpy Give if thumbs up on StumbleUpon Save to Blinklist Add to Tektag Save to Bibsonomy Submit to Tweako
Search ERT on the Tools Page
Did you know? You can discuss this article with the mentor who wrote it and others interested in the topic? You are invited to join the discussion with Go to the forum

Got a technical article or tutorial you want to publish on the Internet? Join Go to the forum in the Round Table Forum and let the Mentors know what you have. If it meets ERT standards, is factual and can help ERT visitors, then ERT Mentors and Editors can help you (without charge) polish your offering so it can be published and promoted by ERT. An article published on ERT may be read by as many as 10,000 visitors a week; promoting you, your site, and your ideas. Please note ERT does not publish re-prints; promotional handouts, or pieces consisting mainly of links. So original technical content only please. If you prefer you can email the Editor