예제 #1
0
 def test_until_wrap(self):
     date = RecurringEvent(datetime.date(2010, 11, 1))
     string = 'daily until Feb'
     date.parse(string)
     expected1 = """RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20110201"""
     expected2 = """RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20110201"""
     self.assertIn(date.get_RFC_rrule(), [expected1, expected2])
예제 #2
0
 def test_format_plus(self):
     date = RecurringEvent()
     self.assertEqual(
         date.format('RRULE:INTERVAL=1;FREQ=MONTHLY;BYDAY=+1FR'),
         '1st Fri of every month')
     self.assertEqual(date.format(datetime.datetime(2000, 1, 2, 3, 4, 5)),
                      'Sun Jan 2, 2000 3:04:05am')
예제 #3
0
 def test_rrule_string(self):
     string = 'every day starting feb 2'
     date = RecurringEvent(NOW)
     date.parse(string)
     expected1 = """DTSTART:20100202\nRRULE:FREQ=DAILY;INTERVAL=1"""
     expected2 = """DTSTART:20100202\nRRULE:INTERVAL=1;FREQ=DAILY"""
     self.assertIn(date.get_RFC_rrule(), [expected1, expected2])
예제 #4
0
 def test_(self):
     date = RecurringEvent(NOW)
     val = date.parse(string)
     back_again = date.format(val)
     expected_params = expected
     known_failure = False
     if isinstance(expected, ExpectedFailure):
         known_failure = True
         expected_params = expected.correct_value
     try:
         if expected_params is None:
             self.assertTrue(
                 val is None
                 or list(date.get_params().keys()) == ['interval'],
                 "Non-date error: '%s' -> '%s', expected '%s'" %
                 (string, val, expected_params))
         elif isinstance(expected_params, datetime.datetime) or isinstance(
                 expected_params, datetime.date):
             if isinstance(expected_params, datetime.datetime):
                 self.assertEqual(
                     val, expected_params,
                     "Date parse error: '%s' -> '%s', expected '%s'" %
                     (string, val, expected_params))
             else:
                 self.assertEqual(
                     val.date(), expected_params,
                     "Date parse error: '%s' -> '%s', expected '%s'" %
                     (string, val, expected_params))
         else:
             actual_params = date.get_params()
             for k, v in list(expected_params.items()):
                 av = actual_params.pop(k, None)
                 self.assertEqual(
                     av, v,
                     "Rule mismatch on rule '%s' for '%s'. Expected %s, got %s\nRules: %s"
                     % (k, string, v, av, date.get_params()))
             # make sure any extra params are empty/false
             for k, v in list(actual_params.items()):
                 self.assertFalse(v)  # pragma nocover
             # ensure rrule string can be parsed by dateutil
             rrule.rrulestr(val)
     except AssertionError as e:
         if known_failure:
             print("Expected failure:", expected_params)
             return
         raise e  # pragma nocover
     if known_failure:
         raise AssertionError("Known failure passed:", expected_params,
                              string)  # pragma nocover
     self.maxDiff = 1000
     if de is not None:
         self.assertEqual(de, back_again)
         if back_again is not None and back_again != string:
             self.assertEqual(back_again, date.format(
                 date.parse(back_again)))  # Run it thru again!
