Subject: Fw: [Ietf-calsify] I-D ACTION:draft-ietf-calsify-rfc2445bis-08.txt

From: "Nigel Swinson" <[email-masked]>
Date: Mon, 17 Mar 2008 13:05:54 -0000

This mislaid feedback is still valid, and highlights the same point that
Cyrus just raised with proposed text for a fix.

----- Original Message ----- 
From: "Nigel Swinson" <[email-masked]>
To: <[email-masked]>
Sent: Friday, February 08, 2008 4:14 PM
Subject: Re: [Ietf-calsify] I-D ACTION:draft-ietf-calsify-rfc2445bis-08.txt

> 3.  iCalendar Object Specification
>
>    Section 3.1. defines the content line format; Section 3.2. defines
>    the property parameter format; Section 3.3. defines the data types
>    for property values; Section 3.4. defines the iCalendar object
>    format; Section 3.5. defines the iCalendar property format; Section
>    3.6. defines the calendar component format; Section 3.7. defines
> -   calendar properties; and Sectiopn 3.8. defines calendar component
> +  calendar properties; and Section 3.8. defines calendar component
>    properties.
>
> 3.3.10.  Recurrence Rule
>
>       represents the last Monday of the month.  The numeric value in a
>       BYDAY rule part with the FREQ rule part set to YEARLY corresponds
>       to an offset within the month when the BYMONTH rule part is
>       present, and corresponds to an offset within the year when the
>       BYWEEKNO or BYMONTH rule parts are present.  If an integer
>      modifier is not present, it means all days of this type within the
>
> ie:
>
> The numeric value in a BYDAY rule part with the FREQ rule part set to
YEARLY
> corresponds to:
> - an offset within the month
> ---when the BYMONTH rule part is present,
> - and corresponds to an offset within the year
> -- when the BYWEEKNO **or** BYMONTH rule parts are present.
>
> So if BYMONTH is present, does that mean the offset is within a year or a
> month?  Both options match.
>
> I still think it's an non intuative shame that
> FREQ=YEARLY;BYDAY=3MO;BYMONTH=11 means the 3rd Monday in November rather
> than the 3rd Monday of the year when it falls in November, so I think it
has
> to be:
>
>       represents the last Monday of the month.  The numeric value in a
>       BYDAY rule part with the FREQ rule part set to YEARLY corresponds
>       to an offset within the month when the BYMONTH rule part is
> -      present, and corresponds to an offset within the year when the
> -      BYWEEKNO or BYMONTH rule parts are present.  If an integer
> +      present, and corresponds to an offset within the year otherwise.
> +      If an integer
>       modifier is not present, it means all days of this type within the
>
> Then a trivial one:
>
>       The BYSETPOS rule part specifies a COMMA character (US-ASCII
>       decimal 44) separated list of values which corresponds to the nth
>       occurrence within the set of recurrence instances specified by the
>       rule.  BYSETPOS operates on a set of recurrence instances in one
>       interval of the recurrence rule.  For example, in a WEEKLY rule,
> -      the interval would be one week A set of recurrence instances
> +     the interval would be one week.  A set of recurrence instances
>       starts at the beginning of the interval defined by the FREQ rule
>       part.  Valid values are 1 to 366 or -366 to -1.  It MUST only be
>       used in conjunction with another BYxxx rule part.  For example
>       "the last work day of the month" could be represented as:
>
> Cheers
>
> Nigel
>

_______________________________________________
Ietf-calsify mailing list
[email-masked]
http://lists.osafoundation.org/mailman/listinfo/ietf-calsify

---

From: Reinhold Kainhofer <[email-masked]>
Date: Mon, 17 Mar 2008 14:12:12 +0100

> > than the 3rd Monday of the year when it falls in November, so I think it

I think it should mean the 3rd monday in November. This becomes clear when you 
think of BYDAY in the same way as BYSETPOSITION:

1) Apply yearly, so all days in a year match
2) Apply BYMONTH, so only all dates in november match
3) Apply BYDAY, meaning the 3rd monday in the set of currently matching dates 
(which are just the days in november).
4) Apply all BYHOUR/BYMINUTE/BYSECOND (not present)
5) Take all missing information (i.e. time) from the DTSTART

RFC 2445 makes it clear that the recurrence evaluation works on the list of 
matching date/times and limits or extends it step by step.

That's the general algorithm as I understand it. The new elaboration in the  
RFC simply explains this in a different way.

Cheers,
Reinhold

