TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack (3) Thread Tools Search this Thread Display Modes
Old 11-11-2007, 04:18 PM   3 links from elsewhere to this Post. Click to view. #1 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Red face Timezone Class: Dealing with Timezones the Proper Way

I must admit that I was going to write you a simple timezone script and then tell you how easy it was. However, I came across some handy timezone_* functions and things got a little more difficult but a lot more practical. This script will allow you to display the time in any timezone you wish, without any ifs, buts or maybes along the way.

This is the code I was going to use:

php Code:
define('TIMEZONE_LONDON', 0);
define('TIMEZONE_AMSTERDAM', +1);
define('TIMEZONE_BRISBANE', +10);
define('TIMEZONE_ARIZONA', -7);

function get_timezone_time($szTimeFormat = 'H:i:s', $szTimezone)
{
    return date($szTimeFormat, strtotime($szTimezone . ' hours'));
}

You can quite clearly see for yourself that it's a small function, however there are a couple of glaring problems with it. I realised the problems as I was coding the revised version and, although it would not be too difficult to fix, if you can do it a better way, then why not! I think it takes a brave coder to analyse and shred their own code into millions of parts, but here goes. I have spotted two immediate problems with the above:
  1. If the locale time is not GMT 0 then other timezones would not be reporting the time accurately. To correct this you would need a little mathematical tweaking in that you would calculate how far the locale is from GMT, and then calculate the target timezone based on that value.
  2. You need to list all the timezones manually and, although there aren't that many, it is rather time consuming listing them all.

With that script safely cast aside, allow us to move onto the new all singing, all dancing, script that will revolutionise the way you deal with timezones. Really!

We're going to begin the script with our obligatory defines. Although these are not required in the least, they help us to visualise the system in an article, and that's the only real reason I use them. We will start off by supporting 3 timezones. These are as follows:

php Code:
define('TIMEZONE_EST', 'EST');
define('TIMEZONE_CST', 'CST');
define('TIMEZONE_GMT', 'GMT');

Once we have our defines in place we can begin our function. We're going to give our function two arguments: a string which accepts the format to return the time and date in, as well as the target timezone to convert to. Without further ado, let us slowly lower our function declaration into its rightful place:

php Code:
function get_timezone_time($szTimeFormat, $szTimezone)
{

}

Now it is time to begin filling in our function with lots of juicy bits of code. I'm assuming here that most people will want to feed in the timezone abbreviation, as that's what most people are familiar with. For example, if I lived in the UK, which luckily for this example I do, then I live in two different timezones at two different times in the year, in summer I live in BST and in winter I live in GMT. Whereas if I was presented with a list of timezones in the format: location/city, then I'd be frantically there looking for Nottingham. However, as there is no Nottingham, but rather a London, then it'd take me a little longer to realise that, and so listing it as GMT and BST, would be much easier, and also make the list a lot smaller because many cities share the same timezones. Using a function called timezone_name_from_abbr will obtain the timezone name from the abbreviation. So:
Quote:
GMT = Europe/London
CST = America/Chicago
Let's drop that into our script now:

php Code:
$szTargetTimezone = timezone_name_from_abbr($szTimezone);

Once we have the correct timezone name we can now call the DateTimeZone class, and subsequently the DateTime class, to get the timezone and the time as a DateTime object:

php Code:
$pLocalTimezone = new DateTimeZone(date_default_timezone_get());
$pLocalDate = new DateTime('now', $pLocalTimezone);

The date_default_timezone_get function as seen here uses a series of faive guesses to determine the default timezone. All that we are doing here is getting the timezone that the server we're using is currently in, and then calculating the date.

Next we are going to use a try...catch statement to see if you have supplied the function with a valid timezone. The DateTimeZone construct is already configured to throw an exception if the timezone is invalid, and so what we will be doing is catching it and returning false:

php Code:
try
{
    $pTargetTimezone = new DateTimeZone($szTargetTimezone);
}
catch(Exception $pEx)
{
    return false;
}

Naturally, if we wanted to, we could have it echo out a message by adding the following code before return false:

php Code:
echo $pEx->getMessage();

This would provide us with the following message if we handed the function an invalid timezone:

Quote:
DateTimeZone::__construct() [function.DateTimeZone---construct]: Unknown or bad timezone ()
All that's left to do now is to perform the calculations on our target timezone by obtaining the offset from our locale timezone and finally change the time and date accordingly. So, to compute the offset:

