2016-06-16 73 views
1

我想了解究竟是什麼責任在我的應用程序堆棧中分別更改和轉換時區和時間,以及在應用程序代碼中將時間轉換爲所需時區的最佳方法是什麼。在PHP和MySQL中處理時區

我目前正在使用:

的JavaScript/HTML字體結束

Laravel的PHP框架服務器端

MySQL存儲(默認爲本地系統時間時間戳等)

我的意見是:

MySQL無法存儲DateTime列的時區,只是存儲YYY:MM:DD hh:mm:ss,並由開發人員將時區存儲在單獨的列中,並將存儲的時間轉換爲應用程序代碼中的本地用戶如果用戶時區不同。

PHP,Laravel應用程序應該工作並將任何DateTime實例轉換爲使用date_default_timezone_set()函數設置的時區。

行爲我目前觀察:

我回來後與JavaScript的日期時間格式設置對象屬性JSON。這種格式看起來像我這樣:例如'Thu Jun 16 2016 18:00:00 GMT + 1000(AEST)'

當這個json數據命中我的服務器時,即使我將date_default_timezone_set('Australia/Sydney ')在控制器類中或更改應用程序配置,替換laravel UTC默認值。我懷疑有東西沒有註冊?如果我能夠節省時間,因爲它來自客戶端(不會自動轉換爲UTC),如果用戶在澳大利亞/悉尼(這其中大部分是用戶),我不必稍後將其轉換爲用戶本地時區)。

我的應用程序將此UTC調整時間存儲在數據庫中,但實際上沒有任何記錄表示它是UTC。當然不是很重要,因爲我可以推測UTC的默認值。

當使用雄辯或DB:查詢檢索記錄時,沒有自動轉換爲用戶時區,它只是返回存儲(轉換爲UTC)時的時間,需要應用程序代碼將其轉換爲正確的時區,否則用戶(在澳大利亞我的情況)將尋求UTC時間,而不是本地AEST等等

轉換時間:

有自動轉換所有檢索到的UTC時間從數據庫中一個輕鬆自由的方式用戶本地時區或某個指定的默認時區,如果所有用戶都是從同一時區推定的?

理想情況下,我想從數據庫中提取記錄,並將所有時間屬性調整爲指定的時區,並考慮夏時制。我將不得不運行一個for循環,並用Carbon方法等來轉換/設置每個屬性?

如果date_default_timezone_set('澳大利亞/悉尼)設置並正常工作,應該PHP自動轉換的時間屬性對所有這些對象,因爲它們是從數據庫中檢索?當它打到服務器時不將時間數據轉換爲UTC?

回答

1

時區是煩人,毫無疑問有關。如果我正確理解你,你希望你的PHP返回次是在用戶正確的區域來看,對不對?

我所做的是在'主視圖'或某種或blade.php文件中保證至少加載一次,我檢查此用戶的時區是否存儲在會話變量中。如果不是,我發送一個AJAX請求到服務器來存儲時區的名稱。

{{-- store timezone in session variables --}} 
@if (!Session::has('timezone')) 
    <script> 
     $(function() { 
      var tz = jstz.determine(); 
      var data = {}; 
      if (typeof (tz) !== 'undefined') { 
       data.timezone = tz.name(); 
      } 
      if (!$.isEmptyObject(data)) { 
       $.ajax({ 
        type: "POST", 
        url: "{{ url('/api/v1/settings') }}", 
        beforeSend: function (request) { 
         request.setRequestHeader("X-CSRF-TOKEN", "{{ csrf_token() }}"); 
        }, 
        data: $.param(data), 
       }); 
      } 
     }); 
    </script> 
@endif 

注意,這種方法utilizies的jstz包,您可以download here,包括您在<head>部分。

當然,你將需要建立路由這一要求,對於我來說,這看起來是這樣的:

Route::post('api/v1/settings', function() { 
    // Save the user's timezone 
    if (Request::has('timezone')) { 
     Session::put('timezone', Request::get('timezone')); 
    } 
}); 

現在,當你想給定數據庫日期時間字符串轉換爲正確的時區,你可以這樣$tz = $request->session()->get('timezone')獲得時區,然後解析出日期與Carbon\Carbon::parse($date, $tz);

在一般情況下,我會recommmend你留在存儲UTC格式的所有日期,因爲這是標準,它是imperitive數據庫保持時區不可知。但是,如果你想改變默認的,你可以在config/app.php編輯該行'timezone' => 'UTC'。這將覆蓋Laravel默認的時間戳,所以你的created_at,的updated_at將被改變,以反映新的時區的區域。

0

哎 - 好老「做什麼用的時區」的問題。就我個人而言,在我的一個L5.2項目中,需要用戶時區格式來顯示數據。我允許用戶在帳戶設置頁面上選擇/修改他們的時區。然後我將它存儲在數據庫中,並建立關係進行檢索。例如,我有許多屬於一家公司的用戶。所以在我的「公司」表中,我在這裏有一個時區字段。通過適當的關係,我可以像這樣訪問它Auth::user()->company->timezone

然後我使用Carbon解析與平臺相關的所有日期。例如,$current_date = Carbon:parse($date, Auth::user()->company->timezone);。如果我不懶惰(有其他優先級),並且不需要更新一堆代碼,我可能會爲我的模型創建一個trait以自動轉換日期屬性。儘管如此,有很多方法 - 如果您的平臺嚴重位於用戶時區,這可能是一件棘手的事情。例如,你可以在每個模型中做這樣的事情(或者創建一個特徵 - 最好的選擇 - 存儲這個)。請注意,我以我的時區關係爲例。顯然,將「some_date」等改爲表名。根據需要重複對於每一日期,你需要轉換:

/** 
* Convert date to user's timezone 
* 
* @return mixed 
*/ 
public function setSomeDateAttribute($value) 
{ 
    $this->attributes['some_date'] = Carbon::parse($value, Auth::user()->company->timezone); 
} 

注,日期應始終保存在數據庫中的UTC。切勿將用戶的時區格式化日期保存在數據庫中。