2012-09-08 6 views
9

Estoy tratando de imprimir una regla de recurrencia como una cadena especificada por formato iCalendar (ver RFC 5545). Im usando dateutils pitón, en particular, dateutil.rrule para crear la regla de repetición y quiero imprimir esto como una cadena como:Python dateutils imprime la regla de recurrencia según el formato iCalendar (ver RFC 5545)

"RRULE:FREQ=DAILY;COUNT=5" 

Puede alguien decirme si hay un método para lograr esto?

Creo que estoy usando labix dateutils btw.

¡Muchas gracias!

Respuesta

7

No hay ningún método o función en el paquete python-dateutil para hacer esto. Vea este error para un parche que puede ayudar: https://bugs.launchpad.net/dateutil/+bug/943512.

+0

se debe tener cuidado con el plegado de línea http: // www .apps.ietf.org/rfc/rfc2445.html # sec-4.1 – oberron

0

Aquí hay una subclase de rrule que incorpora dos parches sugeridos python-dateutil que permiten la salida rrule. Tenga en cuenta que puede haber buenas razones para que los parches no hayan sido aceptados, y solo he probado esto para los casos más simples. El plegado de línea no se maneja.

Véase el seguimiento de errores para la discusión: https://bugs.launchpad.net/dateutil/+bug/943512
https://bugs.launchpad.net/dateutil/+bug/943509

FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY'] 


class ConvertibleRRule(rrule.rrule): 
    # Subclass of the `rrule class that provides a sensible __str__() 
    # method, outputting ical formatted rrules. 
    # Combined from the patches in these dateutil issues: 
    # https://bugs.launchpad.net/dateutil/+bug/943512 
    # https://bugs.launchpad.net/dateutil/+bug/943509 
    _bysecond_internal = False 
    _byminute_internal = False 
    _byhour = False 
    _bymonth_internal = False 
    _bymonthday_internal = False 
    _byweekday_internal = False 

    def __init__(self, freq, dtstart=None, 
       interval=1, wkst=None, count=None, until=None, bysetpos=None, 
       bymonth=None, bymonthday=None, byyearday=None, byeaster=None, 
       byweekno=None, byweekday=None, 
       byhour=None, byminute=None, bysecond=None, 
       cache=False): 
     super(ConvertibleRRule, self).__init__(
      freq, dtstart=dtstart, 
      interval=interval, wkst=wkst, count=count, until=until, bysetpos=bysetpos, 
      bymonth=bymonth, bymonthday=bymonthday, byyearday=byyearday, byeaster=byeaster, 
      byweekno=byweekno, byweekday=byweekday, 
      byhour=byhour, byminute=byminute, bysecond=bysecond, 
      cache=cache) 

     if (byweekno is None and byyearday is None and bymonthday is None and 
        byweekday is None and byeaster is None): 
      if freq == rrule.YEARLY: 
       if not bymonth: 
        self._bymonth_internal = True 
       self._bymonthday_internal = True 
      elif freq == rrule.MONTHLY: 
       self._bymonthday_internal = True 
      elif freq == rrule.WEEKLY: 
       self._byweekday_internal = True 

     # byhour 
     if byhour is None: 
      if freq < rrule.HOURLY: 
       self._byhour_internal = True 

     # byminute 
     if byminute is None: 
      if freq < rrule.MINUTELY: 
       self._byminute_internal = True 

     # bysecond 
     if bysecond is None: 
      if freq < rrule.SECONDLY: 
       self._bysecond_internal = True 

    freq = property(lambda s: s._freq) 
    dtstart = property(lambda s: s._dtstart) 
    interval = property(lambda s: s._interval) 

    @property 
    def wkst(self): 
     if self._wkst == rrule.calendar.firstweekday(): 
      return None 
     return rrule.weekday(self._wkst) 

    count = property(lambda s: s._count) 
    until = property(lambda s: s._until) 
    bysetpos = property(lambda s: s._bysetpos) 

    @property 
    def bymonth(self): 
     if self._bymonth_internal: 
      return None 
     return self._bymonth 

    @property 
    def bymonthday(self): 
     if self._bymonthday_internal: 
      return None 
     return self._bymonthday + self._bynmonthday 

    byyearday = property(lambda s: s._byyearday) 
    byeaster = property(lambda s: s._byeaster) 
    byweekno = property(lambda s: s._byweekno) 

    @property 
    def byweekday(self): 
     if self._byweekday_internal: 
      return None 
     bynweekday, byweekday =(),() 
     if self._bynweekday: 
      bynweekday = tuple(rrule.weekday(d, n) for d, n in self._bynweekday) 
     if self._byweekday: 
      byweekday = tuple(rrule.weekday(d) for d in self._byweekday) 
     return bynweekday + byweekday 

    @property 
    def byhour(self): 
     if self._byhour_internal: 
      return None 
     return self._byhour 

    @property 
    def byminute(self): 
     if self._byminute_internal: 
      return None 
     return self._byminute 

    @property 
    def bysecond(self): 
     if self._bysecond_internal: 
      return None 
     return self._bysecond 

    def __str__(self): 
     parts = ['FREQ=' + FREQNAMES[self.freq]] 

     if self.interval != 1: 
      parts.append('INTERVAL=' + str(self.interval)) 
     if self.wkst: 
      parts.append('WKST=' + str(self.wkst)) 
     if self.count: 
      parts.append('COUNT=' + str(self.count)) 

     for name, value in [ 
      ('BYSETPOS', self.bysetpos), 
      ('BYMONTH', self.bymonth), 
      ('BYMONTHDAY', self.bymonthday), 
      ('BYYEARDAY', self.byyearday), 
      ('BYWEEKNO', self.byweekno), 
      ('BYWEEKDAY', self.byweekday), 
      ('BYHOUR', self.byhour), 
      ('BYMINUTE', self.byminute), 
      ('BYSECOND', self.bysecond), 
     ]: 
      if value: 
       parts.append(name + '=' + ','.join(str(v) for v in value)) 

     return ';'.join(parts) 
0

aunque esto es escrito cuatro años después de que se hizo la pregunta, dateutil por ahora tiene un método __str__ (ver source code), que le permite a uno print sus objetos en tal forma:

In [1]: from dateutil.rrule import * 

In [2]: my_rrule = rrule(DAILY, count=5) 

In [3]: print(my_rrule) 
DTSTART:20161202T184513 
FREQ=DAILY;COUNT=5 
Cuestiones relacionadas