php Code:
$iOffset = $pTargetTimezone->getOffset($pLocalDate);

We are calling the getOffset function on our $pTargetTimezone object which has the $pLocalDate as its argument. This will allow the function to crack open the $pLocalDate object and compare it with the date in $pTargetTimezone. Seem confusing? It isn't really. As the DateTimeZone class goes about things the proper way, in pure OOP, it returns objects which are then fed into the functions.

The offset in the above line is returned as an amount in seconds. Let's write the following pseudo code to help you understand:
  1. Locale time is 14:30
  2. Target time is 15:30
  3. Offset is 3600 (1 hour)

You see how simple that is? That it is all our function does. All that's left to do now is to use that offset to modify the time and return it to the front-end. We will be using the strtotime function for this to save on over-complex functions that may end up confusing you further:

php Code:
return date($szTimeFormat, strtotime($iOffset . ' seconds'));

This takes the time and date format you passed into the function from the function call, and then calculates the unix timestamp from the amount of offset seconds. It is then returned.

As we have used the try and catch statement in our code, we will want to check if the function has returned false, and if so, inform the user that they have supplied an invalid timezone. As I am based in the GMT timezone, I will be converting the time to CST. Our function call looks like this:

php Code:
$szDateTime = get_timezone_time('jS M Y, H:i:s', TIMEZONE_CST);
echo $szDateTime ? $szDateTime : 'Invalid timezone';

We are catching the return from the function, whether that be the time and date or false. We then use the ternary operator to echo out either the date or a message depending on the value of $szDateTime. If $szDateTime contains a time and date then echo out the time and date, otherwise inform the end-user that they have supplied an invalid timezone.

The time in the CST timezone, according to our script, is now:

Quote:
8th Nov 2007, 08:29:52
Early! But that's really all there is to converting the time and date to another timezone! From our first example which was full up to the top with flaws and bugs, we created a timezone function that goes about things the proper way. This function doesn't require you to specify each and every offset, but instead it knows exactly the offsets of various timezones and calculates it based on our locale timezone.

Incidentally, I have attached the script so you can have a good and proper look at how it's done in all its glory!
Attached Files
File Type: php TimezoneConverter-TalkPHP.php (1.0 KB, 1184 views)
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
Old 11-11-2007, 08:20 PM   #2 (permalink)
The Acquainted
Upcoming Programmer 
 
CMellor's Avatar
 
Join Date: Sep 2007
Location: Leeds, UK
Posts: 141
Thanks: 6
CMellor is on a distinguished road
Default

Do not that some functions used in Wildhoney's script will only work with PHP 5 >= 5.1.0.
__________________
Not quite a n00b...
CMellor is offline  
Reply With Quote
Old 01-10-2011, 11:01 PM   #3 (permalink)
The Visitor
 
hitchy's Avatar
 
Join Date: Jan 2011
Location: New Zealand
Posts: 3
Thanks: 0
hitchy is on a distinguished road
Default

hello

im a relitive noob when it comes to php but im learning.
i love this script ive been looking HARD for something like this for a long time.

i changed the above script to pull the "TIMEZONE" out of my database and that works fine. the problem i have is that if i use this script to enter the date of say a comment being posted by someone in GMT at 22:52 on the 10th, if its viewed right away by someone in NZDT (GMT +12) it displays the time of 22:52 on the 10th. where as i think it should be 10:52 on the 11th (NZDT) as those dates/times are the same time relitively speaking.

i believe i need to store the date/time in the database in a set standard say UTC? so that when i run this script it pulls a standard date/time that it can change it as needed for the timezones.

what code would i need to change to make it read a date/time field in the database and then perform the needed changes?

i hope i explained everything properly.
thanks for any help
hitchy is offline  
Reply With Quote
Reply


LinkBacks (?)
LinkBack to this Thread: http://www.talkphp.com/general/1429-timezone-class-dealing-timezones-proper-way.html
Posted By For Type Date
[PHP] Timezone Conversions - ClanTemplates - Powered by vBulletin This thread Refback 01-06-2008 09:12 PM
[PHP] Timezone Conversions - ClanTemplates - Powered by vBulletin This thread Refback 01-06-2008 04:33 PM
[PHP] Timezone Conversions - ClanTemplates - Powered by vBulletin This thread Refback 01-06-2008 02:43 PM

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 10:37 PM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design