Subject: [calsify] SKIP was Re: AD review of draft-ietf-calext-rscale-03

From: Cyrus Daboo <[email-masked]>
Date: Mon, 02 Feb 2015 22:33:13 -0500

Hi,
(Dealing with Barry's AD review issues #2 and #8 in a separate thread)

OK, so I think you have identified a legitimate issue with SKIP. I would 
like to clarify the skip behavior as described below. I will propose 
concrete changes to the draft once we have agreed on the basic concepts.

When a recurrence generates an invalid date, the following applies when 
SKIP is set to FORWARD or BACKWARD:

1) If the invalid date was generated from a rule starting on a leap day or 
a leap month: the SKIP value for forward/backward is then a day or a month, 
respectively.

2) If the invalid date was generated from a rule starting on a day-of-month 
not valid in the current month: the SKIP value for forward/backward is to 
the nearest valid day.

3) If the invalid date was generated from a rule with a BYMONTHDAY that 
results in a day-of-month not valid in the current month: the SKIP value 
for forward/backward is to the nearest valid day.

Note that the above "rules" for SKIP are independent of the actual RSCALE 
value, which I believe is the correct approach (because otherwise we would 
need some kind of registry or an indicator from ICU as to what the behavior 
should be for each calendar scale).

Can other RRULE experts please review the above and make sure those three 
descriptions are valid?

-- 
Cyrus Daboo

---

From: Barry Leiba <[email-masked]>
Date: Mon, 2 Feb 2015 22:41:18 -0500

I think those descriptions are clear, and they look correct and complete to
me.  I'd be happy with them if the working group agrees.

But let me present an alternative formulation:

1. If the date is invalid because the month is not a valid month in the
currect year, the SKIP is to the next (forward) or previous (backward)
valid month.

2. Otherwise, the SKIP is to the next (forward) or previous (backward)
valid day.

I think that covers the situation.  If you think you need to explain the
different "day" situations further, which is never a bad thing, that can be
added as explanatory text.  Yes/no?

Barry

On Monday, February 2, 2015, Cyrus Daboo <[email-masked]> wrote:

> 2) If the invalid date was generated from a rule starting on a
> day-of-month not valid in the current month: the SKIP value for
> forward/backward is to the nearest valid day.
>

---

From: Cyrus Daboo <[email-masked]>
Date: Mon, 02 Feb 2015 23:10:14 -0500

Hi Barry,

--On February 2, 2015 at 10:41:18 PM -0500 Barry Leiba 
<[email-masked]> wrote:

> I think those descriptions are clear, and they look correct and complete
> to me.  I'd be happy with them if the working group agrees.
>
> different "day" situations further, which is never a bad thing, that can
> be added as explanatory text.  Yes/no?

That might be sufficient, but with one further complication that just 
occurred to me. For the case of a leap month, what happens if the 
day-of-month value in the skipped to non-leap month is now not valid for 
that month? e.g., leap month has 30 days, following month only has 29 days. 
Do we then also apply the forward/backward nearest valid day skip to the 
resulting invalid date too? I think we have to state that as well. So with 
your rules, #2 is not an "otherwise". So perhaps this:

1. If the date is invalid because the month is not a valid month in the
correct year, the SKIP is to the next (forward) or previous (backward)
valid month. Use the resulting date for the next test.

2. If the date is invalid because the day-of-month is not valid for that 
month, the SKIP is to the next (forward) or previous (backward) valid day.

-- 
Cyrus Daboo

---

From: Barry Leiba <[email-masked]>
Date: Mon, 2 Feb 2015 23:12:14 -0500

Yes... I thought about that as I was sending the last message, but then
figured that never happens.  But maybe it can.  I think your version
here does cover it.

b

On Monday, February 2, 2015, Cyrus Daboo <[email-masked]> wrote:

> Hi Barry,
>
> --On February 2, 2015 at 10:41:18 PM -0500 Barry Leiba <
> [email-masked]> wrote:
>

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 09:51:01 -0500

Hi Barry,

> figured that never happens.  But maybe it can.  I think your version

Actually I have thought some more about it too and come to a slightly 
different conclusion. I think when a SKIP=FORWARD is used with a leap 
month, the correct behavior, if the resulting date is invalid, is to keep 
the (valid) month fixed, and instead change the date to the last day of 
that month (in effect a SKIP=BACKWARD for the invalid date). I think that 
makes sense because if my birthday was the last day of a leap month I would 
probably want to celebrate on the last day of the next month, not the first 
day of the month after that. Similarly, if SKIP=BACKWARD is used with a 
leap month, then SKIP=BACKWARD should also be applied to any invalid date 
that results - the same argument for SKIP=FORWARD being relevant.

So I now have this:

1. If the date is invalid because the month is not a valid month in the
correct year, the SKIP is to the next (forward) or previous (backward)
valid month. If the resulting date is invalid (the day-of-month exceeds the 
number of days in the specified month) then adjust the day-of-month to the 
last (valid) value for that month.

