diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 3a1fc072b76..53eb5e867ea 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -1754,7 +1754,15 @@ class Meeting(models.Model): if values.get('description'): activity_values['note'] = values['description'] if values.get('start'): - activity_values['date_deadline'] = fields.Datetime.from_string(values['start']).date() + # self.start is a datetime UTC *only when the event is not allday* + # activty.date_deadline is a date (No TZ, but should represent the day in which the user's TZ is) + # See 72254129dbaeae58d0a2055cba4e4a82cde495b7 for the same issue, but elsewhere + deadline = fields.Datetime.from_string(values['start']) + user_tz = self.env.context.get('tz') + if user_tz and not self.allday: + deadline = pytz.UTC.localize(deadline) + deadline = deadline.astimezone(pytz.timezone(user_tz)) + activity_values['date_deadline'] = deadline.date() if values.get('user_id'): activity_values['user_id'] = values['user_id'] if activity_values.keys(): diff --git a/addons/calendar/tests/test_calendar.py b/addons/calendar/tests/test_calendar.py index b764a4a9463..f3dcb3e0b50 100644 --- a/addons/calendar/tests/test_calendar.py +++ b/addons/calendar/tests/test_calendar.py @@ -314,3 +314,73 @@ class TestCalendar(TransactionCase): else: self.assertEqual(d.hour, 15) self.assertEqual(d.minute, 30) + + def test_event_activity_timezone(self): + activty_type = self.env['mail.activity.type'].create({ + 'name': 'Meeting', + 'category': 'meeting' + }) + + activity_id = self.env['mail.activity'].create({ + 'summary': 'Meeting with partner', + 'activity_type_id': activty_type.id, + 'res_model_id': self.env['ir.model'].search([('model', '=', 'res.partner')], limit=1).id, + 'res_id': self.env['res.partner'].search([('name', 'ilike', 'Agrolait')], limit=1).id, + }) + + calendar_event = self.env['calendar.event'].create({ + 'name': 'Meeting with partner', + 'activity_ids': [(6, False, activity_id.ids)], + 'start': '2018-11-12 21:00:00', + 'stop': '2018-11-13 00:00:00', + }) + + # Check output in UTC + self.assertEqual(activity_id.date_deadline, '2018-11-12') + + # Check output in the user's tz + # write on the event to trigger sync of activities + calendar_event.with_context({'tz': 'Australia/Brisbane'}).write({ + 'start': '2018-11-12 21:00:00', + }) + + self.assertEqual(activity_id.date_deadline, '2018-11-13') + + def test_event_allday_activity_timezone(self): + # Covers use case of commit eef4c3b48bcb4feac028bf640b545006dd0c9b91 + # Also, read the comment in the code at calendar.event._inverse_dates + activty_type = self.env['mail.activity.type'].create({ + 'name': 'Meeting', + 'category': 'meeting' + }) + + activity_id = self.env['mail.activity'].create({ + 'summary': 'Meeting with partner', + 'activity_type_id': activty_type.id, + 'res_model_id': self.env['ir.model'].search([('model', '=', 'res.partner')], limit=1).id, + 'res_id': self.env['res.partner'].search([('name', 'ilike', 'Agrolait')], limit=1).id, + }) + + calendar_event = self.env['calendar.event'].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, + 'activity_ids': [(6, False, activity_id.ids)], + }) + + # Check output in UTC + self.assertEqual(activity_id.date_deadline, '2018-10-16') + + # Check output in the user's tz + # write on the event to trigger sync of activities + calendar_event.with_context({'tz': 'Pacific/Honolulu'}).write({ + 'start': '2018-10-16 00:00:00', + 'start_date': '2018-10-16', + }) + + self.assertEqual(activity_id.date_deadline, '2018-10-16')