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'];
    }
}

date_default_timezone_set($timezone);

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

Advertisements