예제 #5
0
def create_entries(
    settings: Settings,
    config: Config,
    spec_row: CollectionRowBlock,
) -> Generator[Dict[str, Any], None, None]:
    r = RecurringEvent(now_date=spec_row.start_date.start)
    times = r.parse(spec_row.recurrence)
    rr = rrule.rrulestr(r.get_RFC_rrule(), dtstart=spec_row.start_date.start)

    if get_row_prop(spec_row, 'not_on'):
        not_r = RecurringEvent(now_date=spec_row.start_date.start)
        not_times = not_r.parse(spec_row.not_on)
        not_dates = {
            d.date()
            for d in rrule.rrulestr(
                not_r.get_RFC_rrule(),
                dtstart=spec_row.start_date.start,
            )
        }

    for dt in rr:
        if get_row_prop(spec_row, 'not_on') and dt.date() in not_dates:
            continue

        to_insert = {
            key: spec_row.get_property(key)
            for key in config.properties_to_sync
        }
        to_insert['title'] = spec_row.title
        if config.tags_property in to_insert:
            to_insert[config.tags_property].append(config.scheduled_tag)
        if config.status_property:
            to_insert[
                config.status_property] = config.status_after_today if dt.date(
                ) >= datetime.date.today() else config.status_before_today

        reminder = None
        if get_row_prop(spec_row, 'reminder'):
            reminder = parse_reminder(spec_row.reminder)

        if get_row_prop(spec_row, 'include_time'):
            if get_row_prop(spec_row, 'duration'):
                duration = datetime.timedelta(
                    minutes=Duration(spec_row.duration).to_minutes())
                to_insert[spec_row.date_field] = NotionDate(dt,
                                                            dt + duration,
                                                            reminder=reminder)
            else:
                to_insert[spec_row.date_field] = NotionDate(dt,
                                                            reminder=reminder)
        else:
            to_insert[spec_row.date_field] = NotionDate(dt.date(),
                                                        reminder=reminder)

        if not settings.dry_run:
            yield to_insert
        logging.info(
            f"Added row '{to_insert.get('title', 'Untitled')}' for {dt:%Y-%m-%d}"
        )
예제 #6
0
 def test_date_incrementer(self):
     date = RecurringEvent(datetime.date(2012, 2, 29))  # Leap year
     string = 'daily for the next year'
     date.parse(string)
     expected1 = """RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20130301"""
     expected2 = """RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20130301"""
     self.assertIn(date.get_RFC_rrule(), [expected1, expected2])
     string = 'daily for the next 12 months'
     date.parse(string)
     self.assertIn(date.get_RFC_rrule(), [expected1, expected2])
예제 #7
0
def recurring_date(event, now_date=None, strftime_format='%Y-%m-%d'):
    if now_date != None:
        time_struct, parse_status = parsedatetime.Calendar().parse(now_date)
        if not parse_status:
            raise InvalidDatetimeException('Failed to parse "%s"' % (now_date))
        now_date = datetime(*time_struct[:6])
    else:
        now_date = datetime.today()

    actually_now = datetime.strptime(
        datetime.today().strftime(strftime_format), strftime_format)
    r = RecurringEvent(now_date=now_date)
    if not r.parse(event):
        raise InvalidRecurringDateException('Invalid recurring date "%s"' %
                                            (event))

    rr = rrule.rrulestr(r.get_RFC_rrule())
    res = rr.after(actually_now, inc=True)
    return res.strftime(strftime_format)
예제 #8
0
파일: test.py 프로젝트: kvh/recurrent
 def test_(self):
     date = RecurringEvent(NOW)
     val = date.parse(string)
     expected_params = expected
     known_failure = False
     if isinstance(expected, ExpectedFailure):
         known_failure = True
         expected_params = expected.correct_value
     try:
         if expected_params is None:
             self.assertTrue(val is None or list(date.get_params().keys()) == ['interval'],
                         "Non-date error: '%s' -> '%s', expected '%s'"%(
                             string, val, expected_params))
         elif isinstance(expected_params, datetime.datetime) or isinstance(expected_params, datetime.date):
             if isinstance(expected_params, datetime.datetime):
                 self.assertEqual(val, expected_params,
                         "Date parse error: '%s' -> '%s', expected '%s'"%(
                             string, val, expected_params))
             else:
                 self.assertEqual(val.date(), expected_params,
                         "Date parse error: '%s' -> '%s', expected '%s'"%(
                             string, val, expected_params))
         else:
             actual_params = date.get_params()
             for k, v in list(expected_params.items()):
                 av = actual_params.pop(k, None)
                 self.assertEqual(av, v,
                         "Rule mismatch on rule '%s' for '%s'. Expected %s, got %s\nRules: %s" % (k, string, v, av,
                             date.get_params()))
             # make sure any extra params are empty/false
             for k, v in list(actual_params.items()):
                 self.assertFalse(v)
             # ensure rrule string can be parsed by dateutil
             rrule.rrulestr(val)
     except AssertionError as e:
         if known_failure:
             print("Expected failure:", expected_params)
             return
         raise e
     if known_failure:
         raise AssertionError("Known failure passed:", expected_params, string)
