Angular Настройка пользовательского интерфейса DatePicker для часового пояса
У меня есть дата, хранящаяся как дата в SQL Server. Дата показывает 4/24/2014, когда я запрашиваю в SQL. Это верно. Дата корректно переносится на клиентскую сторону в UTC. Чтобы изменить эту дату, мы используем Angular UI DatePicker. DatePicker корректирует эту дату на основе моего локального часового пояса и поэтому всегда отключается на один день.
Я вижу, что это происходит. Если бы мы редактировали DateTime вместо Date, тогда было бы правильно настроить часовой пояс. Однако в этом случае у меня просто есть дата, поэтому мне не нужен часовой пояс, и я просто хочу отредактировать дату, как это было в базе данных.
Я могу проверить, что он настраивается для часовой пояс. Если я изменю часовой пояс на моей машине с Windows, чтобы быть UTC, то DatePicker показывает правильную дату.
Итак, вопрос в том, есть ли способ сообщить DatePicker отключить настройки часового пояса и просто управлять датами в формате UTC, чтобы он работал с SQL Date вместо SQL Datetime?
Ответы
Ответ 1
У меня была очень похожая проблема некоторое время назад: я хотел хранить локальные даты на стороне сервера (т.е. просто yyyy-mm-dd и не иметь информацию о времени/времени), но так как Angular Bootstrap Datepicker использует дату JavaScript объекту это было невозможно (он сериализуется в строку времени UTC UTC в JSON, как вы сами узнали).
Я решил проблему с этой директивой: https://gist.github.com/weberste/354a3f0a9ea58e0ea0de
По существу, я переформатирую значение всякий раз, когда дата выбирается на datepicker (это значение, yyyy-mm-dd форматированная строка, будет храниться в модели) и всякий раз, когда к модели обращаются, чтобы заполнить представление, Мне нужно снова обернуть его в объект Date, поэтому datepicker обрабатывает его правильно.
Ответ 2
Решение найдено здесь: https://github.com/angular-ui/bootstrap/issues/4837#issuecomment-203284205
Исправлена проблема с часовым поясом.
Вы можете использовать:
ng-model-options="{timezone: 'utc'}"
Чтобы получить датупик без расчета часового пояса.
EDIT: это решение не работает с версии 2.x, однако до этого он отлично справился. Я не мог найти обходное решение и все еще использую версию 1.3.3.
EDIT 2: Как отметил Себастьян Депрез в комментариях ниже, это было исправлено в версии 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
Надежность ниже директивы полезна для вас
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;
});
}
};
});
Ответ 5
Для меня, потому что мы используем очень старую версию библиотеки, и с учетом объекта expiration_date, возвращаемого DatePicker, мне пришлось найти обходной путь и настроить его так:
expiration_date.setMinutes(-expiration_date.getTimezoneOffset());
Который установит запрашиваемую дату в соответствии с соответствующей датой UTC, но все еще будет отображаться в формате локального часового пояса.
Для меня это сработало хорошо. Надеюсь, это может кому-то помочь.
Ответ 6
лучшим решением является использование библиотеки time.js, исправляющей всю ошибку между часовым поясом браузера и часовым поясом компонента