像MSCRM這樣的全球性產品,使用時不可避免會遇到跨時區的問題,因此都會採取相應的措施。MSCRM利用FilteredView很好地處理了這個問題:在底層的資料庫表中,MSCRM實際儲存的是UTC時間,而相應的FilteredView則會有兩個時間,一個是UTC時間,一個是本地時間。MSCRM在將日期時間返回到頁面的時候,會返回這個本地時間。本地時間取決於不同的使用者的個人設定,在[Tools]->[Options]->[General]上面會有一個Time Zone設定。更改這裡的時區,將會影響到CRM頁面上時間的顯示。
作為編程和二次開發來講,也會遇到這個時間問題。MSCRM Web Service返回的時間類型是CrmDateTime類型,CrmDateTime類型有一個關鍵屬性:value。這個屬性支援UTC時間格式和本地時間格式。MSCRM Web Service返回的CrmDateTime.value是形如“2014-04-30T00:00:00-08:00”的日期時間格式,也就是說,會附帶時區位移量。而.Net Framework中的System.DateTime採取這樣格式的字串初始化時,如不指定時區和格式,會自動將其轉換成本地時間——這個本地時間,是.Net程式所在的本地時間,而不是MSCRM使用者佈建的本地時間。當這兩個本地時間不處在同一個時區時,容易因為混淆而引起程式bug,下面將會舉例。
假設MSCRM中其中一名使用者將其Time Zone設定為西八區(GMT -08:00),而.Net程式部署所在的作業系統時區設定為東八區(GMT +08:00)。這個時候通過調用MSCRM Web Service擷取的activeon時間為“2014-04-30T00:00:00-08:00”。轉換成System.DateTime之後時間變成“2014-04-30 16:00:00”,時區是東八區。如果程式儲存時,簡單地將System.DateTime變數來一個ToString再賦值給CrmDateTime,則MSCRM將會把“2014-04-30 16:00:00”作為該使用者佈建的本地時間(西八區)進行儲存。這樣一進一出將導致時間上相差16個小時。
因此,比較穩妥的辦法是,採用DateTime.Now.ToUniversalTime().ToString("u")將本地時間轉換成UTC時間,並且在ToString的時候一定要帶上UTC的格式。一句話,在儲存日期和時間欄位的時候,如果採用UTC時間,是最為穩妥的事情,這樣時間不會出現錯誤的位移。
查詢的時候,也要注意輸入的字串如果不是UTC格式的話,將會以使用者佈建的Time Zone當地時間進行查詢——這樣可能導致查不到準確的結果。