Commit 6155f7ff authored by Yoshinori Okuji's avatar Yoshinori Okuji

This is a fix for the long-living bug that the periodicity mixin

does not work appropriately with daylight savings / summer time.


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@39374 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent e6c2bdfe
......@@ -130,6 +130,48 @@ class PeriodicityMixin:
elif len(periodicity_month_list) > 0:
return date.month() in periodicity_month_list
def _getTimezone(self, date):
# This method provides an utility to deal with a timezone as a workaround.
# This is necessary because DateTime does not respect the real timezone
# such as Europe/Paris, but only stores a difference from GMT such as
# GMT+1, thus it does not work nicely with daylight savings.
if date.tzoffset() == 0:
# Looks like using GMT.
return date.timezone()
return None
def _getNextDay(self, date, timezone):
if timezone is not None:
new_date = DateTime(date.timeTime() + 86400.0, timezone)
else:
new_date = DateTime(date.timeTime() + 86400.0)
# Due to daylight savings, 24 hours later does not always mean that
# it's next day.
while new_date.day() == date.day():
if timezone is not None:
new_date = DateTime(new_date.timeTime() + 3600.0, timezone)
else:
new_date = DateTime(new_date.timeTime() + 3600.0)
return DateTime(new_date.year(), new_date.month(), new_date.day(),
0, 0, 0, timezone)
def _getNextHour(self, date, timezone):
if timezone is not None:
new_date = DateTime(date.timeTime() + 3600.0, timezone)
else:
new_date = DateTime(date.timeTime() + 3600.0)
return DateTime(new_date.year(), new_date.month(), new_date.day(),
new_date.hour(), 0, 0, timezone)
def _getNextMinute(self, date, timezone):
if timezone is not None:
new_date = DateTime(date.timeTime() + 60.0, timezone)
else:
new_date = DateTime(date.timeTime() + 60.0)
return DateTime(new_date.year(), new_date.month(), new_date.day(),
new_date.hour(), new_date.minute(), 0, timezone)
security.declareProtected(Permissions.AccessContentsInformation, 'getNextPeriodicalDate')
def getNextPeriodicalDate(self, current_date, next_start_date=None):
"""
......@@ -159,21 +201,24 @@ class PeriodicityMixin:
and next_start_date >= periodicity_stop_date):
return None
timezone = self._getTimezone(next_start_date)
previous_date = next_start_date
next_start_date = max(addToDate(next_start_date, minute=1), current_date)
next_start_date = max(self._getNextMinute(next_start_date, timezone),
current_date)
while 1:
if not self._validateMonth(next_start_date):
next_start_date = atTheEndOfPeriod(next_start_date, 'month')
next_start_date = self._getNextMonth(next_start_date, timezone)
elif not (self._validateDay(next_start_date) and
self._validateWeek(next_start_date)):
next_start_date = atTheEndOfPeriod(next_start_date, 'day')
next_start_date = self._getNextDay(next_start_date, timezone)
elif not self._validateMinute(next_start_date, previous_date):
next_start_date = addToDate(next_start_date, minute=1)
next_start_date = self._getNextMinute(next_start_date, timezone)
elif not self._validateHour(next_start_date):
next_start_date = addToDate(next_start_date, hour=1)
next_start_date = self._getNextHour(next_start_date, timezone)
else:
parts = list(next_start_date.parts())
parts[5] = previous_date.second() # XXX keep old behaviour
parts[6] = timezone
return DateTime(*parts)
# XXX May be we should create a Date class for following methods ???
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment