时刻js Timepicker

时间:2015-09-16 20:56:36

标签: javascript angularjs angular-ui-bootstrap momentjs

我们正在尝试使用momentjs来获得令人敬畏的时区功能。我们也使用bootstrap ui的timepicker,它希望将datetime作为ng-model。现在,尝试将时刻转换为日期时间会丢失时区并切换回本地时区。我正在考虑构建我们自己的自定义时间戳,但首先我想检查一下其他人是否遇到过这个问题。提前谢谢!

(function () {
'use strict';
moment.tz.setDefault("America/Phoenix");
angular.module('timepickerPop', ['ui.bootstrap'])
.factory('timepickerState', function () {
    var pickers = [];
    return {
        addPicker: function (picker) {
            pickers.push(picker);
        },
        closeAll: function () {
            for (var i = 0; i < pickers.length; i++) {
                pickers[i].close();
            }
        }
    };
})
.filter('momentFilter', function () {
    return function (input) {
        if (input == undefined) return "";
        return input.format("hh:mm A");
    };
})
.directive("timeFormat", ['$filter', function ($filter) {
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            showMeridian: '=',
        },
        link: function (scope, element, attrs, ngModel) {

            var parseTime = function (viewValue) {

                //Not a concern at the moment
            };

            ngModel.$parsers.push(parseTime);

            var showTime = function (data) {
                parseTime(data);
                return $filter('momentFilter')(data);
            };

            ngModel.$formatters.push(showTime);

            scope.$watch('showMeridian', function (value) {
                var myTime = ngModel.$modelValue;
                if (myTime) {
                    element.val(showTime(myTime));
                }

            });
        }
    };
}])

.directive('timepickerPop', ['$document', 'timepickerState', function ($document, timepickerState) {
    return {
        restrict: 'E',
        transclude: false,
        scope: {
            inputTime: "=",
            showMeridian: "=",
            disabled: "="
        },
        controller: ['$scope', '$element', function ($scope, $element) {
            $scope.isOpen = false;

            $scope.disabledInt = angular.isUndefined($scope.disabled) ? false : $scope.disabled;

            $scope.toggle = function () {
                if ($scope.isOpen) {
                    $scope.close();
                } else {
                    $scope.open();
                }
            };
        }],
        link: function (scope, element, attrs) {
            var picker = {
                open: function () {
                    timepickerState.closeAll();
                    scope.isOpen = true;
                },
                close: function () {
                    scope.isOpen = false;
                }

            }
            timepickerState.addPicker(picker);

            scope.open = picker.open;
            scope.close = picker.close;

            scope.$watch("disabled", function (value) {
                scope.disabledInt = angular.isUndefined(scope.disabled) ? false : scope.disabled;
            });

            scope.$watch("inputTime", function (value) {
                if (!scope.inputTime) {
                    element.addClass('has-error');
                } else {
                    element.removeClass('has-error');
                }

            });

            element.bind('click', function (event) {
                event.preventDefault();
                event.stopPropagation();
            });

            $document.bind('click', function (event) {
                scope.$apply(function () {
                    scope.isOpen = false;
                });
            });
        },
        template: "<input type='text' class='form-control' ng-model='inputTime' ng-disabled='disabledInt' time-format show-meridian='showMeridian' ng-focus='open()' />"
            + "  <div class='input-group-btn' ng-class='{open:isOpen}'> "
            + "    <button type='button' ng-disabled='disabledInt' class='btn btn-default ' ng-class=\"{'btn-primary':isOpen}\" data-toggle='dropdown' ng-click='toggle()'> "
            + "        <i class='glyphicon glyphicon-time'></i></button> "
            + "          <div class='dropdown-menu pull-right'> "
            + "            <timepicker ng-model='inputTime' show-meridian='showMeridian'></timepicker> "
            + "           </div> " + "  </div>"
    };
}]);

}());

1 个答案:

答案 0 :(得分:1)

我过去所做的事情(受bootstrap ui日期选择器的启发)是在同一元素上使用另一个指令,其中包含一个解析器/格式化程序组合。

它的作用是基本上将引导提示器的日期从moment对象转换为Date对象,从Date转换回moment模型。

这是datepicker的实现:

.directive('uiDateMoment', [function () {
    var directive = {
        require: 'ngModel',
        link: function (scope, element, attrs, modelCtrl) {
            modelCtrl.$formatters.length = 0;
            modelCtrl.$formatters.push(function (value) {
                if (moment.isMoment(value)) {
                    var zoneDiffInMinutes = value.zone();
                    var date = value.toDate();
                    var tzDate = new Date(date.getTime() + (date.getTimezoneOffset() * 60000) - (zoneDiffInMinutes * 60000));
                    return tzDate;
                }
                return null;
            });
            modelCtrl.$parsers.push(function (value) {
                if (value) {
                    var isoDate = moment(value).format('YYYY-MM-DD');
                    return moment(isoDate + ' ' + (timeZoneOffset)).zone(timeZoneOffset);
                }
                return null;
            });
        }
    };
    return directive;
}]);

在我的情况下,timeZoneOffset是一个全局变量 - 这不是理想的,但您可以将其移动到服务或其他东西。

它的使用方式如下:

<input type="text" ng-model="TargetDate" ui-date="UIDateSettings" ui-date-moment="mm/dd/yy" />

你当然可以将其改编为时间戳。