예제 #9
0
    def __init__(self,
                 content='',
                 name='',
                 created=None,
                 modified=None,
                 datestring=None,
                 importance=1000,
                 durationstring=None):
        current_time = round(time.time())

        self.name = name
        self.content = content

        self.id = uuid.uuid4().hex

        if created:
            self.created = created
        else:
            self.created = current_time

        if modified:
            self.modified = modified
        else:
            self.modified = current_time

        # self.next = 1
        self.datestring = datestring

        if self.datestring != None and len(self.datestring) > 0:
            try:
                now = datetime.datetime.now()
                # now = datetime.datetime(2010, 1, 1)
                r = RecurringEvent(now_date=now)
                self.dateparse = r.parse(self.datestring)
                self.dateparams = r.get_params()
                self.datesummary = r.format(self.dateparse)
                if r.is_recurring:
                    rr = rrule.rrulestr(r.get_RFC_rrule())
                    self.next = str(rr.after(now))

                    print(self.dateparse, self.dateparams, self.datesummary,
                          self.next)
            except Exception as e:
                print(e)

        self.durationstring = durationstring

        if self.durationstring != None and len(self.durationstring) > 0:
            self.duration = parse_duration(self.durationstring)

        self.importance = {
            'user_defined': importance,
            'calculated': 1000.,
            'history': [],
            'ranked': []
        }
        if hasattr(self, 'dateparse'):
            self.dateparse = str(self.dateparse)
예제 #10
0
 def test_return_recurring(self):
     string = 'every day'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, str))
예제 #11
0
def project_parse_cfg_options(cfg, section):
    """
    Parse project configuration. Use of recurrent lib to parse fuzzy time values
    :param cfg: Configuration object
    :param section: Section in the configuration object, i.e. project type
    :return: Dictionary. Keys are: "duration_text", "duration_dt", "extendable",
            "finish_text", "finish_dt", "cpu", "finish_notice_text", "acl",
            "finish_notice_dt", "transform", "description", "evaluation_text",
            "evaluation_dt", "evaluation_notice_text", "evaluation_notice_dt"
    """
    r = RecurringEvent()
    cpu = cfg.getint(section, "cpu", fallback=None)
    description = cfg.get(section, "description", fallback=None)
    duration = cfg.get(section, "duration", fallback=None)
    if duration:
        duration_dt = r.parse(duration).replace(tzinfo=timezone.utc)
    else:
        duration_dt = None
    end = cfg.get(section, "finish_date", fallback=None)
    if end:
        end_dt = r.parse(end).replace(tzinfo=timezone.utc)
    else:
        end_dt = None
    end_notice = cfg.get(section, "finish_notice", fallback=None)
    if end_notice and end_dt:
        tmp = RecurringEvent(end_dt).parse(end_notice)
        end_notice_dt = tmp.replace(tzinfo=timezone.utc)
    else:
        end_notice_dt = None
    trans = cfg.get(section, "transform", fallback=None)
    if trans:
        transform = list(map(lambda x: x.strip(), trans.split(",")))
    else:
        transform = []
    acl = cfg.get(section, "acl", fallback=[])
    if acl:
        acl = list(map(lambda x: x.strip(), acl.split(",")))
    acl.append("admin")

    eva = cfg.get(section, "evaluation_date", fallback=None)
    if eva:
        evaluation = list(map(lambda x: x.strip(), eva.split(",")))
    else:
        evaluation = []
    if evaluation:
        tmp = list(map(lambda x: r.parse(x), evaluation))
        eva_dt = list(map(lambda x: x.replace(tzinfo=timezone.utc), tmp))
    else:
        eva_dt = None

    eva_notice = cfg.get(section, "evaluation_notice", fallback=None)
    if eva_notice and eva_dt:
        tmp = list(map(lambda x: RecurringEvent(x).parse(eva_notice), eva_dt))
        eva_text_dt = list(map(lambda x: x.replace(tzinfo=timezone.utc), tmp))
    else:
        eva_text_dt = None
    extendable = cfg.get(section, "extendable", fallback=False)

    visa_names = cfg.get(section, "visa", fallback=None)
    if visa_names:
        visa = list(map(lambda x: x.strip(), visa_names.split(",")))
    else:
        visa = []
    return {
        "duration_text": duration,
        "duration_dt": duration_dt,
        "acl": acl,
        "finish_text": end,
        "finish_dt": end_dt,
        "cpu": cpu,
        "visa": visa,
        "finish_notice_text": end_notice,
        "extendable": extendable,
        "finish_notice_dt": end_notice_dt,
        "transform": transform,
        "description": description,
        "evaluation_text": evaluation,
        "evaluation_dt": eva_dt,
        "evaluation_notice_text": eva_notice,
        "evaluation_notice_dt": eva_text_dt
    }
