The DateTime class provides all the date and time handling functionality, while the DateTimeZone provides DateTime objects with all the time zone information. We just need to provide DateTimeZone with the time zone in the Area/Location format (for example, the time zone in which this server is located is America/Los_Angeles), and it will return an object representing that time zone. We can pass this to a DateTime object to convert any time into this time zone.
Here is an overview of the steps required to accomplish this:
- Collect the time zone from the user and store in Area/Location format
- Create a DateTimeZone object using the provided time zone
- Create a DateTime object, providing it the time in the local time zone
- Convert the DateTime object to the time zone created in step 1
- Output the time from the DateTime object
The first step is important, because we need to know the time zone of the user before we can think about converting times to their time zone. There are some methods to automatically predict this, but they tend to be unreliable and/or expensive (such as commercial GeoIP databases). So the best method is to simply ask the user where they are. (You can combine these methods by defaulting to the most likely setting when asking, but I won't go into that now).
Here is the code to create a select list of time zones and showing the user a more friendly name representing each zone:
Code: Select all
<?php
if(isset($_POST['tz'])) {
// store the selected value for future use in DateTimeZone
$_SESSION['tz'] = $_POST['tz'];
}
// create an array listing the time zones
$zonelist = array('Kwajalein' => '(GMT-12:00) International Date Line West',
'Pacific/Midway' => '(GMT-11:00) Midway Island',
'Pacific/Samoa' => '(GMT-11:00) Samoa',
'Pacific/Honolulu' => '(GMT-10:00) Hawaii',
'America/Anchorage' => '(GMT-09:00) Alaska',
'America/Los_Angeles' => '(GMT-08:00) Pacific Time (US & Canada)',
'America/Tijuana' => '(GMT-08:00) Tijuana, Baja California',
'America/Denver' => '(GMT-07:00) Mountain Time (US & Canada)',
'America/Chihuahua' => '(GMT-07:00) Chihuahua',
'America/Mazatlan' => '(GMT-07:00) Mazatlan',
'America/Phoenix' => '(GMT-07:00) Arizona',
'America/Regina' => '(GMT-06:00) Saskatchewan',
'America/Tegucigalpa' => '(GMT-06:00) Central America',
'America/Chicago' => '(GMT-06:00) Central Time (US & Canada)',
'America/Mexico_City' => '(GMT-06:00) Mexico City',
'America/Monterrey' => '(GMT-06:00) Monterrey',
'America/New_York' => '(GMT-05:00) Eastern Time (US & Canada)',
'America/Bogota' => '(GMT-05:00) Bogota',
'America/Lima' => '(GMT-05:00) Lima',
'America/Rio_Branco' => '(GMT-05:00) Rio Branco',
'America/Indiana/Indianapolis' => '(GMT-05:00) Indiana (East)',
'America/Caracas' => '(GMT-04:30) Caracas',
'America/Halifax' => '(GMT-04:00) Atlantic Time (Canada)',
'America/Manaus' => '(GMT-04:00) Manaus',
'America/Santiago' => '(GMT-04:00) Santiago',
'America/La_Paz' => '(GMT-04:00) La Paz',
'America/St_Johns' => '(GMT-03:30) Newfoundland',
'America/Argentina/Buenos_Aires' => '(GMT-03:00) Georgetown',
'America/Sao_Paulo' => '(GMT-03:00) Brasilia',
'America/Godthab' => '(GMT-03:00) Greenland',
'America/Montevideo' => '(GMT-03:00) Montevideo',
'Atlantic/South_Georgia' => '(GMT-02:00) Mid-Atlantic',
'Atlantic/Azores' => '(GMT-01:00) Azores',
'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.',
'Europe/Dublin' => '(GMT) Dublin',
'Europe/Lisbon' => '(GMT) Lisbon',
'Europe/London' => '(GMT) London',
'Africa/Monrovia' => '(GMT) Monrovia',
'Atlantic/Reykjavik' => '(GMT) Reykjavik',
'Africa/Casablanca' => '(GMT) Casablanca',
'Europe/Belgrade' => '(GMT+01:00) Belgrade',
'Europe/Bratislava' => '(GMT+01:00) Bratislava',
'Europe/Budapest' => '(GMT+01:00) Budapest',
'Europe/Ljubljana' => '(GMT+01:00) Ljubljana',
'Europe/Prague' => '(GMT+01:00) Prague',
'Europe/Sarajevo' => '(GMT+01:00) Sarajevo',
'Europe/Skopje' => '(GMT+01:00) Skopje',
'Europe/Warsaw' => '(GMT+01:00) Warsaw',
'Europe/Zagreb' => '(GMT+01:00) Zagreb',
'Europe/Brussels' => '(GMT+01:00) Brussels',
'Europe/Copenhagen' => '(GMT+01:00) Copenhagen',
'Europe/Madrid' => '(GMT+01:00) Madrid',
'Europe/Paris' => '(GMT+01:00) Paris',
'Africa/Algiers' => '(GMT+01:00) West Central Africa',
'Europe/Amsterdam' => '(GMT+01:00) Amsterdam',
'Europe/Berlin' => '(GMT+01:00) Berlin',
'Europe/Rome' => '(GMT+01:00) Rome',
'Europe/Stockholm' => '(GMT+01:00) Stockholm',
'Europe/Vienna' => '(GMT+01:00) Vienna',
'Europe/Minsk' => '(GMT+02:00) Minsk',
'Africa/Cairo' => '(GMT+02:00) Cairo',
'Europe/Helsinki' => '(GMT+02:00) Helsinki',
'Europe/Riga' => '(GMT+02:00) Riga',
'Europe/Sofia' => '(GMT+02:00) Sofia',
'Europe/Tallinn' => '(GMT+02:00) Tallinn',
'Europe/Vilnius' => '(GMT+02:00) Vilnius',
'Europe/Athens' => '(GMT+02:00) Athens',
'Europe/Bucharest' => '(GMT+02:00) Bucharest',
'Europe/Istanbul' => '(GMT+02:00) Istanbul',
'Asia/Jerusalem' => '(GMT+02:00) Jerusalem',
'Asia/Amman' => '(GMT+02:00) Amman',
'Asia/Beirut' => '(GMT+02:00) Beirut',
'Africa/Windhoek' => '(GMT+02:00) Windhoek',
'Africa/Harare' => '(GMT+02:00) Harare',
'Asia/Kuwait' => '(GMT+03:00) Kuwait',
'Asia/Riyadh' => '(GMT+03:00) Riyadh',
'Asia/Baghdad' => '(GMT+03:00) Baghdad',
'Africa/Nairobi' => '(GMT+03:00) Nairobi',
'Asia/Tbilisi' => '(GMT+03:00) Tbilisi',
'Europe/Moscow' => '(GMT+03:00) Moscow',
'Europe/Volgograd' => '(GMT+03:00) Volgograd',
'Asia/Tehran' => '(GMT+03:30) Tehran',
'Asia/Muscat' => '(GMT+04:00) Muscat',
'Asia/Baku' => '(GMT+04:00) Baku',
'Asia/Yerevan' => '(GMT+04:00) Yerevan',
'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg',
'Asia/Karachi' => '(GMT+05:00) Karachi',
'Asia/Tashkent' => '(GMT+05:00) Tashkent',
'Asia/Kolkata' => '(GMT+05:30) Calcutta',
'Asia/Colombo' => '(GMT+05:30) Sri Jayawardenepura',
'Asia/Katmandu' => '(GMT+05:45) Kathmandu',
'Asia/Dhaka' => '(GMT+06:00) Dhaka',
'Asia/Almaty' => '(GMT+06:00) Almaty',
'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk',
'Asia/Rangoon' => '(GMT+06:30) Yangon (Rangoon)',
'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk',
'Asia/Bangkok' => '(GMT+07:00) Bangkok',
'Asia/Jakarta' => '(GMT+07:00) Jakarta',
'Asia/Brunei' => '(GMT+08:00) Beijing',
'Asia/Chongqing' => '(GMT+08:00) Chongqing',
'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong',
'Asia/Urumqi' => '(GMT+08:00) Urumqi',
'Asia/Irkutsk' => '(GMT+08:00) Irkutsk',
'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar',
'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur',
'Asia/Singapore' => '(GMT+08:00) Singapore',
'Asia/Taipei' => '(GMT+08:00) Taipei',
'Australia/Perth' => '(GMT+08:00) Perth',
'Asia/Seoul' => '(GMT+09:00) Seoul',
'Asia/Tokyo' => '(GMT+09:00) Tokyo',
'Asia/Yakutsk' => '(GMT+09:00) Yakutsk',
'Australia/Darwin' => '(GMT+09:30) Darwin',
'Australia/Adelaide' => '(GMT+09:30) Adelaide',
'Australia/Canberra' => '(GMT+10:00) Canberra',
'Australia/Melbourne' => '(GMT+10:00) Melbourne',
'Australia/Sydney' => '(GMT+10:00) Sydney',
'Australia/Brisbane' => '(GMT+10:00) Brisbane',
'Australia/Hobart' => '(GMT+10:00) Hobart',
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok',
'Pacific/Guam' => '(GMT+10:00) Guam',
'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby',
'Asia/Magadan' => '(GMT+11:00) Magadan',
'Pacific/Fiji' => '(GMT+12:00) Fiji',
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka',
'Pacific/Auckland' => '(GMT+12:00) Auckland',
'Pacific/Tongatapu' => '(GMT+13:00) Nukualofa');
?>
<form method="post">
<select name="tz">
<option value="Pacific/Honolulu">(GMT-10:00) Hawaii</option>
<option value="America/Anchorage">(GMT-09:00) Alaska</option>
<option value="America/Los_Angeles">(GMT-08:00) Pacific Time (US & Canada)</option>
<option value="America/Phoenix">(GMT-07:00) Arizona</option>
<option value="America/Denver">(GMT-07:00) Mountain Time (US & Canada)</option>
<option value="America/Chicago">(GMT-06:00) Central Time (US & Canada)</option>
<option value="America/New_York">(GMT-05:00) Eastern Time (US & Canada)</option>
<option value="America/Indiana/Indianapolis">(GMT-05:00) Indiana (East)</option>
<option disabled="disabled">——————–</option>
<?php
foreach($zonelist as $key => $value) {
echo ' <option value="' . $key . '">' . $value . '</option>' . "\n";
}
?>
</select>
<input type="submit" name="submit" value="Set" />
</form>
So now that we have the needed information from the user, we can start with the conversion code. There are two different conversions we might need to do: Timestamp -> User's Time and User's Time -> Timestamp. This is for displaying time to the user and collecting time from the user, respectively.
Converting a timestamp to the user's time:
PHP 5.2:
Code: Select all
// timestamp to convert (just an example)
$timestamp = 1240349566;
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// first convert the timestamp into a string representing the local time
$time = date('r', $timestamp);
// now create the DateTime object for this time
$dtime = new DateTime($time);
// convert this to the user's timezone using the DateTimeZone object
$dtime->setTimeZone($dtzone);
// print the time using your preferred format
$time = $dtime->format('g:i A m/d/y');
PHP 5.3:
Code: Select all
// timestamp to convert (just an example)
$timestamp = 1240349566;
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// create a DateTime object
$dtime = new DateTime();
// set it to the timestamp (PHP >= 5.3.0)
$dtime->setTimestamp($timestamp);
// convert this to the user's timezone using the DateTimeZone object
$dtime->setTimeZone($dtzone);
// print the time using your preferred format
$time = $dtime->format('g:i A m/d/y');
Converting user's time to a timestamp:
Code: Select all
// time to convert (just an example)
$time = 'Tuesday, April 21, 2009 2:32:46 PM';
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// now create the DateTime object for this time and user time zone
$dtime = new DateTime($time, $dtzone);
// print the timestamp
$timestamp = $dtime->format('U');