- -- 
- ------------------------------------------------------------------
Reinhold Kainhofer, Vienna University of Technology, Austria
email: [email-masked], http://reinhold.kainhofer.com/
 * Financial and Actuarial Mathematics, TU Wien, http://www.fam.tuwien.ac.at/
 * K Desktop Environment, http://www.kde.org, KOrganizer maintainer
 * Chorvereinigung "Jung-Wien", http://www.jung-wien.at/
_______________________________________________
Ietf-calsify mailing list
[email-masked]
http://lists.osafoundation.org/mailman/listinfo/ietf-calsify

---

From: "Nigel Swinson" <[email-masked]>
Date: Mon, 17 Mar 2008 13:44:18 -0000

> think of BYDAY in the same way as BYSETPOSITION:

Looking back, I think I meant to illustrate my complaint with:

FREQ=YEARLY;BYDAY=MO;BYSETPOS=3;BYMONTH=11

But I think it's the same issue.

> 5) Take all missing information (i.e. time) from the DTSTART

It's step 3 where the intuative step breaks down for me.  There's the
establishing of the set, and the filtering the set.  The only thing the
defines the set is the FREQ component.  The BYXX components filter the set.
See what was defined for BYSETPOS WRT to sets:

      The BYSETPOS rule part specifies a COMMA character (US-ASCII
      decimal 44) separated list of values which corresponds to the nth
      occurrence within the set of recurrence instances specified by the
*      rule.  BYSETPOS operates on a set of recurrence instances in one
*      interval of the recurrence rule.  For example, in a WEEKLY rule,
*      the interval would be one week A set of recurrence instances
*      starts at the beginning of the interval defined by the FREQ rule
      part.  Valid values are 1 to 366 or -366 to -1.  It MUST only be
      used in conjunction with another BYxxx rule part.  For example
      "the last work day of the month" could be represented as:

It could just have easily said "For example, in a YEARLY rule, the interval
would be one year.  A set of recurrence intstances starts at the beginning
of the interval defined by the FREQ rule part."  ie at the start of the
year, irrespective of any BYXX parts.

Or with the BYDAY text:

      Each BYDAY value can also be preceded by a positive (+n) or
      negative (-n) integer.  If present, this indicates the nth
      occurrence of a specific day within the MONTHLY or YEARLY "RRULE".
*      For example, within a MONTHLY rule, +1MO (or simply 1MO)
*      represents the first Monday within the month, whereas -1MO
*      represents the last Monday of the month.  The numeric value in a

It could just have easily said "For example, within a YEARLY rule, +1MO (or
simply 1MO) represents the first Monday within the year, whereas -1MO
represents the last Monday of the year.".  But then it doesn't say that,
instead it goes on to illustrate the special case:

Which of course equally doesn't make sense, see the thread Cyrus just
started ;o)

I'd have liked 3MO to be a short hand for BYDAY=MO, BYSETPOS = 3, in which
case either with a yearly rule would always be the 3rd instance of Monday
WRT to the start of the year.

I appreciate we can't really change this anyway, as many TZ decls make use
of this special case, including some in the standard itself
(RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=-1SU;UNTIL=19730429T070000Z), so I'm not
lobbying we do so, I'm just stating that I think it's a shame, and it
results in special cases in an already complicated area of the standard.

Nigel

---

From: Reinhold Kainhofer <[email-masked]>
Date: Mon, 17 Mar 2008 15:08:03 +0100

Am Montag, 17. März 2008 schrieben Sie:
> > 3) Apply BYDAY, meaning the 3rd monday in the set of currently matching
> > dates (which are just the days in november).
> defines the set is the FREQ component.  

No, each BY* limits/expands the current set; the set is defined by FREQ and 
all BY* parts. Let's look at the set for 2008:

1) FREQ=YEARLY, set=(Jan1, Jan2, .... Dec31)
2) Filter the set from 1) with BYMONTH, new set=(Nov1, ... Nov30)
3) BYWEEKNO not present, set stays the same
4) BYYEARDAY not present, set stays the same
5) BYMONTHDAY not present, set stays the same
6) Filter the set from 5) with BYDAY=3MO (i.e. the third monday in the 
currently created set), new set=(Nov17)
That's where the order of evaluation is relevant!
7) BYHOUR not present, set stays the same
8) BYMINUTE not present, set stays the same
9) BYSECOND not present, set stays the same
10) BYSETPOS not present, set stays the same (that's the other place where the 
order of the BY* evaluations is relevant)
11) missing data is taken from the DTSTART (i.e. the time in our case)
11) Apply COUNT and UNTIL (not present), set stays the same (Nov17)

