django-recurrence icon indicating copy to clipboard operation
django-recurrence copied to clipboard

DTEND always shows up as occurrence

Open fozzle opened this issue 7 years ago • 9 comments

I think I'm misunderstanding how this all works, but for example I have a recurrence rule describing "Every Day" with a dtend of July 20th. I also have a exception date of July 20th.

Finding all occurrences for this pattern shows July 20th still present. I would have thought July 20th would be excluded.

Example script (note that July 20th is printed):

from datetime import datetime
import recurrence

rule = recurrence.Rule(recurrence.DAILY)
pattern = recurrence.Recurrence(
    dtstart=datetime(2017, 6, 27, 0, 0, 0),
    dtend=datetime(2017, 7, 20, 0, 0, 0),
    rrules=[rule,],
    exdates=[
        datetime(2017, 7, 20, 0, 0, 0),
    ],
)

print(list(pattern.occurrences()))

This will print:

[datetime.datetime(2017, 6, 27, 0, 0), datetime.datetime(2017, 6, 28, 0, 0), datetime.datetime(2017, 6, 29, 0, 0), datetime.datetime(2017, 6, 30, 0, 0), datetime.datetime(2017, 7, 1, 0, 0), datetime.datetime(2017, 7, 2, 0, 0), datetime.datetime(2017, 7, 3, 0, 0), datetime.datetime(2017, 7, 4, 0, 0), datetime.datetime(2017, 7, 5, 0, 0), datetime.datetime(2017, 7, 6, 0, 0), datetime.datetime(2017, 7, 7, 0, 0), datetime.datetime(2017, 7, 8, 0, 0), datetime.datetime(2017, 7, 9, 0, 0), datetime.datetime(2017, 7, 10, 0, 0), datetime.datetime(2017, 7, 11, 0, 0), datetime.datetime(2017, 7, 12, 0, 0), datetime.datetime(2017, 7, 13, 0, 0), datetime.datetime(2017, 7, 14, 0, 0), datetime.datetime(2017, 7, 15, 0, 0), datetime.datetime(2017, 7, 16, 0, 0), datetime.datetime(2017, 7, 17, 0, 0), datetime.datetime(2017, 7, 18, 0, 0), datetime.datetime(2017, 7, 19, 0, 0), datetime.datetime(2017, 7, 20, 0, 0)]

Alternatively, and likely related, declaring a rule like Every Sunday and having a DTEND will still make DTEND come back when getting occurrences with between() even if that DTEND date doesn't fall within the declared rules. (to be clear, in this example, that would be a DTEND falling on a day that isn't Sunday...but still showing up)

Is this working as intended? And If so, what do I need to do have recurrence rules that have end dates?

If not working as intended I will attempt to fix.

fozzle avatar Jun 28 '17 00:06 fozzle

Looks like this is known, but for what reason? Haha.

https://github.com/django-recurrence/django-recurrence/blob/master/tests/test_occurrences.py#L164

This is happening here: https://github.com/django-recurrence/django-recurrence/blob/524d3af408cacc6ff4d91b707a91df064ea147f9/recurrence/base.py#L563

I suppose this indicates that it's by design. Any thoughts on making this optional, sort of how the also confusing DTSTART inclusion has been handled?

fozzle avatar Jun 28 '17 00:06 fozzle

I think this is a different case than with the DTSTART property. Correct me if I'm wrong, but there seems to be no statement in the specs defining DTEND as an obligatory occurrence. So I would consider this behavior a bug.

denisiko avatar Jun 28 '17 18:06 denisiko

I'm pretty shit at reading specs, but I couldn't even find it as a property for recurrences (4.8.5?)

fozzle avatar Jun 28 '17 19:06 fozzle

Maybe @jpulec can shed some light. After all he's the one who found out about the DTSTART parts in RFC 2445.

denisiko avatar Jul 01 '17 10:07 denisiko

The DTEND defined in RFC 2445 is used only to define the end time of a single event... not the end date/time of an rrule. Recurrence.dtend is a completely different concept that happens to share the same name. In the context of django-recurrence, it exists to have parity with django-recurrence's handling of dtstart, meaning that specifying dtend is just supposed to allow a user to explicitly specify the last occurrence. To be clear, it is completely made up for django-recurrence. It is not part of any spec.

jpulec avatar Jul 04 '17 01:07 jpulec

Thanks for clearing that up @jpulec So what do you suggest for fixing this issue? Remove Recurrence.dtend completely?

denisiko avatar Jul 04 '17 09:07 denisiko

Honestly, I have a bias towards cleaning this library up, such that it follows dateutil instead of following the RFC. In my mind, that means removing it. But even trying to adhere to the spec, the idea of dtend as it's used here is just wrong. I don't think it serves that much purpose, since you could just explicitly add your end date via an explicit Date anyway.

jpulec avatar Jul 05 '17 16:07 jpulec

dateutil.rrule is supposed to follow the same specs anyway according to the docs. So I think so too that it's enough to just wrap the python library and leave the job of being coherent with some specs to others.

I would love to see a new fork that is doing this as an alternative. Would you be up to do this @jpulec ?

denisiko avatar Jul 05 '17 20:07 denisiko

I would really like to avoid forking this repo if possible. However, given that what we're describing here would be a pretty big shift in functionality, it might not be possible otherwise.

jpulec avatar Jul 07 '17 16:07 jpulec