PHP CookBook Free Open Book

PHP CookBook

Previous Section Next Section

Recipe 3.12 Calculating Time with Time Zones

3.12.1 Problem

You need to calculate times in different time zones. For example, you want to give users information adjusted to their local time, not the local time of your server.

3.12.2 Solution

For simple calculations, you can explicitly add or subtract the offsets between two time zones:

// If local time is EST
$time_parts = localtime();
// California (PST) is three hours earlier
$california_time_parts = localtime(time() - 3 * 3600);

On Unix-based systems, if you don't know the offsets between time zones, just set the TZ environment variable to your target time zone:

putenv('TZ=PST8PDT');
$california_time_parts = localtime();

3.12.3 Discussion

Before we sink too deeply into the ins and outs of time zones, we want to pass along the disclaimer that the U.S. Naval Observatory offers at http://tycho.usno.navy.mil/tzones.html. Namely, official worldwide time-zone information is somewhat fragile "because nations are sovereign powers that can and do change their timekeeping systems as they see fit." So, remembering that we are at the mercy of the vagaries of international relations, here are some ways to cope with Earth's many time zones.

For a relatively simple treatment of offsets between time zones, use an array in your program that has the various time zones' offsets from UTC. Once you determine what time zone your user is in, just add that offset to the appropriate UTC time and the functions that print out UTC time (e.g., gmdate( ), gmstrftime( )) can print out the correct adjusted time.

// Find the current time 
$now = time();

// California is 8 hours behind UTC
$now += $pc_timezones['PST'];

// Use gmdate() or gmstrftime() to print California-appropriate time
print gmstrftime('%c',$now);

The previous code uses this $pc_timezones array, which contains offsets from UTC:

// From Perl's Time::Timezone
$pc_timezones = array(
  'GMT'  =>   0,           // Greenwich Mean
  'UTC'  =>   0,           // Universal (Coordinated)
  'WET'  =>   0,           // Western European
  'WAT'  =>  -1*3600,      // West Africa
  'AT'   =>  -2*3600,      // Azores
  'NFT'  =>  -3*3600-1800, // Newfoundland
  'AST'  =>  -4*3600,      // Atlantic Standard
  'EST'  =>  -5*3600,      // Eastern Standard
  'CST'  =>  -6*3600,      // Central Standard
  'MST'  =>  -7*3600,      // Mountain Standard
  'PST'  =>  -8*3600,      // Pacific Standard
  'YST'  =>  -9*3600,      // Yukon Standard
  'HST'  => -10*3600,      // Hawaii Standard
  'CAT'  => -10*3600,      // Central Alaska
  'AHST' => -10*3600,      // Alaska-Hawaii Standard
  'NT'   => -11*3600,      // Nome
  'IDLW' => -12*3600,      // International Date Line West
  'CET'  =>  +1*3600,      // Central European
  'MET'  =>  +1*3600,      // Middle European
  'MEWT' =>  +1*3600,      // Middle European Winter
  'SWT'  =>  +1*3600,      // Swedish Winter
  'FWT'  =>  +1*3600,      // French Winter
  'EET'  =>  +2*3600,      // Eastern Europe, USSR Zone 1
  'BT'   =>  +3*3600,      // Baghdad, USSR Zone 2
  'IT'   =>  +3*3600+1800, // Iran
  'ZP4'  =>  +4*3600,      // USSR Zone 3
  'ZP5'  =>  +5*3600,      // USSR Zone 4
  'IST'  =>  +5*3600+1800, // Indian Standard
  'ZP6'  =>  +6*3600,      // USSR Zone 5
  'SST'  =>  +7*3600,      // South Sumatra, USSR Zone 6
  'WAST' =>  +7*3600,      // West Australian Standard
  'JT'   =>  +7*3600+1800, // Java 
  'CCT'  =>  +8*3600,      // China Coast, USSR Zone 7
  'JST'  =>  +9*3600,      // Japan Standard, USSR Zone 8
  'CAST' =>  +9*3600+1800, // Central Australian Standard
  'EAST' => +10*3600,      // Eastern Australian Standard
  'GST'  => +10*3600,      // Guam Standard, USSR Zone 9
  'NZT'  => +12*3600,      // New Zealand
  'NZST' => +12*3600,      // New Zealand Standard
  'IDLE' => +12*3600       // International Date Line East
);

