Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Codeigniter, timezone_menu and date_default_timezone_set

I make use of Codeigniters timezone_menu which gives a drop down box of time timezones and I am wondering how are we supposed to make use of these timezones with PHPs date_default_timezone_set?

An example of codeigniters timezone is UP1. However, you can't use that with PHPs date_default_timezone_set as the string it takes in should be something like Europe/Berlin

The question is, is there a way to convert a codeigniter timezone string to a PHP one that can be accepted by the date_default_timezone_set?

like image 763
Abs Avatar asked Mar 06 '11 18:03

Abs


2 Answers

The following works for me:

// Example - timezones is part of the date helper function
// You obviously wouldn't echo it out, you would pass it in to 
// set default timezone function in PHP based on the posted data from 
// the dropdown
echo timezone_by_offset(timezones('UM5')); // ouputs 'America/Porto_Acre' which is (-5)

// And the function
function timezone_by_offset($offset) {
    $offset = ($offset+1) * 60 * 60;
    $abbrarray = timezone_abbreviations_list();

    foreach ($abbrarray as $abbr) {
        foreach ($abbr as $city) {
            if ($city['offset'] == $offset) { 
                echo($city['timezone_id']);
                return true;
            }
        }
    }
    echo "UTC";
    return false;
} 

EDIT The original function didn't exclude DST offsets. timezone_abbreviations_list() lists 2x for a timezone that has DST marked as true, for example Tasmania appears under +11 and +10. So if DST == TRUE, ignore it as part of the return listing.

//-- Function -------------------------------------------------------------------
function timezone_by_offset($offset) {
    $abbrarray = timezone_abbreviations_list();
    $offset = $offset * 60 * 60;

    foreach ($abbrarray as $abbr) {
        foreach ($abbr as $city) {
            if ($city['offset'] == $offset && $city['dst'] == FALSE) { 
                return $city['timezone_id'];                                
            }
        }
    }
    return 'UTC'; // any default value you wish
}

Some examples:

//-- Test Cases -------------------------------------------------------------------
echo timezone_by_offset(-12) . '<br/>';  
echo (date_default_timezone_set(timezone_by_offset(-12)) == TRUE ? 'Valid' : 'Not Valid'). '<br/>'; 
// Etc/GMT+12
// Valid 

echo timezone_by_offset(-10) . '<br/>';  
echo (date_default_timezone_set(timezone_by_offset(-10)) == TRUE ? 'Valid' : 'Not Valid'). '<br/>'; 
// America/Anchorage
// Valid

echo timezone_by_offset(-8) . '<br/>';  
echo (date_default_timezone_set(timezone_by_offset(-8)) == TRUE ? 'Valid' : 'Not Valid'). '<br/>'; 
// Etc/GMT+8
// Valid        

echo timezone_by_offset(6) . '<br/>';  
echo (date_default_timezone_set(timezone_by_offset(6)) == TRUE ? 'Valid' : 'Not Valid'). '<br/>'; 
// Asia/Aqtobe
// Valid        

echo timezone_by_offset(7) . '<br/>';  
echo (date_default_timezone_set(timezone_by_offset(7)) == TRUE ? 'Valid' : 'Not Valid'). '<br/>'; 
// Indian/Christmas
// Valid
like image 81
Chris Avatar answered Nov 04 '22 10:11

Chris


You can get the UTC offset for one of the U(M|P)x-values by using timezones().

$offset = timezones('UP1'); // don't know the exact format returned but should be something like 1 or '+01:00'

From this point on, I think the only way is some sort of custom mapping between the offset and the PHP timezone. You could use Etc/GMT(+|-)x timezones but the problem with those will be that they do not contain any DST-transition information.

The problem in general is, that the UTC-offsets actually map to a lot of different timezones, e.g. UP1 ((UTC + 1:00) Berlin, Brussels, Copenhagen, Madrid, Paris, Rome) maps to Europe/Berlin, Europe/Brussels, Europe/Copenhagen, Europe/Madrid, Europe/Paris, Europe/Rome but also to Africa/Luanda for example. The thing now gets arbitrarily complex due to the DST-transitions that may oder may not occur in some of these timezones.

If you don't need the DST-thing, a mapping between the return value of the timezones() function and the Etc/GMT(+|-)x timezones should be OK, otherwise you cannot use the Codeigniter timezone handling at all because the mapping is not unambiguous.

like image 39
Stefan Gehrig Avatar answered Nov 04 '22 10:11

Stefan Gehrig