2014-05-06 20 views
0

快速環境概述:Azure中WebRole UTC轉換爲本地時區

我有一個最終被託管作爲Azure的Webrole的ASP.NET MVC/AngularJS應用。數據存儲在同一個Azure數據中心(通過MongoLab)託管的MongoDB中。開發環境和登臺環境(Azure)指向相同的MongoDB數據庫,因此可以看到完全相同的數據。

問題:

該應用程序的個人用戶存儲與他們的優選的時區作爲字符串(TimezoneID)。應用程序中的所有日期都以UTC時間存儲。轉換和從UTC時間爲用戶特定的時區通過其最終調用擴展方法在服務器上完成:

return TimeZoneInfo.ConvertTimeFromUtc(UtcDate, _lookup[TimeZoneID]); 

無處在整個應用程序有沒有DateTime.Now或任何其他日期轉換我期望使用服務器時間設置。

在應用程序的特定區域中,日期存儲在Mongo(UTC)中。我可以確認日期是否正確存儲爲UTC(基於當地時間的偏移量)。當我從數據存儲中檢索該日期並將其轉換回當地時間(中央標準時間)時,我跨過上面的代碼行,轉換工作正常,本地時間已設置。結果作爲API調用的Json結果的一部分發送到客戶端的瀏覽器,並正確顯示給用戶。在運輸過程中的MVC JSON序列解析日期時間到類似的格式:

EventDate: "/Date(1399407153971)/" 

我解析這個在Javascript並相應地顯示,一切都很好。

當我將完全相同的代碼部署到Azure(它指向Mongo中的完全相同的數據存儲)時,通過API調用的結果看起來已經應用了UTC轉換兩次(意思是常規的6小時UTC偏移量被應用兩次,顯示的日期比UTC早12小時......我想要的是6小時)。

我已經在Mongo中更新了一兩分鐘的存儲時間,以確保雙方都進行更新並且他們這樣做(驗證相同的數據)。我修改了本地機器的日期/時間設置,以查看它是否對我的本地結果有任何影響,但是沒有。我已經更改了應用中選定用戶的時區,並且我的本地結果和Azure返回的結果都根據中央標準時間和新時區之間的UTC偏移差異進行了調整(這意味着如果我切換到Mountain Time兩者的結果本地結果和Azure結果調整1小時...但仍然是6小時)。我已通過Chrome開發工具確認,在客戶端檢索到的日期(通過Json)根據網站點擊是否爲刪除(Azure)環境或本地環境而不同(意思是它未被錯誤修改)上的任何客戶端後 - 事實)

這裏是最有說服力的事情:

如果我轉換日期爲字符串返回給客戶之前下發的字符串出現在JSON響應正確。如果我將它保留爲.NET DateTime類型(作爲複雜對象的屬性),則Json序列化程序似乎會再次進行翻譯,但只有在Azure中託管時纔會進行翻譯。這表明問題與我返回日期的DateTimeKind有關。儘管在這一點上,我幾周以來一直在迷失方向,看看爲什麼我的本地環境和Azure主機環境在序列化方面的差異,以及爲什麼一次一件事是正確的,另一次是將其轉換兩次。如果DateKindTime錯誤,兩個環境都不會執行相同的轉換嗎?

感謝您閱讀本文,我會很感激任何想法解決任何人。

回答

1

這是一個很長的帖子:) 如果我是你,我會轉移UTC格式的所有dateTimes。就我而言,服務器基本上必須使用UTC時間。客戶轉換到客戶時必須在客戶端應用。你可以使用momentjs庫,這個庫被證明是用於處理日期和時間的非常好的庫。

在客戶端做這樣的事情

var date = { 
     utc: '/Date(1399407153971)/', //time that you have recieved 
     offset: 240 
      } 

var localTime = moment.utc(date.utc).zone(date.offset).format('DD/MM/YYYY hh:mm'); 

我希望這有助於

UPD 馬特·約翰遜指出,你可以把它即使當前時區短。

var localTime = moment('/Date(1399407153971)/').format('DD/MM/YYYY hh:mm'); 
+0

小心,這將得到*當前*時區偏移量 - 不一定是適用於有問題的值的偏移量。而且,根本不需要指定區域,因爲時刻會自動處理該區域。只需調用構造函數並傳遞值即可。請參閱[這些文檔](http://momentjs.com/docs/#/parsing/asp-net-json-date/)。 –

+0

是的,你是對的沒有必要指定區域。我會更新我的回答 – nomail

+0

固定爲雅。如果你使用'moment.utc',除非你調用'.local()',否則結果將會是utc。由於這種特定的輸入格式隱含地是UTC,因此您可以直接解析它。如果您使用帶有「Z」說明符的ISO格式,或者使用了某個特定的偏移量,則相同。只有在輸入中沒有上下文的情況下,您可能需要明確使用'moment.utc(...)'。但是我們在這裏得到了主題! :) –

1

這很難肯定地說沒有看到更多的代碼,但是會不會是這個問題是在路上轉換在,而不是出路何在?你說你正在使用TimeZoneInfo.ConvertTimeFromUtc作爲輸出。你是否也在另一邊使用TimeZoneInfo.ConvertTimeToUtc?如果是這樣,那很可能是選擇當地時區的來源。

你也可能在某個地方打電話給DateTime.ToUniversalTime,它再次使用當地時區。

可能是罪魁禍首的另一個領域 - 當您從Mongo中檢索到您的價值時,請檢查返回值的Kind。如果它們是Unspecified,那麼當它們被序列化爲JSON時,它們將被視爲它們是Local。基本上,有一個ToUniversalTime呼叫正在進行。因此,您可能需要明確呼叫DateTime.SpecifyKind,以便在出門前將值設置爲Utc

對於Azure的具體問題,它遵循將服務器時區設置爲UTC的最佳做法。你可以在自己的機器上試試,看看你是否得到了類似的結果。

當然,你真的不希望服務器的時區影響結果。

您可能需要考慮用minimal, complete, and verifiable example創建一個新項目。這將有助於您驗證您的假設,並可能會追蹤問題的根源。如果它仍然失敗,那麼你會更好地尋求幫助。

相關問題