Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fullcalendar wrong time in on click event

I'm using angular and fullcalendar. I have (surprise) timezone-issues, and I can't seem to get it right.

If in the weekview I click on 08.00 hours, I open a modal and show the time, I see 09.00 hours.

timezone: "Europe/Brussels",
ignoreTimezone: false,

This is (atm) a +0100 timezone, and during summer a +0200 timezone

The click-event:

dayClick: function (date, jsEvent, view) {

    $scope.newEventDate = date;

    var modalInstance = $modal.open({
        templateUrl: 'newRosterEvent',
        controller: 'NewEventModalController',
        backdrop: "true",
        resolve: {
            event: function () {
                       return $scope.newEventDate;
                   },
            stage: function () {
                       return $scope.stage;
                   }
            }
       });

To display the time:

stagewebApp.controller('NewEventModalController', ["$scope", "$modalInstance","$filter", "event", "stage", function ($scope, $modalInstance, $filter,event, stage) {

    $scope.stage = stage;

    $scope.day = new Date($filter('date')(event._d, "yyyy-MM-dd"));

    $scope.start = event.toDate();

    ....more code....
}

In this case $scope.start displays the clicked time +1

So it seems that fullcalendar takes the time I clicked and converts it to the timezone selected, but I would expect it to interpret the clicked time as being in the timezone I selected.

Apparently I am tackling this wrong, so what is the correct way to do this? ( $scope.start should show the time I clicked (preferably in my timezone)). Afterwards I send it to the server where it is stored as UTC.

like image 714
Kevin Avatar asked Mar 03 '15 16:03

Kevin


1 Answers

The current version of FullCalendar uses moment.js extensively. The problems you are describing are from improper use of moment objects. Specifically:

$scope.start = event.toDate();

When you call toDate, you get back a regular JavaScript Date object - which will be based on the same UTC instant, but will always take on the behavior of the time zone where the code is running. You have a few options:

  • You can keep it as a moment object:

    $scope.start = event;
    
  • You can format it to an ISO string that retains the time zone offset:

    $scope.start = event.format(); // ex: '2015-03-04T08:00:00+01:00'
    

With either option, you'll need to follow through with the usage of $scope.start to expect either a moment or a string, rather than a Date.

Also, in this code:

$scope.day = new Date($filter('date')(event._d, "yyyy-MM-dd"));

You should never access the _d property directly, as there can be unintended side-effects. Consider the underscore to mean "internal". Also, you don't need Angular's date filter here since moment objects have formatting capabilities. Instead, just do this:

$scope.day = event.format("YYYY-MM-DD");
like image 59
Matt Johnson-Pint Avatar answered Sep 25 '22 16:09

Matt Johnson-Pint