From 1dea8a53fbe5d064ea6aeae6506df71be00412f5 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 8 Mar 2017 16:03:54 +0100 Subject: [PATCH] [FIX] resource: correct also microsecond information A lot of methods are designed to work with pure datetime objects as args. If the value comes from the database it will be rounded at the level of seconds (0 microsecond). If it comes from a call do datetime.now() / datetime.utcnow() the datetime object has a value != 0 for its mircroseconds attribute. Therefore some methods have unpredictable results depending of the origin of the values manipulated since the microsecond argument is missing into all the calls to datetime.replace Closes #15768 --- addons/resource/models/resource.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/addons/resource/models/resource.py b/addons/resource/models/resource.py index 32898e2470e..5551d1c6838 100644 --- a/addons/resource/models/resource.py +++ b/addons/resource/models/resource.py @@ -300,34 +300,34 @@ class ResourceCalendar(models.Model): # Computes start_dt, end_dt (with default values if not set) + off-interval work limits work_limits = [] if start_dt is None and end_dt is not None: - start_dt = end_dt.replace(hour=0, minute=0, second=0) + start_dt = end_dt.replace(hour=0, minute=0, second=0, microsecond=0) elif start_dt is None: - start_dt = datetime.datetime.now().replace(hour=0, minute=0, second=0) + start_dt = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) else: - work_limits.append((start_dt.replace(hour=0, minute=0, second=0), start_dt)) + work_limits.append((start_dt.replace(hour=0, minute=0, second=0, microsecond=0), start_dt)) if end_dt is None: - end_dt = start_dt.replace(hour=23, minute=59, second=59) + end_dt = start_dt.replace(hour=23, minute=59, second=59, microsecond=999999) else: - work_limits.append((end_dt, end_dt.replace(hour=23, minute=59, second=59))) + work_limits.append((end_dt, end_dt.replace(hour=23, minute=59, second=59, microsecond=999999))) assert start_dt.date() == end_dt.date(), 'get_working_intervals_of_day is restricted to one day' intervals = [] - work_dt = start_dt.replace(hour=0, minute=0, second=0) + work_dt = start_dt.replace(hour=0, minute=0, second=0, microsecond=0) # no calendar: try to use the default_interval, then return directly if not self: working_interval = [] if default_interval: - working_interval = (start_dt.replace(hour=default_interval[0], minute=0, second=0), - start_dt.replace(hour=default_interval[1], minute=0, second=0)) + working_interval = (start_dt.replace(hour=default_interval[0], minute=0, second=0, microsecond=0), + start_dt.replace(hour=default_interval[1], minute=0, second=0, microsecond=0)) intervals = self.interval_remove_leaves(working_interval, work_limits) return intervals working_intervals = [] tz_info = fields.Datetime.context_timestamp(self, work_dt).tzinfo for calendar_working_day in self.get_attendances_for_weekday(start_dt): - dt_f = work_dt.replace(hour=0, minute=0, second=0) + timedelta(seconds=(calendar_working_day.hour_from * 3600)) - dt_t = work_dt.replace(hour=0, minute=0, second=0) + timedelta(seconds=(calendar_working_day.hour_to * 3600)) + dt_f = work_dt.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(seconds=(calendar_working_day.hour_from * 3600)) + dt_t = work_dt.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(seconds=(calendar_working_day.hour_to * 3600)) # adapt tz working_interval = ( @@ -369,12 +369,12 @@ class ResourceCalendar(models.Model): resource_id=None, default_interval=None): hours = 0.0 for day in rrule.rrule(rrule.DAILY, dtstart=start_dt, - until=(end_dt + timedelta(days=1)).replace(hour=0, minute=0, second=0), + until=(end_dt + timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0), byweekday=self.get_weekdays()): - day_start_dt = day.replace(hour=0, minute=0, second=0) + day_start_dt = day.replace(hour=0, minute=0, second=0, microsecond=0) if start_dt and day.date() == start_dt.date(): day_start_dt = start_dt - day_end_dt = day.replace(hour=23, minute=59, second=59) + day_end_dt = day.replace(hour=23, minute=59, second=59, microsecond=999999) if end_dt and day.date() == end_dt.date(): day_end_dt = end_dt hours += self.get_working_hours_of_date( @@ -528,7 +528,7 @@ class ResourceCalendar(models.Model): intervals = [] planned_days = 0 iterations = 0 - current_datetime = day_date.replace(hour=0, minute=0, second=0) + current_datetime = day_date.replace(hour=0, minute=0, second=0, microsecond=0) while planned_days < days and iterations < 100: working_intervals = self.get_working_intervals_of_day( @@ -585,7 +585,7 @@ class ResourceCalendar(models.Model): saas-3, counts leave hours instead of all-day leaves.""" return self.schedule_hours( hours * -1.0, - day_dt=dt_from.replace(minute=0, second=0), + day_dt=dt_from.replace(minute=0, second=0, microsecond=0), compute_leaves=True, resource_id=resource, default_interval=(8, 16) )