我们正在尝试使用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>"
};
}]);
}());
答案 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" />
你当然可以将其改编为时间戳。