Angular Strap Datepicker:返回的时间戳不一致,UTC + 0 vs UTC +12小时

时间:2014-10-01 09:57:25

标签: javascript angularjs datepicker timestamp angular-strap

情况:

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

问题:

  • 有些电脑会在0:00返回,有些电脑在12:00。

我尝试了什么:

  • 调试时我发现问题出现在angular-strap/dist/modules/datepicker.js#L379的第379行,控制器。$ dateValue返回' Sat Mar 28 1987 12:00:00 GMT + 0100(W. Europe Standard Time )'代替1987年3月28日星期六00:00:00 GMT + 0100(欧洲标准时间)',其他计算机返回的值。

问题:

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

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

我也遇到了类似日期选择的类似问题...我使用ng-model的$解析器解决了它。

    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点,那么这也很容易实现......

    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>

答案 2 :(得分:0)

除了修复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;
};