由於公司慢慢地開始將新的專案都移往 Windows Azure 雲端平台做網站代管,漸漸地也開始遇到一些小問題,這些問題在還沒上雲端之前通常不會發生,像我們這次遇到的問題就跟顯示時間有關。由於 Windows Azure 雲端平台是全球性、跨國家、跨地域的服務平台,因此,無論是 .NET 執行環境的時區,或是 SQL Database 資料庫的時區,預設都是以UTC 世界標準時間 (Coordinated Universal Time) 為主,也因此在上面執行的網站在顯示時間時,你就會覺得時間好像怪怪的,怎麼都不準。今天我就是要來講怎樣利用 ASP.NET MVC 的 範本檢視(Templated View) 來有效的解決這個問題。
首先,在使用 Azure WebSite 或 Azure Cloud Service 來執行網站時,由於你幾乎無法碰觸到執行環境的任何設定,因此變更系統時區變得不太可能,除非你直接租用 Azure Virtual Machine 才有機會,不過這種執行方式無法提升網站的延展性 (Scalability),且成本也高,因此不太建議直接租用 VM 來執行網站。
也因為你無法修改系統的時區設定,所以,要解決這個方法,只有兩種可能:
- 要儲存到資料庫或其他地方時,先將本地時間轉換成 UTC +8 的時間 (台北標準時間)
- 顯示資料時,再轉換成 UTC +8 的時間 (台北標準時間)
我個人是比較偏好儲存資料時一律使用 UTC 標準時間來儲存,以確保時間的一致性。然後顯示時間時,再利用 .NET 內建的轉換類別進行時區轉換,已顯示適當的本地時間。
註: 以下關於 範本檢視 的基本知識,建議可參考 ASP.NET MVC 4 開發實戰 第7章 View 相關技術。
由於我們在 ASP.NET MVC 裡面,大多是使用以下 Html 範本輔助方法來輸出各種時間:
@Html.DisplayFor(m => m.CreatedOn)
因此,要解決時間顯示的問題,解決的方法非常簡單,只要在 Views\Shared\DisplayTemplates 目錄下新增一個 DateTime.cshtml 檔案,如下圖示:
其 DateTime.cshtml 程式碼內容如下,註解都寫在程式中,各位可以自行到 MSDN 查閱相關說明:
@model DateTime?
@{
if (Model.HasValue)
{
DateTime dtCurrentTime; // 判斷本機的時區設定是否為 UTC 時間,如果是,就要進行轉換,否則就直接顯示本地時間
if (TimeZoneInfo.Local == TimeZoneInfo.Utc)
{
// 以下是取得 "台北標準時區" 的標準寫法
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Taipei Standard Time"); // 依據取得的時區進行時間轉換
dtCurrentTime = TimeZoneInfo.ConvertTime(Model.Value, tzi);
}
else
{
dtCurrentTime = Model.Value;
} @dtCurrentTime.ToString()
}
}
在 ASP.NET MVC 裡面,就這樣簡簡單單的新增一個檔案,整個網站的顯示時間就會全部都自動修正完畢,這也是我經常在課堂上講的【關注點分離】之美! (^_^)
課程公告:[台北市] 招生中,6/9(週日) Will 保哥 ...六週 開發實戰
§ 備註
如果想得知全球各時區的 id,建議可參考 TimeZoneInfo.GetSystemTimeZones Method 文件,裡面有範例程式可取得所有系統內建的 id 清單,如此一來你就可以利用 TimeZoneInfo.FindSystemTimeZoneById來取得特定地點的時區資訊。
為了方便各位查找,我已經取出所有時區的 id 清單,如有需要的也可以直接剪貼取用:
- Dateline Standard Time
- UTC-11Hawaiian Standard Time
- Alaskan Standard Time
- Pacific Standard Time (Mexico)
- Pacific Standard Time
- US Mountain Standard Time
- Mountain Standard Time
- Mountain Standard Time (Mexico)
- Central America Standard Time
- Central Standard Time
- Central Standard Time (Mexico)
- Canada Central Standard Time
- US Eastern Standard Time
- Eastern Standard Time
- SA Pacific Standard Time
- Venezuela Standard Time
- Paraguay Standard Time
- SA Western Standard Time
- Central Brazilian Standard Time
- Atlantic Standard Time
- Pacific SA Standard Time
- Newfoundland Standard Time
- E. South America Standard Time
- Argentina Standard Time
- Greenland Standard Time
- Montevideo Standard Time
- Bahia Standard Time
- SA Eastern Standard Time
- UTC-02Mid-Atlantic Standard Time
- Azores Standard Time
- Cape Verde Standard Time
- Morocco Standard Time
- UTCGreenwich Standard Time
- GMT Standard Time
- W. Central Africa Standard Time
- Central European Standard Time
- Romance Standard Time
- Namibia Standard Time
- Central Europe Standard Time
- W. Europe Standard Time
- Turkey Standard Time
- South Africa Standard Time
- Syria Standard Time
- E. Europe Standard Time
- Israel Standard Time
- Middle East Standard Time
- FLE Standard Time
- Egypt Standard Time
- GTB Standard Time
- Kaliningrad Standard Time
- E. Africa Standard Time
- Jordan Standard Time
- Arabic Standard Time
- Arab Standard Time
- Iran Standard Time
- Azerbaijan Standard Time
- Georgian Standard Time
- Russian Standard Time
- Caucasus Standard Time
- Mauritius Standard Time
- Arabian Standard Time
- Afghanistan Standard Time
- Pakistan Standard Time
- West Asia Standard Time
- Sri Lanka Standard Time
- India Standard Time
- Nepal Standard Time
- Ekaterinburg Standard Time
- Bangladesh Standard Time
- Central Asia Standard Time
- Myanmar Standard Time
- SE Asia Standard Time
- N. Central Asia Standard Time
- W. Australia Standard Time
- North Asia Standard Time
- China Standard Time
- Taipei Standard Time
- Singapore Standard Time
- Ulaanbaatar Standard Time
- North Asia East Standard Time
- Tokyo Standard Time
- Korea Standard Time
- Cen. Australia Standard Time
- AUS Central Standard Time
- Yakutsk Standard Time
- AUS Eastern Standard Time
- E. Australia Standard Time
- West Pacific Standard Time
- Tasmania Standard Time
- Vladivostok Standard Time
- Central Pacific Standard Time
- UTC+12New Zealand Standard Time
- Kamchatka Standard Time
- Fiji Standard Time
- Magadan Standard Time
- Tonga Standard Time
- Samoa Standard Time