2015-02-11 18 views
1

我們有+3時區服務器上託管的ASP.NET應用程序。數據庫也位於+3時區。客戶可以在其他時區。如何在ASP.NET應用程序中調整時區?

應用程序按日期範圍搜索某些事件。我們使用2個Bootstrap日期選取器(BeginDate和EndDate)來選取日期。問題是在選定的BeginDate被返回之前的一些事件,這是不正確的。例如,如果我們在客戶端選擇BeginDate = 11.02.2015。和EndDate = 11.02.2015。對於某些時區,時間以這種方式移動:

  1. 客戶端在+3時區:@ BeginDate ='2015-02-11 00:00:00',@ EndDate ='2015-02 -11 00:00:00'(因爲客戶端和服務器處於同一時區,所以沒有移位)
  2. 客戶端在+6時區:@ BeginDate ='2015-02-10 21:00:00 ',@ EndDate ='2015-02-10 21:00:00'(由於客戶端服務器時區爲+3,所以有3小時的班次)
  3. 客戶端在+7時區:@ BeginDate ='2015-02-10 20:00:00',@ EndDate ='2015-02-10 20:00:00'(因爲客戶端的服務器時區爲+4,所以有4小時的轉換)
  4. 客戶端在+8時區:@ BeginDate ='2015-02-10 19:00:00',@ EndDate ='2015-02-10 19:00:00'(有5個小時的轉換,因爲客戶端是與服務器時區相關的+5)

很明顯,前一天10.02.2015發生了一些事件。也將返回。

如何解決這個問題?

其他信息:

看來這個問題是在客戶端,我們有下面的代碼:

$scope.actionDatesQuery = { 
    actionId: -1, 
    limit: 10, 
    toJSON: function() { 
     return ($scope.actionsQuery.searchText) ? { 
      ActionId: this.actionId, 
      FromDate: moment().toJSON(), 
      ToDate: moment().add('y', 1).toJSON() 
     } : { 
      ActionId: this.actionId, 
      FromDate: ($scope.actionsQuery.fromDate) ? moment($scope.actionsQuery.fromDate).toJSON() : moment().toJSON(), 
      ToDate: ($scope.actionsQuery.toDate) ? moment($scope.actionsQuery.toDate).add('d', 1).toJSON() : moment().add('y', 1).toJSON(), 
      IsOpenDatesIncluded: $scope.actionsQuery.isOpenDatesIncluded 
     }; 
    } 
}; 

選擇沒有fromdate和todate日期後,我們使用他們的服務器端:

public IEnumerable<ActionInformation> QueryActionsInformation(ActionsQuery query) 
{ 
    var sql = query.BuildSql(); 
    using (var cn = ConcertDb.CreateSqlConnection()) 
    { 
     var searchText = string.Empty; 
     if (!string.IsNullOrWhiteSpace(query.SearchText)) 
      searchText = "%" + DapperUtils.EncodeLikeString(query.SearchText) + "%"; 

     return cn.Query<ActionInformationDTO>(sql, new 
     { 
      BeginDate = query.FromDate, 
      EndDate = query.ToDate, 
      query.CounterAgentId, 
      SearchText = searchText, 
      query.CityId, 
      query.ActionPlaceId, 

      query.ActionTypeIDArray, 
      query.MaxPrice, 
      query.MinPrice 
     }).Select(t => (ActionInformation) t); 
    } 
} 

正如你所看到的,我們也使用了moment.js庫,並且似乎我應該在客戶端更改該部分,但我不確定以哪種方式。

+1

你知道客戶的*實際時區*嗎?這不僅僅是一個單一的UTC抵消 - 它可以在一年中有所不同,如果他們在一個觀察DST的區域。有多種方式通過Javascript檢測時區。另外,數據如何存儲?如果每個事件都發生在單個時區中,則可能需要存儲事件的* local *時間(以及指示時區的事件)。如果沒有,我建議將它們存儲在UTC中 - 嘗試擺脫對服務器或數據庫時區的任何*依賴關係。 – 2015-02-11 07:39:44

+0

(並請提供一些關於這些事件的更多信息。) – 2015-02-11 07:41:37

+0

通常,您只應在serv/DB端處理UTC。所以客戶應該發送/接收UTC日期並顯示其本地日期時間,這很容易用Javascript完成。只要你嚴格遵守,就不應該有任何問題。你必須確保你的控制器不會嘗試再次轉換接收到的日期*(看看DateTime.Kind),這是我在類似項目中注意到的令人討厭的行爲。 – Robert 2015-02-11 07:50:50

回答

0

你應該做一個概念轉換:不要在你的數據庫中存儲分區時間,而是使用UTC來代替。這樣,你的服務器的物理位置就無關緊要了。

然後,在客戶端,您可以使用JavaScript函數Date.getTimezoneOffset()並將其值傳遞給隱藏字段。回發後,您可以讀取服務器端的值並以適當的方式對其作出反應。

+0

對於這樣的交換機來說已經太晚了,因爲我們的數據庫包含大量原樣存儲的數據。 – tesicg 2015-02-11 08:20:53

+1

此建議可能*不適用 - 「使用UTC」不應被視爲一攬子建議。如果某個事件處於特定時區,那麼該信息本身就很有用。例如,如果我要去旅行,我想在那裏看戲時,那只是*本地*日期和時間對我來說很有趣,而不是UTC時間或與尊重我的「家」區。另一方面,對於全球事件(例如網絡廣播),沒有真正的「事件區」,並且UTC是最合適的。但我肯定會同意不存儲相對於服務器區域的東西。 – 2015-02-11 10:21:59

+0

@JonSkeet當然。但是你不是在這裏把某個本地時間/事件的「含義」(即語義)與這次抽象爲具有通用存儲策略(即其語法)的技術方面混合在一起嗎? – 2015-02-11 11:53:24

相關問題