예제 #12
0
파일: test.py 프로젝트: kvh/recurrent
 def test_return_recurring(self):
     string = 'every day'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, str))
예제 #13
0
파일: test.py 프로젝트: kvh/recurrent
 def test_return_non_recurring2(self):
     string = 'next wednesday'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, datetime.datetime))
예제 #14
0
 def test_return_non_date(self):
     string = 'remember to call mitchell'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertFalse(ret)
예제 #15
0
파일: test.py 프로젝트: kvh/recurrent
 def test_rrule_string(self):
     string = 'every day starting feb 2'
     date = RecurringEvent(NOW)
     date.parse(string)
     expected = """DTSTART:20100202\nRRULE:FREQ=DAILY;INTERVAL=1"""
     self.assertEqual(expected, date.get_RFC_rrule())
예제 #16
0
파일: test.py 프로젝트: kvh/recurrent
 def test_return_non_date(self):
     string = 'remember to call mitchell'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertFalse(ret)
예제 #17
0
 def test_return_non_recurring(self):
     string = 'march 3rd, 2001'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, datetime.datetime))
예제 #18
0
 def test_return_non_recurring2(self):
     string = 'next wednesday'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, datetime.datetime))
예제 #19
0
파일: test.py 프로젝트: kvh/recurrent
 def test_return_non_recurring(self):
     string = 'march 3rd, 2001'
     date = RecurringEvent()
     ret = date.parse(string)
     self.assertTrue(isinstance(ret, datetime.datetime))
예제 #20
0
 def test_rrule_string(self):
     string = 'every day starting feb 2'
     date = RecurringEvent(NOW)
     date.parse(string)
     expected = """DTSTART:20100202\nRRULE:FREQ=DAILY;INTERVAL=1"""
     self.assertEqual(expected, date.get_RFC_rrule())
예제 #21
0
 def test_format_errors(self):
     date = RecurringEvent()
     self.assertIs(date.format(None), None)
     self.assertEqual(date.format(''), '')
     self.assertEqual(date.format('abc'), 'abc')  # No RRULE
     self.assertEqual(date.format('RRULE:INTERVAL=1'),
                      'RRULE:INTERVAL=1')  # No FREQ
     self.assertEqual(date.format('RRULE:FREQ=WEEKLY'),
                      'RRULE:FREQ=WEEKLY')  # No BYDAY
     self.assertEqual(date.format('RRULE:FREQ=WEEKLY;BYDAY=XX'),
                      'RRULE:FREQ=WEEKLY;BYDAY=XX')  # Bad BYDAY
     self.assertEqual(date.format('RRULE:FREQ=MONTHLY'),
                      'RRULE:FREQ=MONTHLY')  # No BYMONTHDAY or BYDAY
     self.assertEqual(
         date.format('RRULE:FREQ=YEARLY'),
         'RRULE:FREQ=YEARLY')  # No BYMONTHDAY or BYDAY or BYMONTH
     self.assertEqual(date.format('RRULE:FREQ=BADLY'), 'RRULE:FREQ=BADLY')
예제 #22
0
def parse(s, now=None):
    return RecurringEvent(now).parse(s)
예제 #23
0
def format(r, now=None):
    return RecurringEvent(now).format(r)