Javascript не конвертирует angular дату datepicker ui в UTC правильно

Я использую angular ui datepicker в своем проекте (asp.net web api + angularjs). Все работает нормально, но когда я пытаюсь сохранить дату на Db, он не конвертирует его в формат UTC правильно и подстраивает 1 день (фактически несколько часов, но это влияет и на день).

Например, когда я выбираю 01/11/2014 в datepicker:

Angularjs object:
Sat Nov 01 2014 00:00:00 GMT+0200 (FLE Standard Time)

In request: 
2014-10-31T22:00:00.000Z

In asp.net api controller:
{31-Oct-14 10:00:00 PM}

Контроллер даты:

app.controller('DatepickerCtrl', function ($scope) {
    $scope.today = function () {
        $scope.dt = new Date();
    };
    $scope.today();
    $scope.clear = function () {
        $scope.dt = null;
    };
    $scope.open = function ($event) {
        $event.preventDefault();
        $event.stopPropagation();

        $scope.opened = true;
    };
    $scope.format = 'dd/MM/yyyy';
    $scope.dateOptions = {
        'starting-day': 1
    };
});

HNML:

<div class="form-group inputGroupContainer" ng-controller="DatepickerCtrl">
                    <label for="date">Date of Birth</label>
                    <p class="input-group">
                        <input type="text" name="date1" ui-date="{dateFormat: 'yy-mm-dd'}" ui-date-format="yy-mm-dd" placeholder="DD/MM/YYYY" class="form-control" datepicker-popup="{{format}}" ng-model="user.Personal.BirthDate" max-date="currentDate" is-open="opened" close-text="Close" />
                        <span class="input-group-btn">
                            <button type="button"   class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
                        </span>
                    </p>
                </div>

Но похоже, что angular datepicker выделяет правильную дату:

enter image description here

Я попытался вручную преобразовать дату в формат UTC, но безуспешно.

   toUTCDate: function (d) {
            var date = new Date(d);
            var _utc = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());//, date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()
            return _utc;
        }

Должен ли я указать часовой пояс или использовать фильтр angular js? Буду признателен за любую помощь!

Ответы

Ответ 1

У меня была одна и та же проблема, решение заключалось в том, чтобы удалить компонент часовой пояс части даты. Чтобы решить проблему более общим образом, я написал директиву

csapp.directive("csDateToIso", 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
    };
});

выше директива удаляет часть часового пояса и учитывает только дату в формате ввода даты ISO.

Я использую moment.js для манипуляций с датами. Но вы можете легко преобразовать выше, чтобы не использовать moment.js

ИЗМЕНИТЬ

используйте его как ниже

  <input ng-model='abc' cs-date-to-iso ui-datepicker>

Ответ 2

Просто добавьте версию ответа Entre coffeescript, которая работает для меня в "angular": "~1.3.14",:

app.directive 'dateToIso', [ () ->

  restrict: 'A',
  require: 'ngModel'

  link: (scope, el, attrs, ngModel) ->
    if (angular.isUndefined(attrs.ngModel))
      console.log 'ngModel attribute missing for date-to-iso'
    else
      ngModel.$parsers.push (datePickerValue) ->
        return moment(datePickerValue).format("YYYY-MM-DD")
]

Ответ 3

Не отправляйте объект javascript в json-запрос, javascript добавляет часовой пояс браузеров в строковое представление объекта, который используется в JSON. Вы можете использовать что-то вроде этого, чтобы извлечь дату в строку без часового пояса:

myApp.service('dateService', function(){
    this.parse = function(date) {
        if(!date){
            return ""
        }
        var day = (date.getDate() < 10 ? '0' : '') + date.getDate();
        var month = ((date.getMonth() + 1) < 10 ? '0' : '') + (date.getMonth() + 1);
        var hours = (date.getHours() < 10 ? '0' : '') + date.getHours();
        var minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
        var seconds = (date.getSeconds() < 10 ? '0' : '') + date.getSeconds();
        return date.getFullYear() + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds
    }
});

Затем в вашем бэкэнд вам нужно только проанализировать строку в объект даты, используя формат "yyyy-MM-dd HH: mm: ss" в выбранном вами часовом поясе. Я не знаю о .NET, но в java вы можете сделать что-то вроде этого:

def jsCalendarFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
jsCalendarFormat.setTimeZone(user.timezone)
Date dateObj = jsCalendarFormat.parse(date)