天天看點

PHP中跨時區應用的解決方法

現在有一個跨時區的應用,不同時區登入的使用者需要看到自己時區的時間,同時也要能夠進行時區的切換,有什麼好辦法麼。

我的思路是,系統中所有存儲的時間都是GMT(UTC)時間,使用者登入時,根據使用者所在的時區進行對應的顯示。

首先了解一下PHP中時區的設定方法。PHP中進行設定的方法比較靈活多樣,可以在php.ini中設定date.timezone屬性、可以通過代碼,調用ini_set(‘date.timezone’, ‘’)設定,也可以使用函數 date_default_timezone_set(),或者在htaccess檔案中設定。

伺服器的預設時區,如果設定的和我們希望的時區不符,而且我們也沒有權限修改全局的時區配置,就隻有借助于代碼了。

PHP還提供了一個友善的函數,gmdate(),可以讓我們不用關心伺服器的時區設定而始終獲得GMT時間,我的思路就是基于這個函數。

我的項目中使用了Codeigniter這個架構,架構中的date這個helper提供了幾個友善的函數,可以用來處理應用中的多時區情況。

其中 now() 始終傳回的是gmt的目前時間;

local_to_gmt() 可以将本地的時間轉換為gmt時間;

gmt_to_local() 可以将gmt時間轉換為本地時間;

考慮一個典型的應用場景:

使用者登陸後,要顯示目前時間。這是我們可以使用now()獲得标準的gmt時間,然後使用gmt_to_local()函數轉化為使用者所在時區的時間。

使用者要釋出一個時間。使用者釋出了一個“2010-07-10 18:30:00”的時間,我們不能直接存入資料庫,必須先利用local_to_gmt() 轉化标準的gmt時間存入資料庫,這樣才能保證整個系統中的時間保持一緻。

這兩個函數的細節,其實都是根據時區,然後進行相應的運算得來。計算的時候,也可以考慮夏令時,但是所在時區夏令時的開始和結束時間,則需要自己維護。

codeigniter中提供了一份較為完整的時區清單,timezone_menu() 可以顯示一個時區的下拉清單,但是這個清單中的時間不能完全對應到PHP自帶的時區顯示上,這是PHP本身的問題,不過可以通過下面這個函數,來讓輸入的每個時區,都可以獲得一個對應的時區文字顯示。

if( ! function_exists("tz_offset_to_name") ) {     /* Takes a GMT offset (in hours) and returns a timezone name */     function tz_offset_to_name($offset)     {             $offset *= 3600; // convert hour offset to seconds             $abbrarray = timezone_abbreviations_list();             foreach ($abbrarray as $abbr)             {                     foreach ($abbr as $city)                     {                             if ($city['offset'] == $offset)                             {                                     return $city['timezone_id'];                             }                     }             }             return FALSE;     } }

參考資料: