Reputation: 770
I'm using angular ui datepicker in my project(asp.net web api + angularjs). All works fine but when I'm trying to save date to Db it doesn't convert it to UTC format correctly and substructs 1 day(actually a few hours but it affects for a day too).
For example when I choose 01/11/2014 in the 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}
Datepicker controller:
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>
But seems like angular datepicker highlight the correct date:
I've tried to manually convert date to UTC format but unsuccessfully as well
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;
}
Should I specify timezone or use angular js filter?
Upvotes: 15
Views: 13540
Reputation: 10244
Just to add the coffeescript version of Entre's answer, which works for me in "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")
]
Upvotes: 3
Reputation: 18055
I have had the exact same problem, the solution was to remove the timezone component of the date part. To solve the problem in a more generic way I had written a directive
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
};
});
above directive removes the timezone part and only considers the date part of the ISO date format input.
I do use moment.js for date manipulations. But you can easily convert above to not use moment.js
EDIT
use it like below
<input ng-model='abc' cs-date-to-iso ui-datepicker>
Upvotes: 19
Reputation: 1465
Don't send the javascript object in the json request, javascript add the browsers timezone in the string representation of the object that is used in the JSON. You can use something like this to extract the date into an string without the timezone:
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
}
});
Then in your backend you only have to parse the string into a date object using the format "yyyy-MM-dd HH:mm:ss" in the timezone of your choosing. I don't know about .NET but in java you can do something like this:
def jsCalendarFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
jsCalendarFormat.setTimeZone(user.timezone)
Date dateObj = jsCalendarFormat.parse(date)
Upvotes: 2