2. Otherwise, if the date is invalid because the day-of-month is not valid 
for that month, the SKIP is to the next (forward) or previous (backward) 
valid day.

-- 
Cyrus Daboo

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 10:02:01 -0500

Hi Cyrus,

On 02/03/2015 09:51 AM, Cyrus Daboo wrote:
> month, the correct behavior, if the resulting date is invalid, is to 
> keep the (valid) month fixed, and instead change the date to the last 
> day of that month (in effect a SKIP=BACKWARD for the invalid date). I 
> think that makes sense because if my birthday was the last day of a 
> leap month I would probably want to celebrate on the last day of the 
> next month, not the first day of the month after that. Similarly, if 
> SKIP=BACKWARD is used with a leap month, then SKIP=BACKWARD should 
> also be applied to any invalid date that results - the same argument 
> for SKIP=FORWARD being relevant.
>
> So I now have this:
>
> valid month. If the resulting date is invalid (the day-of-month 
> exceeds the number of days in the specified month) then adjust the 
> day-of-month to the last (valid) value for that month.
>
> 2. Otherwise, if the date is invalid because the day-of-month is not 
> valid for that month, the SKIP is to the next (forward) or previous 
> (backward) valid day.

I was also thinking about birthdays and doing some research.  For the 
case of birthdays on the Hebrew calendar, if we can trust Wikipedia 
<http://en.wikipedia.org/wiki/Adar>, its fairly complex:

"Based on a line in the Mishnah <http://en.wikipedia.org/wiki/Mishnah> 
declaring that Purim must be celebrated in Adar II in a leap year 
(Megillah <http://en.wikipedia.org/wiki/Tractate_Megillah> 1:4), Adar I 
is considered the "extra" month. As a result, someone born in Adar 
during a non leap year would celebrate his birthday in Adar II during a 
leap year. However, someone born during either Adar in a leap year will 
celebrate his birthday during Adar in a non-leap year, except that 
someone born on 30 Adar I will celebrate his birthday on 1 Nisan in a 
non-leap year because Adar in a non-leap year has only 29 days.^[1] 
<http://en.wikipedia.org/wiki/Adar#cite_note-1> "

It appears your previous rules properly handle the 30 Adar I (leap year) 
case, but the new rules do not.  Can we come up with rules that can 
model the 3 cases listed above?

I'm doing some more digging on this and probably need to look at what 
the Chinese do to celebrate birthdates in leap years as well.

Do we have any i8ln experts in the IETF that we can lean on for this stuff?

-- 
Kenneth Murchison
Principal Systems Software Engineer
Carnegie Mellon University

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 10:08:12 -0500

Hi Ken,

--On February 3, 2015 at 10:02:01 AM -0500 Ken Murchison 
<[email-masked]> wrote:

> case, but the new rules do not.  Can we come up with rules that can model
> the 3 cases listed above?

OK thanks for looking into that. If we want to provide full flexibility to 
control what happens we would need to have two "skip" indicators, one for 
skipping invalid months and one for skipping invalid days (with the month 
one applied first, followed by the day one). So:

RRULE:FREQ=YEARLY;SKIP-MONTH=FORWARD;SKIP-DAY=FORWARD

Would match the Hebrew birthday case you found.

RRULE:FREQ=YEARLY;SKIP-MONTH=FORWARD;SKIP-DAY=BACKWARD

Would match the behavior from my last email. If we find there really is 
never a use case for the above, then we could stick with the single SKIP 
option. But lets see if we can get a confirmation on that.

-- 
Cyrus Daboo

---

From: Barry Leiba <[email-masked]>
Date: Tue, 3 Feb 2015 10:11:45 -0500

> for that month, the SKIP is to the next (forward) or previous (backward)

I think you want "current year", rather than "correct year", no?
Otherwise, this (and your reasoning) seems good.

b

---

From: Barry Leiba <[email-masked]>
Date: Tue, 3 Feb 2015 10:18:27 -0500

Yes, so this is starting to show the complexity of trying to have
general rules that one can apply, rather than "just knowing" how each
calendar works -- that is, saying that the behaviour is specific to
each calendar, and you have to know, when you implement a calendar,
how that calendar works.

In fact, you do: you have to know it in order to know how to generate
the correct SKIP entries.  So why don't we just say that you have to
know it on both ends, and in most cases SKIP won't be used (it's only
to make exceptions from the normal case)?

Maybe that means we should have a registry for calendars and their
SKIP behaviour, where we could put in at least the common calendars we
expect to see used -- there can't be that many.  Or... or maybe we
just say that if you're going to support a calendar, you have to do
the research and know how that calendar works in practice.

Does that latter mean that we might get bad implementations that don't
do it right?  Sure.  But with SKIP as we're doing it, we also might
get bad implementation that don't generate the SKIP(s) right.

Barry

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 12:38:52 -0500

