【问题标题】:Angular UI DatePicker adjusting for timezoneAngular UI DatePicker 调整时区
【发布时间】:2014-05-02 15:55:55
【问题描述】:

我有一个日期存储为 SQL Server 中的日期。当我在 SQL 中查询时,日期显示为 2014 年 4 月 24 日。那是正确的。日期以 UTC 正确地传递给客户端。要编辑该日期,我们使用 Angular UI DatePicker。 DatePicker 正在根据我的本地时区调整该日期,因此它总是关闭一天。

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

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

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

【问题讨论】:

    标签: angularjs datepicker timezone angular-ui


    【解决方案1】:

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

    我用这个指令解决了这个问题:https://gist.github.com/weberste/354a3f0a9ea58e0ea0de

    本质上,每当在日期选择器上选择日期(此值是 yyyy-mm-dd 格式的字符串,将存储在模型上)以及访问模型以填充视图时,我都会重新格式化该值,我需要再次将它包装在 Date 对象中,以便 datepicker 正确处理它。

    【讨论】:

    • 它有点工作。但是当您第一次使用来自服务器的 yyyy-mm-dd 字符串设置它时,datepicker 会调整时区。你怎么能防止它?这里有一张票:issue 2072
    • 好点,感谢您指出这一点——我相信这是落后于 UTC 的时区的一个问题。已更新 Gist 通过“撤消”由 JavaScript 日期引入的时区调整来解决此问题。
    • 这个解决方案很好用,谢谢分享。
    • 谢谢,您为我节省了大量时间!
    • 您的指令帮助我使用 SQL 服务器格式化 Angular Material Datepickers。谢谢。
    【解决方案2】:

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

    时区问题已修复。

    你可以使用:

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

    获取不计算时区的日期选择器。

    编辑:此解决方案自 2.x 版以来不起作用,但在那之前它做得非常好。我找不到解决方法,但仍在使用 1.3.3 版。

    编辑 2:正如 Sébastien Deprez 在下面的 cmets 中指出的那样,这已在 2.3.1 版中修复。我刚刚测试过,效果很好。

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

    【讨论】:

    【解决方案3】:

    首先我想指出,引导程序的本地化日期选择器既愚蠢又无用,没有人需要这样的东西,你真正想要的只是一个日期 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”)。

    希望这会有所帮助!

    【讨论】:

      【解决方案4】:

      将时区设置为 null 对我来说就像是一种魅力。它只是保持选定的日期不变。

      ng-model-options="{timezone: null}"
      

      注意:已在所有时区测试,我使用的 uib 版本是 1.3.3

      【讨论】:

        【解决方案5】:

        希望下面的指令对你有用

        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;
                    });
                }
            };
        });
        

        【讨论】:

          【解决方案6】:

          对我来说,因为我们使用了一个非常旧版本的库,并且给定一个由日期选择器返回的对象 expiration_date,我必须找到一种解决方法并像这样对其进行调整:

          expiration_date.setMinutes(-expiration_date.getTimezoneOffset());
          

          这会将请求的日期设置为其对应的 UTC 日期,但仍以本地时区格式表示。

          对我来说效果很好。希望它可以帮助某人。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-03-21
            • 1970-01-01
            • 2021-07-30
            • 2016-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多