From 7680635c541502dcf207378a8ffe2f444e82878d Mon Sep 17 00:00:00 2001
From: Nicolas Lempereur <nle@odoo.com>
Date: Wed, 11 Apr 2018 14:58:25 +0200
Subject: [PATCH] [FIX] web: setDate mixing utc+tz and local date

In the calendar view there is some mixing of moment with:

- a local date with given timezone
- a UTC date with added timezone manually applied

The setDate function of calendar model sometimes received either of the
two types, and always transforms them to UTC date with added timezone.

This cause eg. the following issues:

- in the minicalendar, if we click on a day (eg. 12) the day highlighed
  will be the one of 12th at midnight with timezone applied. So with a
  negative timezone the 11th would be highlighted in the mini calendar
  (but the 12th would still be the day shown).

- if we change scale (week/day/month) or open calendar or use next or
  previous button: we call `setDate` with a UTC+timezone moment. So each
  time this is done, we get an additional timezone

  eg. when opening the calendar view on the 12th at 5:00 with GMT-0200:
      -> the target date is 12th at 1:00
      -> if we set the day mode: target date is 11th at 23:00
      -> if we set the week mode: target date is 11th at 21:00

With this change we keep target_date and highlight_date as local date so
setDate always receives a local date and jquery-ui DatePicker gets the
date in the expected format.

opw-1831368
closes #24188
---
 .../src/js/views/calendar/calendar_model.js   |  5 ++-
 .../web/static/tests/views/calendar_tests.js  | 35 +++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index 9c18e3065828..e8e2b245369f 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -253,7 +253,10 @@ return AbstractModel.extend({
      * @param {Moment} start
      */
     setDate: function (start) {
-        this.data.start_date = this.data.end_date = this.data.target_date = this.data.highlight_date = start;
+        // keep highlight/target_date in localtime
+        this.data.highlight_date = this.data.target_date = start.clone();
+        // set dates in UTC with timezone applied manually
+        this.data.start_date = this.data.end_date = start;
         this.data.start_date.utc().add(this.getSession().getTZOffset(this.data.start_date), 'minutes');
 
         switch (this.data.scale) {
diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js
index a24826709f03..198fd8a9d997 100644
--- a/addons/web/static/tests/views/calendar_tests.js
+++ b/addons/web/static/tests/views/calendar_tests.js
@@ -1715,6 +1715,41 @@ QUnit.module('Views', {
 
         testUtils.unpatch(mixins.ParentedMixin);
     });
+
+    QUnit.test('timezone does not affect current day', function (assert) {
+        assert.expect(2);
+
+        var calendar = createView({
+            View: CalendarView,
+            model: 'event',
+            data: this.data,
+            arch:
+            '<calendar date_start="start_date">'+
+                    '<field name="name"/>'+
+            '</calendar>',
+            archs: archs,
+            viewOptions: {
+                initialDate: initialDate,
+            },
+            session: {
+                getTZOffset: function () {
+                    return -2400; // 40 hours timezone
+                },
+            },
+
+        });
+
+        var $sidebar = calendar.$('.o_calendar_sidebar');
+
+        assert.strictEqual($sidebar.find('.ui-datepicker-current-day').text(), "12", "should highlight the target day");
+
+        // go to previous day
+        $sidebar.find('.ui-datepicker-current-day').prev().click();
+
+        assert.strictEqual($sidebar.find('.ui-datepicker-current-day').text(), "11", "should highlight the selected day");
+
+        calendar.destroy();
+    });
 });
 
 });
-- 
GitLab