2014-03-25 48 views
35

我有一个日期作为日期存储在SQL Server中。日期显示4/24/2014当我在SQL中查询。那是对的。日期被正确地带到UTC的客户端。要编辑该日期,我们使用的是Angular UI DatePicker。 DatePicker根据我的本地时区调整该日期,因此它总是关闭一天。针对时区的角度UI DatePicker调整

我可以看到它正在发生。如果我们编辑日期时间而不是日期,那么为时区调整是正确的。然而,在这种情况下,我只是有一个日期,所以我不在乎时区,我只是想编辑日期,因为它在数据库中。

我可以验证它是否在调整时区。如果我将Windows机器上的时区更改为UTC,则DatePicker会显示正确的日期。

所以,问题是,有没有办法告诉DatePicker关闭时区调整,只管理UTC格式的日期,以便它可以使用SQL Date而不是SQL Datetime?

回答

34

前段时间我有一个非常类似的问题:我想在服务器端存储本地日期(即只是yyyy-mm-dd,没有timezome /时间信息),但由于Angular Bootstrap Datepicker使用JavaScript Date对象这是不可能的(它会在JSON中序列化为UTC日期时间字符串,就像你自己发现的那样)。

我解决此指令该问题:https://gist.github.com/weberste/354a3f0a9ea58e0ea0de

本质上讲,我重新格式化每当日期在日期选择器(此值,YYYY-MM-DD格式的字符串中选择的值,将存储在模型),并且每当访问模型来填充视图时,我需要再次将它包装在Date对象中,以便datepicker正确处理它。

+0

它还挺作品之间的所有错误。但是,当您第一次使用来自服务器的yyyy-mm-dd字符串进行设置时,datepicker会调整时区。你如何防止它?有一张票在这里打开:[问题2072](https://github.com/angular-ui/bootstrap/issues/2072) – jlareau

+1

好点,谢谢你指出 - 这是一个时区问题我相信UTC在后面。通过“撤销”JavaScript日期引入的时区调整来更新Gist来解决此问题。 – weberste

+0

这个解决方案很好地工作,谢谢分享。 –

1

首先我想指出bootstrap的本地化日期选择器是愚蠢的和无用的,没有人需要这样的东西,所有你真正想要的是一个日期yyyy-MM-dd,我看不到本地化日期当你不需要时间。

我不会试图弯曲客户端来适应服务器的时区,这是矫枉过正,不起作用。 我做的却是让在它的用户工作的时区,并像这样发送到服务器之前格式化日期:

fields.date = dateFilter(trans.date, 'MM/dd/yy'); 

这确保了无论用户看到日期选取器我收到在服务器端。如果你问我,这是至关重要的。 如果您需要设置最小和最大的日期,同样,只需将它们设置在用户的时区是这样的:

$scope.datepickerOptions.minDate = new Date(dateFilter(minDate, 'yyyy-MM-dd\'T\'00:00:00', serverTimezone)); 
$scope.datepickerOptions.maxDate = new Date(dateFilter(maxDate, 'yyyy-MM-dd\'T\'00:00:00', serverTimezone)); 

的minDate和的maxDate是服务器本地化的日期和serverTimezone是服务器的时区偏移(“0500”例如)。

希望这会有所帮助!

0

希望下面的指令是对你有用

app.directive('datetimepickerNeutralTimezone', function() { 
    return { 
     restrict: 'A', 
     priority: 1, 
     require: 'ngModel', 
     link: function (scope, element, attrs, ctrl) { 
      ctrl.$formatters.push(function (value) { 
       if (typeof value === "undefined") { 
        var date = new Date(); 
        //date = new Date(date.getTime() + (60000 * date.getTimezoneOffset())); 
        return date; 
       } else { 
        var date = new Date(Date.parse(value)); 
        //date = new Date(date.getTime() + (60000 * date.getTimezoneOffset())); 
        return date; 
       } 
      }); 

      ctrl.$parsers.push(function (value) { 
       var date = new Date(value.getTime() - (60000 * value.getTimezoneOffset())); 
       return date; 
      }); 
     } 
    }; 
}); 

app.directive('timepickerNeutralTimezone', function() { 
    return { 
     restrict: 'A', 
     priority: 1, 
     require: 'ngModel', 
     link: function (scope, element, attrs, ctrl) { 
      ctrl.$formatters.push(function (value) { 
       if (typeof value === "undefined") { 
       } else { 
        var date = new Date(Date.parse(value)); 
        date = new Date(date.getTime() + (60000 * date.getTimezoneOffset())); 
        return date; 
       } 
      }); 

      ctrl.$parsers.push(function (value) { 
       var date = new Date(value.getTime() - (60000 * value.getTimezoneOffset())); 
       return date; 
      }); 
     } 
    }; 
}); 
25

解决方案在这里找到:https://github.com/angular-ui/bootstrap/issues/4837#issuecomment-203284205

的时区问题是固定的。

您可以使用:

ng-model-options="{timezone: 'utc'}"

为了得到一个datepicker没有时区计算。

编辑:此解决方案从版本2.x不起作用,但它直到那时才完全正常。我无法找到解决方法,仍在使用1.3.3版本。编辑2:正如SébastienDeprez在下面的评论中指出的那样,这已经在版本2.3.1中得到修复。我只是测试它,它的效果很好。

<input 
uib-datepicker-popup 
ng-model="$ctrl.myModel" 
ng-model-options="{timezone: 'utc'}"> 
+0

这是非常有帮助 - 谢谢! – Brendan

+0

我确认此解决方案有效,但不适用于较新版本。具体来说,它是版本> = 2.0.2和<= 2.3.0(至少)的bug。这很无聊。 –

+1

实际上,它会从2.3.1修复! https://github.com/angular-ui/bootstrap/issues/6235 –

-2

最好的解决方案是使用moment.js库修复浏览器时区和组件时区