From eef4c3b48bcb4feac028bf640b545006dd0c9b91 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Thu, 18 Oct 2018 13:48:36 +0000 Subject: [PATCH] [FIX] calendar: all day event shouldn't store in UTC With a user in a distant timezone, like UTC +/- 11 Create a all day event. Before this commit, the event was displayed across the wrong days This was because the dates were converted from the user's timezone into UTC before being stored. Which is: - start date at december, 12 - if the user's tz is utc-11: the date becomes december, 11 (at 1:00pm) - at rendering, it becomes december, 11 (at 7:00am) After this commit, we store the datetime field "as if" it were a date field that is, we don't convert it to any particular tz It is worth noting that, if one removes the allday mapping in the xml view, an event that has been created as allday will get its start and stop date converted to the browser's timezone, and will NOT be displayed as from 8am to 8pm as one could expect This is considered as a limitation of the code, that was present before this commit anyway. In any case, please do not revert this commit :D OPW 1891110 closes odoo/odoo#27949 --- addons/calendar/models/calendar.py | 12 ++++++------ addons/calendar/tests/test_calendar.py | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 25377659563..8ec5dcb195c 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -890,18 +890,18 @@ class Meeting(models.Model): def _inverse_dates(self): for meeting in self: if meeting.allday: - tz = pytz.timezone(self.env.user.tz) if self.env.user.tz else pytz.utc + # Convention break: + # stop and start are NOT in UTC in allday event + # in this case, they actually represent a date + # i.e. Christmas is on 25/12 for everyone + # even if people don't celebrate it simultaneously enddate = fields.Datetime.from_string(meeting.stop_date) - enddate = tz.localize(enddate) enddate = enddate.replace(hour=18) - enddate = enddate.astimezone(pytz.utc) meeting.stop = fields.Datetime.to_string(enddate) startdate = fields.Datetime.from_string(meeting.start_date) - startdate = tz.localize(startdate) # Add "+hh:mm" timezone - startdate = startdate.replace(hour=8) # Set 8 AM in localtime - startdate = startdate.astimezone(pytz.utc) # Convert to UTC + startdate = startdate.replace(hour=8) # Set 8 AM meeting.start = fields.Datetime.to_string(startdate) else: meeting.write({'start': meeting.start_datetime, diff --git a/addons/calendar/tests/test_calendar.py b/addons/calendar/tests/test_calendar.py index 12547c8f695..e04866f1f68 100644 --- a/addons/calendar/tests/test_calendar.py +++ b/addons/calendar/tests/test_calendar.py @@ -275,3 +275,20 @@ class TestCalendar(TransactionCase): self.assertEqual(test_event.res_model, test_record._name) self.assertEqual(test_event.res_id, test_record.id) self.assertEqual(len(test_record.activity_ids), 1) + + def test_event_allday(self): + self.env.user.tz = 'Pacific/Honolulu' + + event = self.CalendarEvent.create({ + 'name': 'All Day', + 'start': "2018-10-16 00:00:00", + 'start_date': "2018-10-16", + 'start_datetime': False, + 'stop': "2018-10-18 00:00:00", + 'stop_date': "2018-10-18", + 'stop_datetime': False, + 'allday': True, + }) + + self.assertEqual(event.start, '2018-10-16 08:00:00') + self.assertEqual(event.stop, '2018-10-18 18:00:00')