On Unix systems, you can use the zoneinfo library to do the conversions. This makes your code more compact and also transparently handles DST, as discussed in Recipe 3.13.

To take advantage of zoneinfo in PHP, do all your internal date math with epoch timestamps. Generate them from time parts with the pc_mktime( ) function shown in Example 3-2.

Example 3-2. pc_mktime( )
function pc_mktime($tz,$hr,$min,$sec,$mon,$day,$yr) {
    putenv("TZ=$tz");
    $a = mktime($hr,$min,$sec,$mon,$day,$yr);
    putenv('TZ=EST5EDT');   // change EST5EDT to your server's time zone!
    return $a;
}

Calling putenv( ) before mktime( ) fools the system functions mktime( ) uses into thinking they're in a different time zone. After the call to mktime( ), the correct time zone has to be restored. On the East Coast of the United States, that's EST5EDT. Change this to the appropriate value for your computer's location (see Table 3-5).

Time parts are turned into epoch timestamps by pc_mktime( ). Its counterpart, to turn epoch timestamps into formatted time strings and time parts, is pc_strftime( ), shown in Example 3-3.

Example 3-3. pc_strftime( )
function pc_strftime($tz,$format,$timestamp) {
    putenv("TZ=$tz");
    $a = strftime($format,$timestamp);
    putenv('TZ=EST5EDT');   // change EST5EDT to your server's time zone!
    return $a;
}

This example uses the same system-function-fooling pc_mktime( ) does to get the right results from strftime( ).

The great thing about these functions is that you don't have to worry about the offsets from UTC of different time zones, whether DST is in effect, or any other irregularities of time-zone differences. You just set the appropriate zone and let your system's libraries do the rest.

Note that the value of the $tz variable in both these functions should not be a time-zone name but a zoneinfo zone. zoneinfo zones are more specific than time zones, because they correspond to particular places. Table 3-5 contains mappings for appropriate zoneinfo zones for some UTC offsets. The last column indicates whether the zone observes DST.

Table 3-5. zoneinfo zones

UTC offset (hours)

UTC offset (seconds)

zoneinfo zone

DST?

-12

-43200

Etc/GMT+12

No

-11

-39600

Pacific/Midway

No

-10

-36000

US/Aleutian

Yes

-10

-36000

Pacific/Honolulu

No

-9

-32400

America/Anchorage

Yes

-9

-32400

Etc/GMT+9

No

-8

-28800

PST8PDT

Yes

-8

-28800

America/Dawson_Creek

No

-7

-25200

MST7MDT

Yes

-7

-25200

MST

No

-6

-21600

CST6CDT

Yes

-6

-21600

Canada/Saskatchewan

No

-5

-18000

EST5EDT

Yes

-5

-18000

EST

No

-4

-14400

America/Halifax

Yes

-4

-14400

America/Puerto_Rico

No

-3.5

-12600

America/St_Johns

Yes

-3

-10800

America/Buenos_Aires

No

0

0

Europe/London

Yes

0

0

GMT

No

1

3600

CET

Yes

1

3600

GMT-1

No

2

7200

EET

No

2

7200

GMT-2

No

3

10800

Asia/Baghdad

Yes

3

10800

GMT-3

No

3.5

12600

Asia/Tehran

Yes

4

14400

Asia/Dubai

No

4

14400

Asia/Baku

Yes

4.5

16200

Asia/Kabul

No

5

18000

Asia/Tashkent

No

5.5

19800

Asia/Calcutta

No

5.75

20700

Asia/Katmandu

No

6

21600

Asia/Novosibirsk

Yes

6

21600

Etc/GMT-6

No

6.5

23400

Asia/Rangoon

No

7

25200

Asia/Jakarta

No

8

28800

Hongkong

No

9

32400

Japan

No

9.5

34200

Australia/Darwin

No

10

36000

Australia/Sydney

Yes

10

36000

Pacific/Guam

No

12

43200

Etc/GMT-13

No

12

43200

Pacific/Auckland

Yes

Countries around the world don't begin and end DST observance on the same days or at the same times. To calculate time appropriately for an international DST-observing location, pick a zoneinfo zone that matches your desired location as specifically as possible.

3.12.4 See Also

