【问题标题】:Python dateutils print recurrence rule according to iCalendar format (see RFC 5545)Python dateutils 根据 iCalendar 格式打印重复规则(参见 RFC 5545)
【发布时间】:2012-09-02 03:17:13
【问题描述】:

我正在尝试将重复规则打印为 iCalendar 格式指定的字符串(请参阅RFC 5545)。我使用 python dateutils,特别是 dateutil.rrule 来创建重复规则,我想将其打印为如下字符串:

    "RRULE:FREQ=DAILY;COUNT=5"

谁能告诉我有没有办法做到这一点?

我想我正在使用 labix dateutils btw。

非常感谢!

【问题讨论】:

    标签: python python-dateutil rrule rfc5545


    【解决方案1】:

    python-dateutil 包中没有执行此操作的方法或函数。请参阅此错误以获取可能有帮助的补丁:https://bugs.launchpad.net/dateutil/+bug/943512

    【讨论】:

    【解决方案2】:

    这是rrule 的子类,它包含两个建议的python-dateutil 补丁,可以启用rrule 输出。请注意,补丁未被接受可能有充分的理由,我仅针对最简单的情况进行了测试。不处理线折叠。

    请参阅错误跟踪器进行讨论: 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)
    

    【讨论】:

      【解决方案3】:

      虽然这是在提出问题四年后写的,dateutil 现在有一个__str__ 方法(参见source code),它允许print 它的对象以这样的形式:

      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
      

      【讨论】:

        猜你喜欢
        • 2012-07-12
        • 1970-01-01
        • 2017-10-18
        • 2023-04-09
        • 2014-11-20
        • 2011-03-22
        • 2020-06-24
        • 2012-06-21
        相关资源
        最近更新 更多