From 28e1686bc5c862802162606527a190e344014591 Mon Sep 17 00:00:00 2001 From: jpr-odoo Date: Thu, 24 Jan 2019 07:06:04 +0000 Subject: [PATCH] [FIX] calendar: add timezone info to avoid DST issue on recurrent events As original timezone is not taken into account when computing recurrent event time of a given recurrency change depending on the DST. This commit fixes that behavior by correctly storing the event timezone and using it when computing recurrency datetimes. Related to task 30388 closes odoo/odoo#32950 Signed-off-by: Thibault Delavallee (tde) --- addons/calendar/models/calendar.py | 10 ++++++++-- addons/calendar/views/calendar_views.xml | 1 + addons/hr_holidays/models/hr_leave.py | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index 981fef73c3b..2febffdf578 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -17,6 +17,7 @@ import uuid from odoo import api, fields, models from odoo import tools +from odoo.addons.base.models.res_partner import _tz_get from odoo.osv import expression from odoo.tools.translate import _ from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, pycompat @@ -599,7 +600,7 @@ class Meeting(models.Model): else: reference_date = self.start - timezone = pytz.timezone(self._context.get('tz') or 'UTC') + timezone = pytz.timezone(self.event_tz) if self.event_tz else pytz.timezone(self._context.get('tz') or 'UTC') event_date = pytz.UTC.localize(fields.Datetime.from_string(reference_date)) # Add "+hh:mm" timezone if not event_date: event_date = datetime.datetime.now() @@ -637,7 +638,7 @@ class Meeting(models.Model): invalidate = True def naive_tz_to_utc(d): - return timezone.localize(d).astimezone(pytz.UTC) + return timezone.localize(d.replace(tzinfo=None), is_dst=True).astimezone(pytz.UTC) return [naive_tz_to_utc(d) if not use_naive_datetime else d for d in rset1 if d.year < MAXYEAR] @api.multi @@ -780,6 +781,7 @@ class Meeting(models.Model): start_datetime = fields.Datetime('Start DateTime', compute='_compute_dates', inverse='_inverse_dates', store=True, states={'done': [('readonly', True)]}, tracking=True) stop_date = fields.Date('End Date', compute='_compute_dates', inverse='_inverse_dates', store=True, states={'done': [('readonly', True)]}, tracking=True) stop_datetime = fields.Datetime('End Datetime', compute='_compute_dates', inverse='_inverse_dates', store=True, states={'done': [('readonly', True)]}, tracking=True) # old date_deadline + event_tz = fields.Selection('_event_tz_get', string='Timezone', default=lambda self: self.env.context.get('tz') or self.user_id.tz) duration = fields.Float('Duration', states={'done': [('readonly', True)]}) description = fields.Text('Description', states={'done': [('readonly', True)]}) privacy = fields.Selection([('public', 'Everyone'), ('private', 'Only me'), ('confidential', 'Only internal users')], 'Privacy', default='public', states={'done': [('readonly', True)]}, oldname="class") @@ -935,6 +937,10 @@ class Meeting(models.Model): data.update(self._rrule_parse(meeting.rrule, data, meeting.start)) meeting.update(data) + @api.model + def _event_tz_get(self): + return _tz_get(self) + @api.constrains('start_datetime', 'stop_datetime', 'start_date', 'stop_date') def _check_closing_date(self): for meeting in self: diff --git a/addons/calendar/views/calendar_views.xml b/addons/calendar/views/calendar_views.xml index 76be748d098..9a69e99410b 100644 --- a/addons/calendar/views/calendar_views.xml +++ b/addons/calendar/views/calendar_views.xml @@ -139,6 +139,7 @@ {'no_create_edit': True}"/> + diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 34afa16eb5d..443d01f4729 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -618,7 +618,8 @@ class HolidaysRequest(models.Model): 'stop': self.date_to, 'allday': False, 'state': 'open', # to block that meeting date in the calendar - 'privacy': 'confidential' + 'privacy': 'confidential', + 'event_tz': self.user_id.tz, } # Add the partner_id (if exist) as an attendee if self.user_id and self.user_id.partner_id: