From 38b0855aca58539f389bb4427ba220702621734e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= Date: Wed, 6 Jul 2016 08:38:37 +0000 Subject: [PATCH 1/2] calendar: add a test for calendar assignent with day light saving switch --- product/ERP5/tests/testCalendar.py | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/product/ERP5/tests/testCalendar.py b/product/ERP5/tests/testCalendar.py index c4b3d3e9978..25bfed4d1ea 100644 --- a/product/ERP5/tests/testCalendar.py +++ b/product/ERP5/tests/testCalendar.py @@ -1071,6 +1071,46 @@ class TestCalendar(ERP5ReportTestCase): presence_request.setDestinationValue(person) self.assertEqual(0, len(presence_request.checkConsistency())) + def test_GroupCalendarPeriodicityDayLightSaving(self): + """Test group calendar periodicity handles day light saving. + + If we configure "every day from 09:00 to 12:00 in Europe/Paris time", this is 09:00 GMT+1 or + 09:00 GMT+1 according to daylight saving time. + + """ + node = self.portal.organisation_module.newContent(portal_type='Organisation',) + + group_calendar = self.portal.group_calendar_module.newContent( + portal_type='Group Calendar') + group_calendar_period = group_calendar.newContent( + portal_type='Group Presence Period') + + # In 2008, DST switch was Sunday 30 march + group_calendar_period.setStartDate('2008/03/29 09:00:00 Europe/Paris') + group_calendar_period.setStopDate('2008/03/29 12:00:00 Europe/Paris') + group_calendar_period.setQuantity(10) + group_calendar_period.setResourceValue( + self.portal.portal_categories.calendar_period_type.type1) + group_calendar_period.setPeriodicityDayFrequency(1) + group_calendar_period.setPeriodicityStopDate(DateTime('2008/12/31 00:00:00 Europe/Paris')) + self.tic() + + assignment = self.portal.group_calendar_assignment_module.newContent( + specialise_value=group_calendar, + resource_value=self.portal.portal_categories.calendar_period_type.type1, + start_date=DateTime('2008/03/29 09:00:00 Europe/Paris'), + stop_date=DateTime('2008/04/02 00:00:00 Europe/Paris'), + destination_value=node) + assignment.confirm() + self.tic() + + self.assertEqual([ + ( DateTime('2008/03/29 09:00:00 Europe/Paris'), DateTime('2008/03/29 12:00:00 Europe/Paris') ), + ( DateTime('2008/03/30 09:00:00 Europe/Paris'), DateTime('2008/03/30 12:00:00 Europe/Paris') ), + ( DateTime('2008/03/31 09:00:00 Europe/Paris'), DateTime('2008/03/31 12:00:00 Europe/Paris') ), + ( DateTime('2008/04/01 09:00:00 Europe/Paris'), DateTime('2008/04/01 12:00:00 Europe/Paris') ), ], + [ (m.getStopDate(), m.getStartDate()) for m in assignment.asMovementList() ] ) + def test_SimpleLeaveRequestWithSameDateAsGroupCalendar(self): group_calendar = self.portal.group_calendar_module.newContent( portal_type='Group Calendar') -- 2.30.9 From 627fec02822fbbfef2429247dfc91557689e8f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= Date: Wed, 6 Jul 2016 09:43:29 +0000 Subject: [PATCH 2/2] calendar: make PresencePeriod support timezone with daylight saving - update PresencePeriod.getNextPeriodicalDate with fixes from 6155f7ff14843c50ffa7cebefa6dfdce25546fa1 - do not use addToDate, but simply DateTime arithmetics that unlike addToDate, works correctly --- product/ERP5/Document/PresencePeriod.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/product/ERP5/Document/PresencePeriod.py b/product/ERP5/Document/PresencePeriod.py index 197f522b1a7..a2e21cdad4b 100644 --- a/product/ERP5/Document/PresencePeriod.py +++ b/product/ERP5/Document/PresencePeriod.py @@ -31,6 +31,7 @@ from copy import copy from AccessControl import ClassSecurityInfo +from DateTime import DateTime from Products.ERP5Type import Permissions, PropertySheet from Products.ERP5.mixin.periodicity import PeriodicityMixin @@ -145,15 +146,15 @@ class PresencePeriod(Movement, PeriodicityMixin): stop_date = self.getStopDate(start_date) periodicity_stop_date = self.getPeriodicityStopDate( start_date) - second_duration = int(stop_date) - int(start_date) - if second_duration > 0: + duration = stop_date - start_date + if duration > 0: # First date has to respect the periodicity config next_start_date = self.getNextPeriodicalDate(addToDate(start_date, day=-1)) while (next_start_date is not None) and \ (next_start_date <= periodicity_stop_date): if next_start_date.Date() not in exception_date_set: result.append({'start_date': next_start_date, - 'stop_date': addToDate(next_start_date, second=second_duration), + 'stop_date': next_start_date + duration, 'quantity': self.getQuantity()}) next_start_date = self.getNextPeriodicalDate(next_start_date) @@ -178,12 +179,21 @@ class PresencePeriod(Movement, PeriodicityMixin): day_count = int(current_date-next_start_date) next_start_date = next_start_date + day_count - next_start_date = addToDate(next_start_date, day=1) + timezone = self._getTimezone(next_start_date) + next_start_date = self._getNextDay(next_start_date, timezone) while 1: if (self._validateDay(next_start_date)) and \ (self._validateWeek(next_start_date)) and \ (self._validateMonth(next_start_date)): break else: - next_start_date = addToDate(next_start_date, day=1) - return next_start_date + next_start_date = self._getNextDay(next_start_date, timezone) + + return DateTime( + next_start_date.year(), + next_start_date.month(), + next_start_date.day(), + current_date.hour(), + current_date.minute(), + current_date.second(), + timezone) -- 2.30.9