Go4Expert

Go4Expert (http://www.go4expert.com/)
-   PHP (http://www.go4expert.com/articles/php-tutorials/)
-   -   Using PEAR Date, converting between time zones in PHP (http://www.go4expert.com/articles/using-pear-date-converting-time-zones-t3494/)

Mary 20Mar2007 18:01

Using PEAR Date, converting between time zones in PHP
 

Introduction



PHP comes with an extensive catalog of date and time functions, all designed to let you easily retrieve temporal information, massage it into a format you require, and either use it in a calculation or display it to the user. However, if you'd like to do something more complicated, things get much, much messed up.

A simple example of this involves displaying the time on a Web page. With PHP, you can easily use the date() function to read the server's clock and display the required information in a specific format. But what if you'd like to display the time in a different location - for example, if your company is located in a different country from your server and you want to see "home" time instead of local time? Well, then you have to figure out the difference between the two places and perform some date arithmetic to adjust for the different time zones. If the time difference is significant, you need to take account of whether the new time is on the day before or after, worry about daylight savings time, and keep track of end-of-the-month and leap year constraints.

As you can imagine, the math to perform such time zone conversions can quickly get very complicated if you do it manually. To be fair, PHP has built-in time zone functions to help with this, but these aren't particularly intuitive and require a fair amount of time to get used to. A quicker alternative is to use the PEAR Date class, which comes with built-in support for time zones and is, by far, the simplest way to perform these conversions.

This article will teach you how to convert temporal values between time zones with the PEAR Date class. It assumes that you have a working Apache and PHP installation and that the PEAR Date class has been correctly installed.

Note: You can install the PEAR Date package directly from the Web, either by downloading it or by using the instructions provided.

Getting started



Let's begin with the basics - initialising and using a Date object. Create a PHP script with the following lines of code:

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 16:55:11");

// retrieve date
echo $d->getDate();
?>

This is fairly simple - include the class code, initialise a Date() object with a date/time string, and then use the getDate() method to display the value you just inserted. Here's the output:

1951-09-13 16:55:11

What if you want the date in a different format? If the format is a standard one, such as the ISO format, simply pass getDate() a modifier indicating this:

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 16:55:11");

// retrieve date as timestamp
echo $d->getDate(DATE_FORMAT_ISO_BASIC);
?>

The output in this case conforms to the standard ISO format.

19510913T165511

If you'd like a custom format, you can do that too, with the format() method. Like PHP's native date() function, this method accepts a series of format specifiers that indicate how each component of the date is to be formatted. Below is an example (look in the class documentation for a complete list of modifiers):

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 16:55:11");

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>

And here's the output:

Thursday, 13 September 1951 16:55:11

Converting between time zones



Now that you've got the basics, let's talk about time zones. Once you have a Date() object initialised, converting from one time zone to another is a simple two-step process:
1. Tell the Date class which time zone you're converting from, with the setTZByID() method.
2. Then, tell the Date class which time zone you wish to convert to, with the convertTZByID() method.
Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 10:36:27");

// set local time zone
$d->setTZByID("GMT");

// convert to foreign time zone
$d->convertTZByID("IST");

// retrieve converted date/time
echo $d->format("%A, %d %B %Y %T");
?>

In this case, I'm attempting to convert from Greenwich Mean Time (GMT) to Indian Standard Time (IST). India is about 5.5 hours ahead of Greenwich, which is why the output of the script is:

Thursday, 13 September 1951 16:06:27

Simple, isn't it? Here's another example, this one demonstrating how the class handles leap years and month end values.

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2008-03-01 06:36:27");

// set local time zone
$d->setTZByID("GMT");

// print local time
echo "Local time is " . $d->format("%A, %d %B %Y %T") . "\n";

// convert to foreign time zone
$d->convertTZByID("PST");

// retrieve converted date/time
echo "Destination time is " . $d->format("%A, %d %B %Y %T");
?>

And the output is:

Code:

Local time is Saturday, 01 March 2008 06:36:27
Destination time is Friday, 29 February 2008 22:36:27

Note: In case you're wondering where the time zone IDs come from, you can find a complete list within the class documentation.

Calculating GMT offsets



Another piece of information that's sometimes useful when working with time zones is the GMT offset -- that is, the difference between the specified time zone and standard GMT. The PEAR Date class lets you get this information easily, via its getRawOffset() method. Here's an example:

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 10:36:27");

// set local time zone
$d->setTZByID("PST");

// get raw offset from GMT, in msec
echo $d->tz->getRawOffset();
?>

Here, the getRawOffset() method calculates the time difference between the local time and GMT. Here's the output:

-28800000

Note that this offset value is expressed in milliseconds, so you will need to divide it by 3600000 (the number of milliseconds in one hour) to calculate the time zone difference in hours.

Tip: You can use the inDaylightTime() method to see if the destination is currently observing daylight savings time. Look in the class documentation for details on this method.

Adding and subtracting timespans



The Date class also lets you perform sophisticated date arithmetic on temporal values, adding or subtracting durations to a date/time value. These durations (or timespans) are expressed as a string containing day, hour, minute and/or second components.

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 16:55:11");

// add 01:20 to it
$d->addSpan(new Date_Span("0,1,20,0"));

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>

In this case, I've added an hour and twenty minutes to the initial timestamp, by calling the Date class' addSpan() method and supplying it with a Date_Span() object initialised to that duration. The output is fairly easy to guess:

Thursday, 13 September 1951 18:15:11

Just as you can add timespans, so too can you subtract them. That, in fact, is the purpose of the subtractSpan() method, which is illustrated below.

Code: PHP

<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("1951-09-13 16:55:11");

// add 01:20 to it
$d->addSpan(new Date_Span("0,1,20,0"));

// subtract 00:05 from it
$d->subtractSpan(new Date_Span("0,0,5,0"));

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>

Here, I've first added an hour and twenty minutes, and then subtracted a further five minutes. The net effect is an addition of an hour and fifteen minutes, and the output reflects this:

Thursday, 13 September 1951 18:10:11

As the examples above illustrate, the PEAR Date class provides methods to easily and efficiently perform fairly complex date math. If you're looking for a stress-free way to convert timestamps between different locations, I'd recommend it to you.

ronmauldin 29Jul2007 18:36

Re: Using PEAR Date, converting between time zones in PHP
 
This article was helpful and got me started, but the way PEAR Date recognizes timezones is infinately more complex than suggested. Converting from EST to PST works as expected, but converting from EDT to PDT yields strange results... this is because PEAR Date is DST aware and any DST code is not a valid PEAR timezone entry.

First you need to convert your timezones to ones that are recognized by PEAR. Here is the PHP code I used to convert between various USA time zones:
PHP Code:

<?php

function getPEARtimeZoneAbbrevUSA($timeZone,$timeZoneDate){//returns time zones expected by PEAR Date
  /** Used by: convertDayTimeByZoneUSA
    * $timeZoneDate needs to be in YYYYMMDD format
    * PEAR has it own Time Zone IDs. To view all, download PEAR Date and view TimeZone.php source
    * PEAR is DST aware.
    * Arizona is the only location in Mountain time to not observe DST,
    * so they stay on MST. When MST is used during normal DST, PEAR will auto convert
    * it to MDT... not what most would expect. So the routine will assume that MST
    * when used during DST will be Arizona time.
    * first must get the DST start and end date for a given year. Beginning 2007,
    * United States Daylight Saving Time begins on the second Sunday in March and 
    * reverts to standard time on the first Sunday in November.
    */
    
$year $timeZoneDate[0].$timeZoneDate[1].$timeZoneDate[2].$timeZoneDate[3];
    
$DSTstart date('Ymd'strtotime("second Sunday"strtotime("March 0 ".$year)));
    
$DSTend date('Ymd'strtotime("first Sunday"strtotime("November 0 ".$year)));
    if (((
$timeZoneDate >= $DSTstart) && ($timeZoneDate $DSTend)) && ($timeZone == 'MST')) {$timeZone 'ARIZONA';}
    
    
//As of 2007, there are 13 different ways time zones are handled in the USA
    
$timeZone strtoupper($timeZone);
    switch (
$timeZone){
        case 
"ATLANTIC"     :
        case 
"AST"          :$timeZonePEAR 'America/Virgin';break;
        case 
"EASTERN"      :
        case 
"EDT"          :
        case 
"EST"          :$timeZonePEAR 'US/Eastern';break;
        case 
"CENTRAL"      :
        case 
"CDT"          :
        case 
"CST"          :$timeZonePEAR 'US/Central';break;
        case 
"ARIZONA (MST)":
        case 
"ARIZONA"      :$timeZonePEAR 'US/Arizona';break;
        case 
"MOUNTAIN"     :
        case 
"MST"          :
        case 
"MDT"          :$timeZonePEAR 'US/Mountain';break;
        case 
"PACIFIC"      :
        case 
"PDT"          :
        case 
"PST"          :$timeZonePEAR 'US/Pacific';break;
        case 
"ALASKA"       :
        case 
"AKDT"         :
        case 
"AKST"         :$timeZonePEAR 'US/Alaska';break;
        case 
"ALEUTIAN"     :
        case 
"HADT"         :
        case 
"HAST"         :$timeZonePEAR 'US/Aleutian';break;
        case 
"HAWAII"       :
        case 
"HST"          :$timeZonePEAR 'US/Hawaii';break;
        case 
"SAMOA"        :
        case 
"SST"          :$timeZonePEAR 'US/Samoa';break;
        case 
"MARSHALL"     :
        case 
"MHT"          :$timeZonePEAR 'Marshall Islands Time';break;
        case 
"MICRONESIA"   :
        case 
"YAPT"         :$timeZonePEAR 'Yap Time';break;
        case 
"GUAM"         :
        case 
"CHST"         :$timeZonePEAR 'Chamorro Standard Time';break;
        default             :
$timeZonePEAR 'US/Eastern';
    }
    return 
$timeZonePEAR;
}

function 
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT,
         
$dateFormat1 'l, F jS',$dateStr ' at ',$dateFormat2 'g:iA T'){
// $date must be in the format YYYYMMDD, $time must be in the format HHMM
// $timeZoneIN/OUT must be a USA standard or DST abbreviation
    
$timeZoneINpear  getPEARtimeZoneAbbrevUSA($timeZoneIN,$date);
    
$timeZoneOUTpear getPEARtimeZoneAbbrevUSA($timeZoneOUT,$date);
    
$year    $date[0].$date[1].$date[2].$date[3];
    
$month   $date[4].$date[5];
    
$day     $date[6].$date[7];
    
$hours   $time[0].$time[1];
    
$minutes $time[2].$time[3];
    
$seconds '00';
    
// $dayTime should be in the format "YYYY-MM-DD HH:MM:SS"
    
$dayTime $year.'-'.$month.'-'.$day.' '.$hours.':'.$minutes.':'.$seconds;
    
//$dayTime = date('Y-m-d H:i:s ', mktime($hours, $minutes, $seconds, $month, $day, $year));

    // include PEAR Date class
    
require_once ("Date.php");

    
// initialize object
    
$d = new Date($dayTime);

    
// set IN time zone
    
$d->setTZByID($timeZoneINpear);

    
// convert to OUT time zone
    
$d->convertTZbyID($timeZoneOUTpear);
    
     
/**
     *  format function options:
     *
     *  %a  ==  abbreviated weekday name (Sun, Mon, Tue) 
     *  %A  ==  full weekday name (Sunday, Monday, Tuesday) 
     *  %b  ==  abbreviated month name (Jan, Feb, Mar) 
     *  %B  ==  full month name (January, February, March) 
     *  %C  ==  century number (the year divided by 100 and truncated to an integer, range 00 to 99) 
     *  %d  ==  day of month (range 00 to 31) 
     *  %D  ==  same as "%m/%d/%y" 
     *  %e  ==  day of month, single digit (range 0 to 31) 
     *  %E  ==  number of days since unspecified epoch (integer, Date_Calc::dateToDays()) 
     *  %H  ==  hour as decimal number (00 to 23) 
     *  %I  ==  hour as decimal number on 12-hour clock (01 to 12) 
     *  %j  ==  day of year (range 001 to 366) 
     *  %m  ==  month as decimal number (range 01 to 12) 
     *  %M  ==  minute as a decimal number (00 to 59) 
     *  %n  ==  newline character (\n) 
     *  %O  ==  dst-corrected timezone offset expressed as "+/-HH:MM" 
     *  %o  ==  raw timezone offset expressed as "+/-HH:MM" 
     *  %p  ==  either 'am' or 'pm' depending on the time 
     *  %P  ==  either 'AM' or 'PM' depending on the time 
     *  %r  ==  time in am/pm notation, same as "%I:%M:%S %p" 
     *  %R  ==  time in 24-hour notation, same as "%H:%M" 
     *  %s  ==  seconds including the decimal representation smaller than one second 
     *  %S  ==  seconds as a decimal number (00 to 59) 
     *  %t  ==  tab character (\t) 
     *  %T  ==  current time, same as "%H:%M:%S" 
     *  %w  ==  weekday as decimal (0 = Sunday) 
     *  %U  ==  week number of current year, first sunday as first week 
     *  %y  ==  year as decimal (range 00 to 99) 
     *  %Y  ==  year as decimal including century (range 0000 to 9999) 
     *  %%  ==  literal '%' 
     */

    
$hours = ($d->format('%H'));
    
$minutes = ($d->format('%M'));
    
$seconds = ($d->format('%S'));
    
$month = ($d->format('%m'));
    
$day = ($d->format('%d'));
    
$year = ($d->format('%Y'));
    return 
date($dateFormat1mktime($hours$minutes$seconds$month$day$year)).$dateStr
          
.date($dateFormat2mktime($hours$minutes$seconds$month$day$year));
}

$date '20080401';
$time '0100';
$timeZoneIN 'Eastern';
$timeZoneOUT 'Pacific';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'PDT';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'Arizona';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'MST';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'MDT';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'Central';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

$date '20080401';
$time '0100';
$timeZoneIN 'EDT';
$timeZoneOUT 'CDT';
echo 
'Date In: '.$date.' / Time In: '.$time.' / Zone In: '.$timeZoneIN.'   -   Zone Out: '.$timeZoneOUT.'<br />Time Out: '.
     
convertDayTimeByZoneUSA($date,$time,$timeZoneIN,$timeZoneOUT).'<br /><br />';

?>


pradeep 29Jul2007 21:54

Re: Using PEAR Date, converting between time zones in PHP
 
Firstly, please use tag around the code you post!
Why don't you use time offsets to convert between time zones?

ronmauldin 30Jul2007 06:35

Re: Using PEAR Date, converting between time zones in PHP
 
HI Pradeep,

I don't know how to "tag around" the code I posted... this is my first post here. Perhaps you can instruct me?

There are many reasons to use a package such as PEAR Date. Time offsets can work for minor adjustments in time on the same day, but when time zones change such as this year (2007) in the USA... code much be altered... PEAR will be updated by others. The code I wrote is for a website that has live Webinars at a given time. When trying to host an event where some people are "in the next day"... then date math is involved... questions then arise... is it leap year... the end of DST/week/month/year. It is then much simpler to use pre-written code that is already meant for date/timezone conversion. Once I figured out how to use PEAR Date, it worked well. Ultimately, there was less coding and testing involved by using PEAR Date.

shabbir 30Jul2007 09:05

Re: Using PEAR Date, converting between time zones in PHP
 
Quote:

Originally Posted by ronmauldin
I don't know how to "tag around" the code I posted... this is my first post here. Perhaps you can instruct me?

Here is the link to complete instructions of how to go about it. http://www.go4expert.com/misc.php?do=bbcode#code

gkumar 26Jun2009 14:55

Re: Using PEAR Date, converting between time zones in PHP
 
PHP comes with an extensive catalog of date and time functions, however, a quicker alternative is to use the PEAR Date class, which comes with built-in support for time zones and is, by far, the simplest way to perform date conversions.


All times are GMT +5.5. The time now is 23:28.