[icalendar-dev] problem with negative fractional vDuration (with patch)

Gene Cash gcash at cfl.rr.com
Wed Oct 10 02:25:20 CEST 2007


It seems that vDuration objects have a problem with negative fractional 
days.

I first noticed this when I was dealing with VALARMs.

 >>> import icalendar
 >>> s='''BEGIN:VALARM
... ACTION:DISPLAY
... DESCRIPTION:Testing
... TRIGGER:-PT5M
... END:VALARM'''
 >>>
 >>> cal=icalendar.Calendar.from_string(s)
 >>> alarm=cal.walk('VALARM')[0]
 >>> print alarm
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Testing
TRIGGER:-P1DT23H55M
END:VALARM

Note the incorrect trigger value.

 >>> print alarm.decoded('TRIGGER')
-2 days, 0:05:00

 >>> x=icalendar.vDuration.from_ical('-PT10M')
 >>> icalendar.vDuration(x).ical()
'-P1DT23H50M'

Oops.

It turns out that negative datetime.timedeltas get normalized, so that 
datetime.timedelta(minutes=-5) becomes datetime.timedelta(-1, 86100) 
which actually means -1 day, +23 hours, +55 minutes, which is where the 
"TRIGGER:-P1DT23H55M" comes from. This upsets vDuration.

The fix is a one-liner in the vDuration.ical method:

--- prop.py.new 2007-10-09 20:17:11.000000000 -0400
+++ prop.py     2007-10-09 20:17:18.000000000 -0400
@@ -423,12 +423,13 @@
          self.params = Parameters()

      def ical(self):
          sign = ""
          if self.td.days < 0:
              sign = "-"
+            self.td=-self.td
          timepart = ""
          if self.td.seconds:
              timepart = "T"
              hours = self.td.seconds // 3600
              minutes = self.td.seconds % 3600 // 60
              seconds = self.td.seconds % 60

After this, things work:

 >>> import icalendar
 >>> s='''BEGIN:VALARM
... ACTION:DISPLAY
... DESCRIPTION:Testing
... TRIGGER:-PT5M
... END:VALARM'''
 >>>
 >>> cal=icalendar.Calendar.from_string(s)
 >>> alarm=cal.walk('VALARM')[0]
 >>> print alarm
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Testing
TRIGGER:-PT5M
END:VALARM

 >>> print alarm.decoded('TRIGGER')
-1 day, 23:55:00

 >>> x=icalendar.vDuration.from_ical('-PT10M')
 >>> icalendar.vDuration(x).ical()
'-PT10M'

Yay. That was not easy to figure out.

-gc

-- 
Is this my glass? Is it? Does it *look* like my glass? No. *My* glass 
was bigger. And full.


More information about the icalendar-dev mailing list