On 02/03/2015 10:08 AM, Cyrus Daboo wrote:
> OK thanks for looking into that. If we want to provide full 
> flexibility to control what happens we would need to have two "skip" 
> indicators, one for skipping invalid months and one for skipping 
> invalid days (with the month one applied first, followed by the day 
> one). So:
>
> Would match the behavior from my last email. If we find there really 
> is never a use case for the above, then we could stick with the single 
> SKIP option. But lets see if we can get a confirmation on that.
>

Cyrus,

I believe we can get by with just a single SKIP and your previous rules 
to handle both cases above (using Hebrew leap month):

RRULE:FREQ=YEARLY;RSCALE=HEBREW;SKIP=FORWARD;BYMONTH=5L;BYMONTHDAY=30

Would yield 1 Nisan (skipping forward both a month and day)

RRULE:FREQ=YEARLY;RSCALE=HEBREW;SKIP=FORWARD;BYMONTH=5L;BYMONTHDAY=-1

Would yield 29 Adar (skipping forward just a month)

For the BACKWARD cases, both BYMONTHDAY=30 and BYMONTHDAY=-1 would yield 
Shevat 30.

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 12:51:43 -0500

Hi Ken,

> Would yield 29 Adar (skipping forward just a month)

Actually I am not convinced about that since the spec says that SKIP is 
applied AFTER all other rule parts are processed (except for BYSETPOS, 
COUNT and UNTIL). So the BYMONTHDAY=-1 refers to the last day of the 
invalid month, 30 Adar I, which then becomes the invalid date 30 Adar after 
the month skip and then 1 Nisan after the day skip.

-- 
Cyrus Daboo

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 12:53:22 -0500

On 02/03/2015 12:38 PM, Ken Murchison wrote:
>> is never a use case for the above, then we could stick with the 
>> single SKIP option. But lets see if we can get a confirmation on that.
>>
>
> Cyrus,
>
> I believe we can get by with just a single SKIP and your previous 
> rules to handle both cases above (using Hebrew leap month):
>
> For the BACKWARD cases, both BYMONTHDAY=30 and BYMONTHDAY=-1 would 
> yield Shevat 30.
>

And it turns out that the BACKWARD case works for celebrating birthdays 
in the Chinese calendar, based on the following in Wikipedia 
<http://en.wikipedia.org/wiki/Chinese_calendar#Age_recognition_in_China>:

"The birthday is the day in each year that have the same date as the one 
on which someone was born. It's easy to confirm the birthday in the 
Chinese calendar for most people. But, if someone was born on the 30_th 
of a month, his birthday is the last day of that month, and if someone 
is born in an intercalary month, his birthday is the day with the same 
date in the common month of the intercalary month."

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 12:58:40 -0500

On 02/03/2015 12:51 PM, Cyrus Daboo wrote:
> Actually I am not convinced about that since the spec says that SKIP 
> is applied AFTER all other rule parts are processed (except for 
> BYSETPOS, COUNT and UNTIL). So the BYMONTHDAY=-1 refers to the last 
> day of the invalid month, 30 Adar I, which then becomes the invalid 
> date 30 Adar after the month skip and then 1 Nisan after the day skip.

Hmm, I think you're right based on the current wording.  I don't recall 
exactly how we decided on that wording, but perhaps it might needs to be 
adjusted.

Other than violating the current wording in the spec, does my logic 
appear to be sane?

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 13:12:34 -0500

Hi Ken, Barry,

--On February 3, 2015 at 12:51:43 PM -0500 Cyrus Daboo <[email-masked]> 
wrote:

> invalid month, 30 Adar I, which then becomes the invalid date 30 Adar
> after the month skip and then 1 Nisan after the day skip.

I think the following would work:

RRULE:FREQ=YEARLY;RSCALE=HEBREW;SKIP=FORWARD;BYMONTH=5L,6;BYMONTHDAY=-1;BYSETPOS=1

In a leap year that would generate the last day of 5L and 6 and BYSETPOS 
would select 5L.

In a non-leap year that would generate the first day of 7 (the skip forward 
by month and by day) and the last day of 6, so BYSETPOS would select the 
last day of 6.

These complex rules would all be great things to include in an RSCALE test 
suite.

Of course all this just goes to prove Barry's point about trying to come up 
with a simple behavior that can be easily codified without having to write 
such complex RRULEs. But I would still prefer something that can be clearly 
represented in the rule and has a fixed default per calendar (with perhaps 
a BCP - or appendix in the current draft - that describes how common 
situations are handled: Hebrew calendar birthdays, Chinese calendar 
birthdays, other...).

-- 
Cyrus Daboo

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 13:13:47 -0500

On 02/03/2015 12:58 PM, Ken Murchison wrote:
> Hmm, I think you're right based on the current wording.  I don't 
> recall exactly how we decided on that wording, but perhaps it might 
> needs to be adjusted.

