{"action":"created","issue":{"url":"https://api.github.com/repos/dateutil/dateutil/issues/37","labels_url":"https://api.github.com/repos/dateutil/dateutil/issues/37/labels{/name}","comments_url":"https://api.github.com/repos/dateutil/dateutil/issues/37/comments","events_url":"https://api.github.com/repos/dateutil/dateutil/issues/37/events","html_url":"https://github.com/dateutil/dateutil/issues/37","id":57869591,"number":37,"title":"Make it possible to separate `dtstart` and `basis` in constructing `rrule`","user":{"login":"carljm","id":61586,"avatar_url":"https://avatars.githubusercontent.com/u/61586?v=3","gravatar_id":"","url":"https://api.github.com/users/carljm","html_url":"https://github.com/carljm","followers_url":"https://api.github.com/users/carljm/followers","following_url":"https://api.github.com/users/carljm/following{/other_user}","gists_url":"https://api.github.com/users/carljm/gists{/gist_id}","starred_url":"https://api.github.com/users/carljm/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carljm/subscriptions","organizations_url":"https://api.github.com/users/carljm/orgs","repos_url":"https://api.github.com/users/carljm/repos","events_url":"https://api.github.com/users/carljm/events{/privacy}","received_events_url":"https://api.github.com/users/carljm/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dateutil/dateutil/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/dateutil/dateutil/labels/rrule","name":"rrule","color":"bfd4f2"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-02-17T00:45:31Z","updated_at":"2015-02-17T14:11:45Z","closed_at":null,"body":"I have a case where I need to know whether or not the start date of a recurrence (given a period, an interval, and a `dtstart`) is far enough in the future to make the next occurrence further away than it would be if the recurrence extended back to today. (Or to simplify the problem statement, I need to take an `rrule` determined by an interval, a period, and a `dtstart`, and extend that `rrule` backwards in time before that `dtstart`).\r\n\r\nIt seems the most robust way to answer this question would be to construct an `rrule` whose start date is today, but which uses the real start date as the basis for determining the `by*` defaults. It seems to me that `dateutil` doesn't currently provide any public API that I could use to do this, though.\r\n\r\nI could, of course, provide today as the original `dtstart` if I explicitly calculate and provide the necessary `by*` arguments, so that `dtstart` isn't used as the basis for defaulting them. But this involves duplicating a bunch of knowledge that's already encoded in `rrule.__init__`, which seems silly.\r\n\r\nThere would be a few possible APIs for this, but the one that seems most natural to me (and doesn't break the immutability of `rrule` objects, which would be problematic for caching) would be to provide a new init argument, `basis`, which defaults to `dtstart` if not provided, and is used to provide the defaults for all the `by*` arguments. This would allow one to separate \"when does this rrule start?\" from \"what key datetime should be used to lock down this recurrence?\"\r\n\r\nWhat do you think? Is this a reasonable use case? Is there an alternative technique that I've missed? If I submitted a PR for this, would it have a shot of getting in?\r\n\r\nI think the actual code changes would be quite simple: add the `basis` arg, default it to `dtstart` if it is `None`, and then replace `dtstart` with `basis` throughout `__init__` wherever `dtstart` is currently used to determine default values for `by*` properties."},"comment":{"url":"https://api.github.com/repos/dateutil/dateutil/issues/comments/74672829","html_url":"https://github.com/dateutil/dateutil/issues/37#issuecomment-74672829","issue_url":"https://api.github.com/repos/dateutil/dateutil/issues/37","id":74672829,"user":{"login":"pganssle","id":1377457,"avatar_url":"https://avatars.githubusercontent.com/u/1377457?v=3","gravatar_id":"","url":"https://api.github.com/users/pganssle","html_url":"https://github.com/pganssle","followers_url":"https://api.github.com/users/pganssle/followers","following_url":"https://api.github.com/users/pganssle/following{/other_user}","gists_url":"https://api.github.com/users/pganssle/gists{/gist_id}","starred_url":"https://api.github.com/users/pganssle/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pganssle/subscriptions","organizations_url":"https://api.github.com/users/pganssle/orgs","repos_url":"https://api.github.com/users/pganssle/repos","events_url":"https://api.github.com/users/pganssle/events{/privacy}","received_events_url":"https://api.github.com/users/pganssle/received_events","type":"User","site_admin":false},"created_at":"2015-02-17T14:11:45Z","updated_at":"2015-02-17T14:11:45Z","body":"Actually, looking at this more carefully, I realize that `after()` retrieves exactly one date, so the way to do what you want would be:\r\n\r\n```python\r\n    def dates_after(rr, basis_date, count=None):\r\n    \"\"\"\r\n    Generator to generate `count` dates after basis_date from rrule rr\r\n\r\n    :param rr:\r\n        Instance of `dateutil.rrule` to iterate over.\r\n\r\n    :param basis_date:\r\n        The date from which to start generating dates (inclusive)\r\n\r\n    :param count:\r\n        The maximum number of dates to return - if None is passed this will yield dates until the\r\n        rrule is exhausted.\r\n    \"\"\"\r\n    # Needs to execute at least once\r\n    cdate = rr.after(basis_date, inc=True)  # Include the basis date on the first run\r\n\r\n    n = 0\r\n    while cdate is not None:\r\n        cdate = rr.after(cdate)\r\n\r\n        yield cdate\r\n\r\n        n += 1\r\n        if cdate is None and count is not None and n >= count:\r\n            raise StopIteration\r\n\r\n    return None\r\n```\r\n\r\nI think the best thing to do is to add a `count` parameter to both `before()` and `after()` which, if specified, naturally returns a generator, but for now hoepfully the function above works for you."}}