Detecting the system timezone from PHP

PHP Warning: date(): It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone ‘UTC’ for now, but please set date.timezone to select your timezone.

We’ve all seen this at least once.
PHP5 requires you to have a timezone specified in your php.ini.
If you don’t, it will issue the warning and versions <5.4 will try to autodetect the system timezone.
This didn't always work, so PHP 5.4 dropped the autodetection code completely and left us on our own. Wonderful.

Normally, this isn’t such a big deal, a script can always run
date_default_timezone_set() to set a new default.
However, I’m currently writing a CLI tool (using Symfony Console) and prompting the user to specify a timezone is much more annoying in this context.
So I wrote some code that tries to autodetect the system timezone, with a UTC fallback:

$timezone = 'UTC';
if (is_link('/etc/localtime')) {
    // Mac OS X (and older Linuxes)    
    // /etc/localtime is a symlink to the 
    // timezone in /usr/share/zoneinfo.
    $filename = readlink('/etc/localtime');
    if (strpos($filename, '/usr/share/zoneinfo/') === 0) {
        $timezone = substr($filename, 20);
} elseif (file_exists('/etc/timezone')) {
    // Ubuntu / Debian.
    $data = file_get_contents('/etc/timezone');
    if ($data) {
        $timezone = $data;
} elseif (file_exists('/etc/sysconfig/clock')) {
    // RHEL / CentOS
    $data = parse_ini_file('/etc/sysconfig/clock');
    if (!empty($data['ZONE'])) {
        $timezone = $data['ZONE'];


A further improvement would be to try and make autodetection work on Windows as well.


It’s been two and a half years since I last blogged.

Back then, I used an alpha version of D7 that didn’t even have imagefield working properly. In time, the installation became too annoying to remigrate (there was no upgrade path for pre-releases), and I decided that Twitter was a better medium for what I wanted to say, so I closed the blog.

Fast forward to May 2013, I’ve slowly filled up a queue of technical topics I want to discuss, so I’ve decided to reopen a blog. Also decided I want a hosted solution, but not Drupal Gardens, since I’m already very familiar with Drupal 7. Instead, I am giving WordPress a shot for the first time. It fits nicely with my efforts to get off the island this year, branch into other projects and work on new things. So far I’ve had a lot of fun playing and developing with Silex and AngularJS, as well as contributing to an oauth2 server library. The pull of Python is always strong, too. Fun times ahead, especially considering the approaching Drupal 8 and the many advances it brings.

So, here we go…