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 Timeand 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:
- at 150° W longitude, the time should be 150/15= 10 hours behind GMT
- at 75° E longitude, the time would be 75/15= 5 hours ahead of GMT
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.