Recipe 3.13 for dealing with DST; documentation on putenv( ) at http://www.php.net/putenv, localtime( ) at http://www.php.net/localtime, gmdate( ) at http://www.php.net/gmdate, and gmstrftime( ) at http://www.php.net/gmstrftime; zoneinfo zone names and longitude and latitude coordinates for hundreds of places around the world are available at ftp://elsie.nci.nih.gov/pub/tzdata2002c.tar.gz; many links to historical and technical information about time zones can be found at http://www.twinsun.com/tz/tz-link.htm.

    Previous Section Next Section
    Index: [SYMBOL][A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Z]


         Main Menu
    Main Page
    Table of content
    Copyright
    Preface
    Chapter 1. Strings
    Chapter 2. Numbers
    Chapter 3. Dates and Times
    3.1 Introduction
    Recipe 3.2 Finding the Current Date and Time
    Recipe 3.3 Converting Time and Date Parts to an Epoch Timestamp
    Recipe 3.4 Converting an Epoch Timestamp to Time and Date Parts
    Recipe 3.5 Printing a Date or Time in a Specified Format
    Recipe 3.6 Finding the Difference of Two Dates
    Recipe 3.7 Finding the Difference of Two Dates with Julian Days
    Recipe 3.8 Finding the Day in a Week, Month, Year, or the Week Number in a Year
    Recipe 3.9 Validating a Date
    Recipe 3.10 Parsing Dates and Times from Strings
    Recipe 3.11 Adding to or Subtracting from a Date
    Recipe 3.12 Calculating Time with Time Zones
    Recipe 3.13 Accounting for Daylight Saving Time
    Recipe 3.14 Generating a High-Precision Time
    Recipe 3.15 Generating Time Ranges
    Recipe 3.16 Using Non-Gregorian Calendars
    Recipe 3.17 Program: Calendar
    Chapter 4. Arrays
    Chapter 5. Variables
    Chapter 6. Functions
    Chapter 7. Classes and Objects
    Chapter 8. Web Basics
    Chapter 9. Forms
    Chapter 10. Database Access
    Chapter 11. Web Automation
    Chapter 12. XML
    Chapter 13. Regular Expressions
    Chapter 14. Encryption and Security
    Chapter 15. Graphics
    Chapter 16. Internationalization and Localization
    Chapter 17. Internet Services
    Chapter 18. Files
    Chapter 19. Directories
    Chapter 20. Client-Side PHP
    Chapter 21. PEAR
    Colophon
    Index


    More Books
    PHP Hacks
    Processing Xml With Java - A Guide To Sax, Dom, Jdom, Jaxp, And Trax
    The Koran (Holy Qur'an)
    Macromedia Flash 8 Bible
    Search Engine Optimization for Dummies
    YouTube Traffic
    PHP 5 for Dummies
    Harry Potter and The Chamber of Secrets
    Harry Potter and the Sorcerer's Stone
    The Pilgrim's Progress
    Wireless Hacks
    Flash Hacks. 100 Industrial-Strength Tips & Tools
    PayPal Hacks. 100 Industrial-Strength Tips and Tools
    Amazon Hacks
    Pdf Hacks
    The Da Vinci Code
    Google Hacks
    The Holy Bible
    Windows XP For Dummies
    Harry Potter and the Half-Blood Prince
    Seo Book
    Upgrading and Repairing Networks
    Macromedia Dreamweaver 8 UNLEASHED
    Windows XP Annoyances
    Windows XP Hacks
    Microsoft Windows XP Power Toolkit
    Teach Yourself MS Office In 24Hours
    iPod & iTunes Missing Manual
    PC Hacks 100 Industrial-Strength Tips and Tools
    PC Overclocking, Optimization, and Tuning - 2th Edition
    PC Hardware In A Nutshell 3rd Edition
    PC Hardware in a Nutshell, 2nd Edition
    Upgrading and Repairing PCs
    Google for Dummies
    MySQL Cookbook
    Teach Yourself Macromedia Flash 8 In 24 Hours
    PHP CookBook
    Sams Teach Yourself JavaScript in 24 Hours
    PHP5 Manual
    Free Games Paper Airplanes
    500 Juegos Gratis 500 Giochi Gratis 500 Jeux Gratuits 500 Jogos Gratis 500 Kostenlose Spiele