So we end up with one recurrence in 2008, namely November 17, 2008, same time 
as DTSTART.

This way, evaluating arbitrarily complex recurrence rules is just as simple as 
trivial rules.

> WRT to the start of the year.

Huh??? BYSETPOS works on the final set after all other BY* rules have been 
applied. 

If you have FREQ=YEARLY;BYMONTH=3,6,9; BYMONTHDAY=1; BYSETPOS=2, then you'll 
get June 1 (At least that was the case with RFC 2445 with the original 
recurrence rule algorithm, no idea if the reformulation in calsify have 
messed this up, though).

Cheers,
Reinhold

- --

---

From: Cyrus Daboo <[email-masked]>
Date: Mon, 17 Mar 2008 11:50:28 -0400

Hi Reinhold,

--On March 17, 2008 3:08:03 PM +0100 Reinhold Kainhofer 
<[email-masked]> wrote:

> No, each BY* limits/expands the current set; the set is defined by FREQ
> and  all BY* parts. Let's look at the set for 2008:
>
> 10) BYSETPOS not present, set stays the same (that's the other place
> where the  order of the BY* evaluations is relevant)

I don't understand how this works! What if there was no BYMONTH and no 
BYDAY. Then as per step (1), a yearly rule would result in an occurrence on 
every day of the year! That is clearly wrong. Same problem for YEARLY with 
BYMONTH and no BYDAY - according to your steps that would be every day in 
November - again wrong.

So I think your steps above only work in the specific case you give.

I view the recurrence expansion in the opposite way to your steps above. I 
would start with the "seed" being DTSTART. Then apply each BYxxx that is 
present in turn operating on the set from the previous operation.

Its hard to explain that in text or even pseudo-code. The table was an 
attempt to do so but I think it falls slight short in the BYDAY area. 
Perhaps the best thing I can do is point to the code I did write. I am not 
claiming this is perfect or the only way to look at this, its just the way 
that seemed to work for me. So:

<http://trac.mulberrymail.com/repos/browser/PyCalendar/trunk/src/pycalendar/recurrence.py>

The generateXXXSet methods there correspond to each column (FREQ values) in 
the table. Within each generateXXXSet method are conditionals for each 
BYxxx part corrsponding to the rows in the table. For each BYxxx part there 
is a byXXXExpand and byXXXLimit method that applies the appropriate logic 
to a set of date-times passed in, and returns the modified set. The key 
thing to note is that there are three BYDAY methods byDayExpandYearly, 
byDayExpandMonthly and byDayExpandWeeky that are used to special case BYDAY.

So looking at generateYearlySet, we have:

    if BYYEARDAY or BYMONTHDAY are present:
        use byDayLimit

    else if BYWEEKNO present:
        use byDayExpandWeekly

    else if BYMONTH present:
        use byDayExpandMonthly

    else:
        use byDayExpandYearly

There is similar logic in generateMonthlySet for BYDAY.

This "seed with DTSTART, then Expand/Limit successive sets" approach looks 
like it covers all cases.

So given the above, I think the two notes currently in the 2445bis table 
should be changed to be more specific about what it means to have a 
"special expand":

Note 1: Limit if BYMONTHDAY is present,
        otherwise expand days within each month only.

Note 2: Limit if BYYEARDAY or BYMONTHDAY is present,
        otherwise if BYWEEKNO is present expands days within each week only,
        otherwise if BYMONTH is present expand days within each month only,
        otherwise expand days throughout the year.

-- 
Cyrus Daboo

---

From: "Nigel Swinson" <[email-masked]>
Date: Mon, 17 Mar 2008 16:22:10 -0000

> Huh??? BYSETPOS works on the final set after all other BY* rules have been

I guess this is getting close to the point I was trying to make, and not 
making a very good job of it, sorry.  I agree 3MO should not be the same as 
BYDAY=MO;BYSETPOS=3 as I understand that BYSETPOS is the last of the BYXX 
parts to be evaluated, and operates on the collection bound by the sets 
specified by the FREQ part, but filtered by the previous BYXX rules.  But in 
saying that, 3MO does not mean "3rd monday in the set", that's what BYSETPOS 
is for, or else it's referring to a different "set", so what does 3MO mean? 
What I'm trying to say is that I think it would have been better if 3MO had 
meant, regardless of BYXX rules:

weekly/day/hour/second:
- 3rd monday of the week/day/hour/second, irrelevant, hence the standard 
dissalows.
freq=monthly
- 3rd monday of the month
freq=yearly
- 3rd monday of the year