Looking at RFC 5545:

       If multiple BYxxx rule parts are specified, then after evaluating
       the specified FREQ and INTERVAL rule parts, the BYxxx rule parts
       are applied to the current set of evaluated occurrences in the
       following order: BYMONTH, BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY,
       BYHOUR, BYMINUTE, BYSECOND and BYSETPOS; then COUNT and UNTIL are
       evaluated.

I'm wondering if we shouldn't have SKIP applied both immediately 
following BYMONTH and BYMONTHDAY evaluation.  I don't think we want the 
other BYxxx rule parts to be operating on invalid dates at any point.  
Thoughts?

---

From: Marten Gajda <[email-masked]>
Date: Tue, 03 Feb 2015 21:08:12 +0100

@Ken: Sorry for the double post, I hit the wrong reply button

Am 03.02.2015 um 19:13 schrieb Ken Murchison:
>>>> rules
> following BYMONTH and BYMONTHDAY evaluation.  I don't think we want 
> the other BYxxx rule parts to be operating on invalid dates at any 
> point.  Thoughts?
>
The only reason I can come up with right now, is that a rule with RSCALE 
& SKIP=OMIT could have different results than the same rule without 
RSCALE and SKIP.

example:

DTSTART;VALUE=DATE:20120229
RRULE:FREQ=YEARLY;BYMONTH=2;BYDAY=SU

-> all Sundays in February, every year

DTSTART;VALUE=DATE:20120229
RRULE:FREQ=YEARLY;RSCALE=GREGORIAN;BYMONTH=2;BYDAY=SU;SKIP=OMIT

-> all Sundays in February, but only in leap years, since SKIP would 
filter Feb. 29th in non-leap years before BYDAY is evaluated

Marten

-- 

*Marten Gajda*
Schandauer Straße 34
01309 Dresden
Germany

tel: +49 177 4427167
email: [email-masked]
twitter: twitter.com/dmfs_org

VAT Reg. No.: DE269072391

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 15:23:13 -0500

On 02/03/2015 03:08 PM, Marten Gajda wrote:
>>>> Actually I am not convinced about that since the spec says that 
>>>> SKIP is applied AFTER all other rule parts are processed (except 
>>>> for BYSETPOS, COUNT and UNTIL). So the BYMONTHDAY=-1 refers to the 
>>>> last day of the invalid month, 30 Adar I, which then becomes the 
>>>> invalid date 30 Adar after the month skip and then 1 Nisan after 
>>>> the day skip.
>>>
> The only reason I can come up with right now, is that a rule with 
> RSCALE & SKIP=OMIT could have different results than the same rule 
> without RSCALE and SKIP.
>
> example:
>

I think both of these come out the same (and my libical computes the 
same) as there is no BYMONTHDAY or anything else forcing the expansion 
onto Feb 29 in a non-leap year.  In this case the DTSTART just gives us 
the first instance (which in this case doesn't fall on a Sunday so isn't 
included).  After that, the BYMONTH+BYDAY is what really drives the 
expansion.

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 15:48:45 -0500

Hi Ken,

> included).  After that, the BYMONTH+BYDAY is what really drives the

But if we use 20140229 as the DTSTART - and that is a leap day on a Sunday 
- then I think Marten is write that apply the SKIP after the BYMONTH and 
before the BYDAY would result in only Sundays in leap years being returned.

I think having those two rules return different results would be 
counterintuitive so I would prefer we left the order of BYxxx element and 
SKIP processing as it is now.

-- 
Cyrus Daboo

---

From: Ken Murchison <[email-masked]>
Date: Tue, 03 Feb 2015 15:57:23 -0500

On 02/03/2015 03:48 PM, Cyrus Daboo wrote:
> But if we use 20140229 as the DTSTART - and that is a leap day on a 
> Sunday - then I think Marten is write that apply the SKIP after the 
> BYMONTH and before the BYDAY would result in only Sundays in leap 
> years being returned.
>
> counterintuitive so I would prefer we left the order of BYxxx element 
> and SKIP processing as it is now.

What I was thinking, and probably wasn't clear, is that we apply SKIP to 
the month after BYMONTH and apply SKIP to the day after BYMONTHDAY/BYDAY.

I don't think we want any of the down stream rule parts to be operating 
on a bogus month.

---

From: Marten Gajda <[email-masked]>
Date: Tue, 03 Feb 2015 21:58:55 +0100

> and SKIP processing as it is now.
you meant 20040229, right?

The point is, that evaluating SKIP=OMIT after BYMONTH=2 would remove Feb 
29th in non-leap years and there would be nothing left for BYDAY to expand.

I'd also prefer having SKIP=OMIT behave like a rule without RSCALE.

-- 

*Marten Gajda*
Schandauer Straße 34
01309 Dresden
Germany

tel: +49 177 4427167
email: [email-masked]

---

From: Cyrus Daboo <[email-masked]>
Date: Tue, 03 Feb 2015 16:04:15 -0500

Hi Marten,

> you meant 20040229, right?

Yes!

