[Erp5-report] r39374 yo - /erp5/trunk/products/ERP5/Document/Alarm.py

nobody at svn.erp5.org nobody at svn.erp5.org
Wed Oct 20 10:08:41 CEST 2010


Author: yo
Date: Wed Oct 20 10:08:41 2010
New Revision: 39374

URL: http://svn.erp5.org?rev=39374&view=rev
Log:
This is a fix for the long-living bug that the periodicity mixin
does not work appropriately with daylight savings / summer time.

Modified:
    erp5/trunk/products/ERP5/Document/Alarm.py

Modified: erp5/trunk/products/ERP5/Document/Alarm.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5/Document/Alarm.py?rev=39374&r1=39373&r2=39374&view=diff
==============================================================================
--- erp5/trunk/products/ERP5/Document/Alarm.py [utf8] (original)
+++ erp5/trunk/products/ERP5/Document/Alarm.py [utf8] Wed Oct 20 10:08:41 2010
@@ -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 ???




More information about the Erp5-report mailing list