I think the standard is difficult to interpret WRT to a rule such as: 
RRULE:FREQ=YEARLY;BYMONTH=2,4;BYDAY=3MO;  If we follow your steps, which I 
agree are appropriate and correct, then when we get to #5 does the 3MO mean 
we include Mondays for Feb and Apr, or just Apr?
- We have to read the special case to realise it's Feb and Apr, not just 
Apr.
- BYSETPOS=3 would be clear, it would be just Feb, which we'd select at step 
10.
- Equally if we wrote the rule as a MONTHLY rule rather than a YEARLY rule, 
then it would be fairly easy to interpret as Mondays in Feb and Apr.

It's the combination of the 3MO with YEARLY+BYMONTHLY that I think requires 
unhelpful special casing :o(

Lets try one more way to explain my point.  The standard says:

      The numeric value in a
      BYDAY rule part with the FREQ rule part set to YEARLY corresponds
      to an offset within the month when the BYMONTH rule part is
      present, and corresponds to an offset within the year when the
      BYWEEKNO or BYMONTH rule parts are present.

Surely it would have been clearer to write, easier to implement, and produce 
better interoperability to reduce the number of clauses to:

      The numeric value in a
      BYDAY rule part with the FREQ rule part set to YEARLY corresponds
      to an offset within the year.

But again, I'm not expecting anything to change in the standard, I think it 
would break too much code that's out there :o(

Nigel

---

From: Jonathan Lennox <[email-masked]>
Date: Mon, 17 Mar 2008 12:36:25 -0400

> would break too much code that's out there :o(

I believe this was the original intent of 2445.  However, 2445's example
VTIMEZONE (on page 66) contains an RRULE with
FREQ=YEARLY;BYDAY=1SU;BYMONTH=4 meaning "the first Sunday in April", and the
spec was unclear enough that people implemented following the example
instead.  Thus the somewhat odd behavior described by 2445bis, which is
intended to describe existing practice.

-- 
Jonathan Lennox
lennox at cs dot columbia dot edu

---

From: Reinhold Kainhofer <[email-masked]>
Date: Mon, 17 Mar 2008 22:18:01 +0100

Am Montag, 17. März 2008 schrieben Sie:
> > Surely it would have been clearer to write, easier to implement, and
> > produce better interoperability to reduce the number of clauses to:
> >
> >       The numeric value in a
> > But again, I'm not expecting anything to change in the standard, I think
> > it would break too much code that's out there :o(
>
> I believe this was the original intent of 2445.

Really? Given that **all** VTIMEZONES I have seen (even those in the RFC!) use 
YEARLY together with BYDAY and BYMONTH, I find this hard to believe... Even 
the implementations from Lotus and Microsoft (the first draft of RFC 2445 
came from Microsoft (!!) while reimplementing Outlook/OE and was merged with 
the Versit vCalendar draft, see 
http://www.imc.org/ietf-calendar/archive1/msg00192.html) use this, and the 
two editors of RFC 2445 were from Lotus and Micosoft, so I doubt that this 
was just a collective error made simultaneously by all implementations at 
that time...

Anyway, I took a look at the ietf-calendar archives from 1996-1999 when RFC 
2445 was written and discussed and there are some quite interesting postings 
by the RFC authors, some of which contradict what was "clarified"  in 
calsify:

Apparently, RDATE befor the DTSTART were not meant to be allowed:
http://www.imc.org/ietf-calendar/archive1/msg02220.html

About the order of the BY* rule parts (clearly indicating the step-by-step 
application):
http://www.imc.org/ietf-calendar/archive1/msg02221.html

That the DTSTART does not have to be part of the RRULE (e.g. an event 
recurring every monday can have a DTSTART on Tuesday; Also compare the 
example on page 120 of the original RFC 120; Notice that Frank is the editor 
of RFC 2445 and Vinod worked for Lotus, where the other editor worked, too):
http://www.imc.org/ietf-calendar/archive1/msg02224.html
http://www.imc.org/ietf-calendar/archive1/msg02230.html
(Tread started at http://www.imc.org/ietf-calendar/archive1/msg02197.html)
Also: http://www.imc.org/ietf-calendar/archive1/msg01429.html

Unfortunately, none of the postings from 1996 to 1999 explain in more detail 
how the RRULE is supposed to be evaluated exactly :(
And apparently the archives of the old (pre-1996) mailing list from cst.ca are 
not available any more...

Cheers,
Reinhold
- --