> I'd also prefer having SKIP=OMIT behave like a rule without RSCALE.

I think Ken's idea is that you apply the SKIP after BYMONTH only if the 
invalid data corresponds to an invalid leap month as opposed to a leap day. 
In which case the SKIP would not have applied after BYMONTH in your 
example. But I think a behavior like that is going to be really tricky for 
implementors to get right and hard to describe really well without having 
to delve into the gory details of RRULE processing.

-- 
Cyrus Daboo

---

From: Marten Gajda <[email-masked]>
Date: Tue, 03 Feb 2015 22:50:01 +0100

Am 03.02.2015 um 22:04 schrieb Cyrus Daboo:
> I think Ken's idea is that you apply the SKIP after BYMONTH only if 
> the invalid data corresponds to an invalid leap month as opposed to a 
> leap day. In which case the SKIP would not have applied after BYMONTH 
> in your example. But I think a behavior like that is going to be 
> really tricky for implementors to get right and hard to describe 
> really well without having to delve into the gory details of RRULE 
> processing.
>
Ah, got it.

So, considering the following

Applying SKIP=FORWARD after BYDAY on the following rule

FREQ=YEARLY;RSCALE=HEBREW;MONTHLY=5L;BYDAY=MO,TU,WE,TH,FR,SA,SU;SKIP=FORWARD

results in 30 instances in leap years and in non-leap years, since it 
would expand the week days in Adar I and roll them forward afterwards

Applying SKIP=FORWARD after BYMONTH but before BYDAY results in 30 
instances in leap years, but 29 instances in non-leap years, since the 
weekdays would be expanded for Adar instead of Adar I.

It's similar when the month following the leap month has more days than 
the leap month itself.

