【问题标题】:Angular Strap Datepicker: Inconsistent timestamps returned, UTC +0 vs UTC +12 hoursAngular Strap Datepicker:返回的时间戳不一致,UTC +0 vs UTC +12 小时
【发布时间】:2014-10-01 09:57:25
【问题描述】:

情况:

  • 我们正在使用 Angular-Strap 的 datepicker 并希望将 UTC 时间戳返回到服务器。
  • 在选择日期(未选择时间)时,我们发现有些计算机返回的时间戳记为 0:00,有些则返回时间为 12:00。
  • 这与浏览器无关,但在计算机之间有所不同。

问题:

  • 有些计算机返回 0:00,有些返回 12:00。

我尝试了什么:

  • 调试时我发现问题出现在angular-strap/dist/modules/datepicker.js#L379 的第 379 行,controller.$dateValue 返回 'Sat Mar 28 1987 12:00:00 GMT+0100 (W. Europe Standard Time)' 而不是 ' Sat Mar 28 1987 00:00:00 GMT+0100 (W. Europe Standard Time)',由其他计算机返回的值。

问题:

  • 如何在所有情况下返回 0:00 时间?

【问题讨论】:

    标签: javascript angularjs datepicker timestamp angular-strap


    【解决方案1】:

    我也遇到了同样的问题。我所做的是编写了一个指令来转换日期 utc 日期。检查代码示例。这解决了我的问题。

    (function (angular) {
    angular.module('myApp').directive('datePicker', ['$parse', 'dateFilter', function           ($parse, dateFilter) {
        var inputDateFormat = 'dd/MM/yyyy';
    
        var utcDateGeneretor = function (dateString) {
            if ('undefined' === typeof dateString || '' === dateString) {
                return null;
            }
    
            var parts = dateString.split('/');
            if (3 !== parts.length) {
                return null;
            }
            var year = parseInt(parts[2], 10);
            var month = parseInt(parts[1], 10);
            var day = parseInt(parts[0], 10);
            if (year.toString().length < 4) {
                return null;
            }
    
            if (month < 0 || year < 0 || day < 1) {
                return null;
            }
    
            //Javascript month is zero based. thats why always reduce 1 form selected month.
            return new Date(Date.UTC(year, (month - 1), day));
        };
    
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ctrls) {
    
                var mindatecalvalue = parseInt(attrs["mindatecalvalue"], 10);
                var maxdatecalvalue = parseInt(attrs["maxdatecalvalue"], 10);
                var twoDigitCutoffSpecified = attrs["twoDigitCutoff"];
                var twoDigitYear1900cutoff = -1;  //If a 2-digityear is less than this number it is treated as being 2000+, otherwise 1900+.
                if (twoDigitCutoffSpecified) {
                    twoDigitYear1900cutoff = parseInt(attrs["twoDigitCutoff"], 10);
                    if (isNaN(twoDigitYear1900cutoff)) {
                        twoDigitYear1900cutoff = -1;
                    } else if (twoDigitYear1900cutoff <= 0) {
                        twoDigitYear1900cutoff += (new Date().getFullYear() - 2000); //A negative number is interpreted as a number of years before the current year.
                    }
                }
    
                var updateModel = function (dateText) {
    
                    var canonicalisedDateText = ensureFullYear(dateText, twoDigitYear1900cutoff);
    
                    // call $apply to bring stuff to angular model
                    scope.$apply(function () {
                        ctrls.$setViewValue(canonicalisedDateText);
                    });
                    ctrls.$render();
                };
    
                var ensureFullYear = function (dateText, twoDigitYear1900cutoff) {
                    var findYearRegex = /(.+[^0-9])([0-9]+)\s*$/;
                    var dateParts = findYearRegex.exec(dateText);
                    if ((!dateParts) || (dateParts.length != 3)) {
                        return dateText; //can't find a year in this date.
                    }
                    var originalYearAsStr = dateParts[2];
                    if (originalYearAsStr.length > 2) {
                        return dateText; //Not a 2-digit year.
                    }
                    var originalYear = parseInt(originalYearAsStr, 10);
                    var fullYear = 0;
                    if (originalYear <= twoDigitYear1900cutoff) {
                        fullYear = 2000 + originalYear;
                    } else {
                        fullYear = 1900 + originalYear;
                    }
                    var restOfDate = dateParts[1];
                    return restOfDate + fullYear;
                }
    
    
                ctrls.$formatters.push(function (modelValue) {
                    return dateFilter(modelValue, inputDateFormat);
                });
    
                ctrls.$parsers.push(function (dateString) {
                    return utcDateGeneretor(dateString);
                });
            }
        };
    }]);
    
    })(angular);
    

    【讨论】:

      【解决方案2】:

      我也遇到过关于仅日期选择的类似问题...我使用 ng-model 的 $parsers 解决了它。

          ngModelCtrl.$parsers.push(function (datepickerValue) {
              return moment(datepickerValue).format("YYYY-MM-DD");
          });
      

      我正在使用 moment.js 进行日期处理。但即使没有moment.js,上述解决方案也可以工作, 如下所示。 (注意:我没有测试下面的代码,所以你可能需要稍微调整一下)

          ngModelCtrl.$parsers.push(function (datepickerValue) {
              //return new Date(datepickerValue).toISOString().substring(0,10);
              return new Date(datepickerValue).format("YYYY-MM-DD");
          });
      

      上面会给你没有时间戳的日期。但是如果你的要求说最后总是需要0:00,那也可以很容易地实现...

          ngModelCtrl.$parsers.push(function (datepickerValue) {
              return moment(datepickerValue).format("YYYY-MM-DD") + " 0:00";
          });
      

      我用于此的完整指令代码是:

      shared.directive("dateToIso", function () {
      
          var linkFunction = function (scope, element, attrs, ngModelCtrl) {
      
              ngModelCtrl.$parsers.push(function (datepickerValue) {
                  return moment(datepickerValue).format("YYYY-MM-DD");
              });
          };
      
          return {
              restrict: "A",
              require: "ngModel",
              link: linkFunction
          };
      });
      

      我已将它定义为一个属性,以便您可以将它与您拥有的其他指令一起使用。你可以像下面这样使用它......

                <input type="text" ng-model="myDate" name="date" bs-datepicker date-to-iso>
      

      【讨论】:

      • 这个答案对你有帮助吗??
      【解决方案3】:

      除了修复本地 AngularStrap 副本中的错误之外,您还可以创建一个指令来包装 DatePicker 指令。我从 angular-strap 中取出 plunker 并编写了一个装饰器指令,以在所有情况下始终返回 0:00 时间。这很好,因为您可以在指令中编写所需的所有自定义逻辑。注意 - 该指令在模型上创建一个监视,然后执行更新后所需的任何修改,并通过回调将其返回到应用程序的控制器。注意:为了方便使用,我也切换到了 moment.js。

      Plunker

      HTML:

      <date-wrapper></date-wrapper>
      

      指令:

      app.directive('dateWrapper', function($compile) {
        return {
            restrict:'AE',
            link:function(scope, element, attrs, ctrl) {
      
                var html = '<input type="text" class="form-control" name="date" ng-model="selectedDate" bs-datepicker>';
      
                var e = $compile(html)(scope);
                element.replaceWith(e);
      
                scope.$watch('selectedDate', function(date) {        
                    var updatedDate = moment.utc(date).hour(0).minute(0).second(0).format("YYYY-MM-DDTHH:mm:ss Z");
      
                    scope.dateChanged(updatedDate);
                });
            }
        }
      });
      

      应用控制器示例:

      // call back for updated date
      $scope.dateChanged = function(date) {
          $scope.selectedZeroHourUtcDate = date;
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-16
        • 1970-01-01
        • 2017-09-27
        • 2011-06-16
        • 1970-01-01
        • 1970-01-01
        • 2019-05-02
        相关资源
        最近更新 更多