In essence, applying SKIP after all BYxxx parts won't change the number 
of instances (given they don't fall on another instance), but Ken's 
approach might do that.

Not sure what's preferable in this case.

-- 

*Marten Gajda*
Schandauer Straße 34
01309 Dresden
Germany

tel: +49 177 4427167
email: [email-masked]

---

From: Gregory Yakushev <[email-masked]>
Date: Wed, 04 Feb 2015 11:26:33 +0000

Quite a discussion here, let me try to catch up.

As for FREQ=YEARLY;RSCALE=HEBREW;MONTHLY=5L;BYDAY=MO,TU,WE,TH,FR,SA,SU;SKIP=FORWARD
case, its clearly artificial and doesn't represent any real-world usecase,
so there's no preference for our users on how to handle it.

As was cleared above, SKIP behavior is clear for all Calendars except
Hebrew, and for all except Hebrew people will use SKIP=BACKWARD for most
usecases.

It is important to clear the Hebrew case, but lets keep in mind this we are
talking about a very narrow usecase for a relatively small number of users.
It will be unfair to complicate life for billions of Chinese or Hindu users
to make Hebrew case perfectly right.

Do I understand correctly that current draft allows to specify an RRULE for
all Hebrew cases, even though it looks ugly for Adar I 30th?

Grisha

On Tue Feb 03 2015 at 10:50:15 PM Marten Gajda <[email-masked]> wrote:

> In essence, applying SKIP after all BYxxx parts won't change the number of
> instances (given they don't fall on another instance), but Ken's approach
> might do that.
>
>   _______________________________________________
> calsify mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/calsify
>

---

From: Marten Gajda <[email-masked]>
Date: Wed, 04 Feb 2015 14:17:04 +0100

Am 04.02.2015 um 12:26 schrieb Gregory Yakushev:
> As for 
> case, its clearly artificial and doesn't represent any real-world 
> usecase, so there's no preference for our users on how to handle it.
That's true, but it's probably easy to generate a real world example 
where the execution order of SKIP and BYxxx rules matters.

The question is, do we want BYDAY and BYMONTHDAY expansion to be 
executed on the days of the skipped leap month or on the days of the 
actual month?

The more I think about this, the more I like the idea to apply SKIP 
right after BYMONTH when skipping a leap month. When you expand BYDAY=SU 
for a leap month you probably want to expand all Sundays in the 
following (or preceding) month when the year is not a leap year. The 
number of Sundays you expand for the skipped month might be different 
from the number of Sundays in the next or previous month. Also when 
rolling a day backwards to the previous month, a Sunday would fall on a 
different weekday (unless the number of days in that month is a multiple 
of 7).

> Hebrew, and for all except Hebrew people will use SKIP=BACKWARD for 
> most usecases.
>
> It is important to clear the Hebrew case, but lets keep in mind this 
> we are talking about a very narrow usecase for a relatively small 
> number of users. It will be unfair to complicate life for billions of 
> Chinese or Hindu users to make Hebrew case perfectly right.
I think the user shouldn't notice any difference. It's the developers 
that have to get this right. Setting the default to SKIP=OMIT sounds 
like the best solution to me. It doesn't prefer any specific calendar 
and it doesn't change the semantics of existing rule when you add 
RSCALE=GREGORIAN but no SKIP.

Marten

>
> Do I understand correctly that current draft allows to specify an 
> RRULE for all Hebrew cases, even though it looks ugly for Adar I 30th?
>
> Grisha
>
>
> On Tue Feb 03 2015 at 10:50:15 PM Marten Gajda <[email-masked] 
> <mailto:[email-masked]>> wrote:
>
>
>>     I think Ken's idea is that you apply the SKIP after BYMONTH only
>>     if the invalid data corresponds to an invalid leap month as
>>     opposed to a leap day. In which case the SKIP would not have
>>     applied after BYMONTH in your example. But I think a behavior
>>     like that is going to be really tricky for implementors to get
>>     right and hard to describe really well without having to delve
>>     into the gory details of RRULE processing.
>>
>     Ah, got it.
>
>     results in 30 instances in leap years and in non-leap years, since
>     it would expand the week days in Adar I and roll them forward
>     afterwards
>
>     instances in leap years, but 29 instances in non-leap years, since
>     the weekdays would be expanded for Adar instead of Adar I.
>
>     It's similar when the month following the leap month has more days
>     than the leap month itself.
>
>     In essence, applying SKIP after all BYxxx parts won't change the
>     number of instances (given they don't fall on another instance),
>     but Ken's approach might do that.
>
>     email: [email-masked] <mailto:[email-masked]>
>     twitter: twitter.com/dmfs_org <http://twitter.com/dmfs_org>
>
>     [email-masked] <mailto:[email-masked]>

-- 
Marten Gajda
Schandauer Straße 34
01309 Dresden
Germany

tel: +49 177 4427167
email: [email-masked]

---

From: Ken Murchison <[email-masked]>
Date: Wed, 04 Feb 2015 08:20:34 -0500

On 02/03/2015 04:50 PM, Marten Gajda wrote:
> number of instances (given they don't fall on another instance), but 
> Ken's approach might do that.
>

I'd argue that what this rule is asking for is all days of the leap 
month, but in non-leap years provide all days of the next month, so 30 
and 29 are correct respectively.

I'd also argue that BYMONTHDAY=30/31 should have different results from 
BYMONTHDAY=-1, in the same way that it does for GREGORIAN:

RRULE:FREQ=MONTHLY;RSCALE=GREGORIAN;SKIP=FORWARD;COUNT=12;BYMONTHDAY=31
DTSTART:20150131
INSTANCES:20150131,20150301,20150331,20150501,20150531,20150701,20150731,20150831,20151001,20151031,20151201,20151231

RRULE:FREQ=MONTHLY;RSCALE=GREGORIAN;SKIP=FORWARD;COUNT=12;BYMONTHDAY=-1
DTSTART:20150131
INSTANCES:20150131,20150228,20150331,20150430,20150531,20150630,20150731,20150831,20150930,20151031,20151130,20151231

So, my proposal is to tweak the BYxxx rule part processing order in RFC 
5545, Section 3.3.10 by inserting SKIP processing in the following way:

BYMONTH
SKIP (for invalid month only)
BYWEEKNO
BYYEARDAY
BYMONTHDAY
SKIP (for invalid day)
BYDAY
BYHOUR
BYMINUTE
BYSECOND
BYSETPOS
COUNT
UNTIL

By main argument here is that BYWEEKNO, BYYEARDAY, BYMONTHDAY should 
apply to a "real" month in all cases, and not a leap month in non-leap 
years.

This leads to the following for the Hebrew calendar:

RRULE:FREQ=YEARLY;RSCALE=HEBREW;SKIP=FORWARD;COUNT=5;BYMONTHDAY=30;BYMONTH=5L
DTSTART:20140302
INSTANCES:20140302 (30 Adar I), 20150321 (1 Nisan), 20160310 (30 Adar 
I), 20170328 (1 Nisan), 20180317 (1 Nisan)

RRULE:FREQ=YEARLY;RSCALE=HEBREW;SKIP=FORWARD;COUNT=5;BYMONTHDAY=-1;BYMONTH=5L
DTSTART:20140302
INSTANCES:20140302 (30 Adar I), 20150320 (29 Adar), 20160310 (30 Adar 
I), 20170327 (29 Adar), 20180316 (29 Adar)

---

From: Marten Gajda <[email-masked]>
Date: Wed, 04 Feb 2015 14:55:28 +0100

+1 for Ken's proposal.

I couldn't find it in the latest draft (maybe I just didn't look close 
enough), but I think it should be pointed out that in this context 
"invalid day" refers to leap days only. I.e. SKIP=FORWARD doesn't apply 
to Feb 30 or similar dates.

Am 04.02.2015 um 14:20 schrieb Ken Murchison:
>>> the invalid data corresponds to an invalid leap month as opposed to 
>>> a leap day. In which case the SKIP would not have applied after 
>>> BYMONTH in your example. But I think a behavior like that is going 
>>> to be really tricky for implementors to get right and hard to 
>>> describe really well without having to delve into the gory details 
>>> of RRULE processing.
>>>
>> Ah, got it.
>>
> I'd also argue that BYMONTHDAY=30/31 should have different results 
> from BYMONTHDAY=-1, in the same way that it does for GREGORIAN:
>
>
> So, my proposal is to tweak the BYxxx rule part processing order in 
> RFC 5545, Section 3.3.10 by inserting SKIP processing in the following 
> way:
>
> BYMONTH

-- 
Marten Gajda
Schandauer Straße 34
01309 Dresden
Germany

tel: +49 177 4427167
email: [email-masked]

---

From: Ken Murchison <[email-masked]>
Date: Wed, 04 Feb 2015 09:34:19 -0500

Hi Marten,

On 02/04/2015 08:55 AM, Marten Gajda wrote:
> "invalid day" refers to leap days only. I.e. SKIP=FORWARD doesn't 
> apply to Feb 30 or similar dates.

Actually, for Feb 30, SKIP=FORWARD should yield Mar 1, which is why the 
draft say "invalid day".

Same for April 31.

---

From: Cyrus Daboo <[email-masked]>
Date: Wed, 04 Feb 2015 09:49:07 -0500

Hi Ken,

> Actually, for Feb 30, SKIP=FORWARD should yield Mar 1, which is why the

Yes, I think an "invalid" day means either a leap day or a day-of-month 
value that exceeds the number of days in the current month.

-- 
Cyrus Daboo

---

From: Marten Gajda <[email-masked]>
Date: Wed, 04 Feb 2015 16:12:15 +0100

Oh, interesting. One more reason to make SKIP=OMIT the default, IMHO.

-- 
Diese Nachricht wurde von meinem Android-Mobiltelefon mit K-9 Mail gesendet.

---

From: Gregory Yakushev <[email-masked]>
Date: Thu, 05 Feb 2015 10:47:37 +0000

Funny enough, my understanding of RRULE parsing was incorrect and I made
some mistakes with my implementation, because it already follows what Ken
suggested. I added all four of the rules from his e-mail (and their
expansions) to my rscale_golden.txt (attached) and it passes without any
changes. I have no objections to clarifying text about the order of SKIP
processing.

As mentioned in another thread, I'd prefer to have SKIP=BACKWARD as default
to reduce the total amount of text in RRULEs (that is, sum of all RRULEs
stored in the world). Length of RRULEs matter from both performance and
readability point of view. But SKIP=OMIT is an acceptable compromise if
consensus points in this direction.

Grisha

---

From: Barry Leiba <[email-masked]>
Date: Thu, 5 Feb 2015 10:49:39 -0500

> consensus points in this direction.

And yet I'm still concerned that trying to define SKIP rules outside
the context of implementation of a specific calendar is complex and
error prone.  It remains my contention that the best thing to do
(which also keeps the rules short) is to say that how RRULEs that
contain RSCALE work without SKIP is dependent upon the calendar
specified in RRULE, and that when you implement a particular calendar,
you have to know how that calendar works and support it properly.
Then we reserve SKIP for exception situations.

I do NOT think that we need to accompany this with any list of
calendars.  Whoever implements a particular calendar needs to know how
it works in order to generate the right SKIP values anyway.  So why
not just say that, and forget about having to include the SKIPs?

Barry

---

From: Gregory Yakushev <[email-masked]>
Date: Thu, 05 Feb 2015 16:09:29 +0000

> not just say that, and forget about having to include the SKIPs?

Because there should be an agreement between all implementation on what
SKIP default is applied to a given Calendar. Say, we agree here that SKIP
should default to BACKWARD for all calendars except HEBREW, for which it
should default to FORWARD. This information needs to be written somewhere
and set in stone, so that all implementation apply correct default when
expanding RRULEs.

Otherwise an implementor without deep knowledge of a particular calendar
(its not required if he bases his implementation on ICU for example), can
apply a different default. I don't see how can we do without a registry for
variable defaults, if we choose this option.

Grisha

---

From: Barry Leiba <[email-masked]>
Date: Thu, 5 Feb 2015 11:13:27 -0500

> Because there should be an agreement between all implementation on what SKIP
> default is applied to a given Calendar. Say, we agree here that SKIP should
> default to BACKWARD for all calendars except HEBREW, for which it should
> default to FORWARD. This information needs to be written somewhere and set
> in stone, so that all implementation apply correct default when expanding
> RRULEs.

No, the point isn't that we should agree that SKIP defaults to
BACKWARD or FORWARD or BANANA, except for anything.  We should agree
that the way each calendar behaves in this regard is specific to each
calendar, and implementors of a particular calendar need to understand
how that calendar works and implement it right.

> variable defaults, if we choose this option.

We do this sort of thing all the time, and it works.  Do we get bad
implementations sometimes, because someone gets it wrong?  Sure.
Those usually get fixed.  I think that situation is *far* better than
having skip rules (perhaps wrong ones, created by the same buggy
implementations) imbedded in the iCalendar entries.

Barry

---

From: Cyrus Daboo <[email-masked]>
Date: Thu, 05 Feb 2015 11:16:30 -0500

Hi Barry,

> not just say that, and forget about having to include the SKIPs?

I am not convinced that there is one convention per calendar system that is 
consistently used. In discussions I have had with others I got the 
impression that the skip mode was dependent on other factors - e.g. the 
nature of the event. For example the convention for personal anniversaries 
may be different than that for "legal" ones. Previously I cited the 
Gregorian example of someone born on a leap day who prefers to celebrate on 
the 28th, but legally is not considered to be "of age" until the 1st.

The bottom line is conventions for one calendar system can vary from locale 
to locale and it would be very hard for us to define the basis for that.

-- 
Cyrus Daboo

---

From: Ken Murchison <[email-masked]>
Date: Thu, 05 Feb 2015 11:19:38 -0500

> implementations) imbedded in the iCalendar entries.

FWIW, the ICU library, which I assume most implementations will use, 
seems to always skip forward to the next valid date if/when you try to 
set an invalid one, regardless of calendar.  So, If I try to set Feb 29 
in a non-leap year it gives me Mar 1.  If I try to set 30 Adar I in a 
non-leap year it gives me 1 Nisan. I could try some more examples using 
Chinese leap months and Ethiopic leap day.

AFAICT, it never skips backwards on its own, I have to do that one layer up.

---

From: Barry Leiba <[email-masked]>
Date: Thu, 5 Feb 2015 11:23:18 -0500

> to locale and it would be very hard for us to define the basis for that.

Ack.

But, then, I still don't see how using possibly complicated SKIP
controls really works here.  If I create a repeating entry, my
calendar system tries to figure out what's what and sticks in some set
of SKIPs.  Maybe it gets them right, and maybe it doesn't.  Whatever
it does, those are now copied to every other calendar system that I
give this vevent to.  If it's wrong, it's wrong everywhere.

If we rely on the calendar implementations to do the right thing with
respect to the particular calendars, then one implementation's bugs
don't spread.

On the other hand, if "personal" and "legal" differ, we'd have to have
some way to convey that this vevent is personal and that one is legal.
Oy.  I'm not worried about exceptions (personal preferences and the
like, though I'm not sure how a calendar implementation would do a UI
to let a user control that)... I'm worried about having most things
get it right most of the time, and reserving explicit SKIP rules for
the exceptions.

I really don't see a way out here.

b

---

From: Cyrus Daboo <[email-masked]>
Date: Thu, 05 Feb 2015 11:25:36 -0500

Hi Ken,

> AFAICT, it never skips backwards on its own, I have to do that one layer

Right but ICU's approach is a purely "arithmetic" behavior where they just 
count the extra days and move forward that number. i.e., if you set the ICU 
date to 30th February in a non-leap year you would get March 2nd. However, 
our "logicial" skip behavior would give Match 1st.

-- 
Cyrus Daboo

---

From: Cyrus Daboo <[email-masked]>
Date: Thu, 05 Feb 2015 11:29:04 -0500

Hi Barry,

> respect to the particular calendars, then one implementation's bugs

But provided the "buggy" data is represented consistently by all clients, 
users do have a reasonable chance of spotting the mistake and correcting 
it. On the other hand, if an event looks right on my mobile device, but is 
interpreted differently on my calendar-aware thermostat (or perhaps more 
seriously a medical device) I probably have no chance of spotting the error 
because the device might not expose its "internal" calendar view. So I 
would much rather the data be interpreted consistently across all devices 
even if its was not exactly what I wanted.

-- 
Cyrus Daboo

---

From: Gregory Yakushev <[email-masked]>
Date: Thu, 05 Feb 2015 16:31:14 +0000

> give this vevent to.  If it's wrong, it's wrong everywhere.

It may be wrong, but for all invitees the event will happen at the same
time. The most important aspect of recurring events is that they should be
consistent: if I invite you to an event it should show up at the same time
for us even if its a wrong time. Otherwise we won't meet at all, and people
get really angry about this.

In your example, the user (creater) will see when instances happen. And if
he is not happy with the implementation - he can always choose a better
system. But at least he won't have to blame Google Calendar for getting his
event wrong when some invitees using it don't show up.

---

From: Barry Leiba <[email-masked]>
Date: Thu, 5 Feb 2015 11:45:00 -0500

> users do have a reasonable chance of spotting the mistake and correcting it.
> On the other hand, if an event looks right on my mobile device, but is
> because the device might not expose its "internal" calendar view. So I would
> much rather the data be interpreted consistently across all devices even if
> its was not exactly what I wanted.

OK, and Grisha says the same thing in his response.

I'm still not happy with the situation, but as it's not clear that we
can do better, I'll consider my issue discussed, and let you guys
decide what the final settings should be.

Thanks for discussing this with me.

Barry