カレンダーの予定のような繰り返しのデータ定義を実装するにあたり、RFC5545(旧RFC2445)のRRULEというのがあるのを知ったので
それについて調べたメモ。中でも 3.3.10. Recurrence Rule
についてのみ取り扱っている。
- RFC 5545 - Internet Calendaring and Scheduling Core Object Specification (iCalendar)
- RFC 2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar)
比べると、記述方法が若干変わっていた。RFC5545の方が説明が増えて読みやすくなっている。
今回は繰り返しのデータ定義方法の参考にしたいだけなのでどちらでも特に問題はない。
書式
/
は ORの意味
recur = recur-rule-part *( ";" recur-rule-part )
recur-rule-part
を;
で区切りながら連続表記する。- ルールの順序は考慮しない
FREQ
ルールは必須。ただし複数回登場してはならない- UNTIL または COUNTはオプション。ただし、UNTIL と COUNT は同時には指定できない
- それ以外はオプションで指定可能。ただし複数回登場してはならない
recur-rule-part = ( "FREQ" "=" freq ) / ( "UNTIL" "=" enddate ) / ( "COUNT" "=" 1*DIGIT ) / ( "INTERVAL" "=" 1*DIGIT ) / ( "BYSECOND" "=" byseclist ) / ( "BYMINUTE" "=" byminlist ) / ( "BYHOUR" "=" byhrlist ) / ( "BYDAY" "=" bywdaylist ) / ( "BYMONTHDAY" "=" bymodaylist ) / ( "BYYEARDAY" "=" byyrdaylist ) / ( "BYWEEKNO" "=" bywknolist ) / ( "BYMONTH" "=" bymolist ) / ( "BYSETPOS" "=" bysplist ) / ( "WKST" "=" weekday )
ぱっと見わかりにくいのだけど、続く文章で各項目を説明している。
freq(周期)
SECONDLY
/MINUTELY
/HOURLY
/DAILY
/WEEKLY
/MONTHLY
/YEARLY
のいずれか
enddate (終了日)
日付または日時
enddate = date / date-time
byseclist (秒指定)
秒を指定。秒をカンマ区切りで複数回指定できる。
byseclist = ( seconds *("," seconds) ) seconds = 1*2DIGIT ;0 to 60 1から2桁の整数。0 〜 60まで。0と60の違いは不明。
byminlist (分指定)
分を指定。分をカンマ区切りで複数回指定できる
byminlist = ( minutes *("," minutes) ) minutes = 1*2DIGIT ;0 to 59 #1から2桁の整数。0 〜 59まで
byhrlist (時間指定)
時間を指定。カンマ区切りで複数回指定できる。
byhrlist = ( hour *("," hour) ) hour = 1*2DIGIT ;0 to 23 # 1から2桁の整数。0〜23まで
bywdaylist(曜日指定)
weekdaynumをカンマ区切りで複数回指定できる。
bywdaylist = ( weekdaynum *("," weekdaynum) ) weekdaynum = [[plus / minus] ordwk] weekday # その年の何週目の何曜日か。 plus = "+" minus = "-" ordwk = 1*2DIGIT ;1 to 53 # 年の何週目か。1または2桁。1から53まで weekday = "SU" / "MO" / "TU" / "WE" / "TH" / "FR" / "SA" (それぞれ SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY に対応)
bymodaylist (月日指定)
月の何日目かを指定する。複数回指定可能
bymodaylist = ( monthdaynum *("," monthdaynum) ) monthdaynum = [plus / minus] ordmoday # 何日目かを指定する ordmoday = 1*2DIGIT ;1 to 31 # 1または2桁。1から31まで
byyrdaylist(年の何日目かを指定)
yeardaynum
を複数回指定できる
byyrdaylist = ( yeardaynum *("," yeardaynum) ) yeardaynum = [plus / minus] ordyrday # 年の何日目か ordyrday = 1*3DIGIT ;1 to 366 # 1桁から3桁。 1から366まで
bywknolist(何番目の週か)
bywknolist = ( weeknum *("," weeknum) ) weeknum = [plus / minus] ordwk ordwk #1または2桁。1から53まで
bymolist(月指定)
bymolist = ( monthnum *("," monthnum) ) # 月をカンマ区切りで複数回 monthnum = 1*2DIGIT ;1 to 12 #1桁または2桁。 1から12
bysplist(日の位置指定)
bysplist = ( setposday *("," setposday) ) # 何番目の日かを指定 setposday = yeardaynum yeardaynum = [plus / minus] ordyrday # 年の何日目か ordyrday = 1*3DIGIT ;1 to 366 # 1桁から3桁。 1から366まで
FREQ
- SECONDLY、1秒以上の間隔に基づいて繰り返しイベントを指定
- MINUTELY、1分以上の間隔に基づいて繰り返しイベントを指定
- HOURLY、1時間以上の間隔に基づいて繰り返しイベントを指定
- DAILY、1日以上の間隔に基づいて繰り返しイベントを指定
- WEEKLY、1週間以上の間隔に基づいて繰り返しイベントを指定
- MONTHLY、1ヶ月以上の間隔に基づいて繰り返しイベントを指定
- YEARLY、1年以上の間隔に基づいて繰り返しイベントを指定
INTERVAL
どの間隔で繰り返すかを指定。デフォルトは1で、毎秒、毎分、毎時、毎日、毎週、毎月、毎年を表す。
例えば FREQ=DAILY;INTERVAL=8
は8日ごとを表す。
UNTIL
- 繰り返しの終了日('DATE')または終了日時(
DATE-TIME
)を表す。 UNTIL
ルール部は、繰り返しルールの境界を含むDATEまたはDATE-TIME値を包括的に定義するUNTIL
で指定された値が指定された繰り返しと同期している場合は、この'DATE'または'DATE-TIME'が繰り返しの最後のインスタンスになる- 'UNTIL'ルールパートの値は
DTSTART
プロパティと同じ値型を持たなければならない。
さらに、DTSTART
プロパティが現地時間の日付として指定されている場合、UNTIL
ルール部分も現地時間の日付として指定されなければならない DTSTART
プロパティがUTC時間付きの日付または現地時間とタイムゾーン参照付きの日付として指定されている場合、UNTIL
ルール部分はUTC時間付きの日付として指定されなければならないSTANDARD
とDAYLIGHT
サブコンポーネントの場合、UNTILルールパートは常にUTC時間付きの日付として指定されなければならないDATE-TIME
値として指定されているなら、それはUTC時間フォーマットで指定されなければならないUNTIL
が存在しない場合、およびCOUNT
ルール部分も存在しない場合、RRULE
は永遠に繰り返されると見なされる。
COUNT
- 出現回数を定義
DTSTART
の値は最初の出現としてカウントされる
BYSECOND
- 1分以内の秒。カンマ区切りのリストで表される
- 有効な値は0から60
DTSTART
がDATE
の場合は指定できない
BYMINUTE
- 1時間以内の分。カンマ区切りのリストで表される
- 有効な値は 0 - 59
DTSTART
がDATE
の場合は指定できない
BYHOUR
- 1日の時間。カンマ区切りのリストで表される
- 有効な値は 0 - 23
DTSTART
がDATE
の場合は指定できない
BYDAY
- カンマ区切りの曜日のリストを表す
FREQ=MONTHLY
ルールでは+1MO
はその月の最初の月曜日を意味し、-1MO
は最後の月曜を意味するFREQ=YEARLY
の場合、BYMONTH
で指定した月のオフセットに対応し、BYWEEKNO
またはBYMONTH
が存在する年内のオフセットに対応する。 (注:仕様書上BYMONTHが2回出てくるので文章が間違ってるかも)- 数値が指定されていない場合、毎週実行される
FREQ=MONTHLY
またはYEARLY
でない場合は数値は指定できないFREQ=YEARLY
でBYWEEKNO
が指定されている場合はBYDAY
に数値は指定できない
BYMONTHDAY
- カンマ区切りの月の日のリストを表す
- 有効な値は1から31または-31から-1
- -10はその月の最後の日から10日を表す
FREQ=WEEKLY
の場合には指定できない
BYYEARDAY
- カンマ区切りの年の通算日を表す
- 有効な値は1から366または-366から-1
- -1は年の最後の日(12月31日)を表す
- -306は、その年の最後の日から306日前(3月1日)を表す
FREQ
がDAILY
,WEEKLY
,MONTHLY
のいずれかの場合は指定できない
BYWEEKNO
- カンマ区切りの年の何番目の週かを表す
- 有効値は1〜53 または-53から-1
- 週は
WKST
で定義された曜日から始まる7日間を表す - 暦年の週番号1は、その暦年の最低4日を含む最初の週
FREQ=YEARLY
以外では指定できないBYWEEKNO=3
は年の3番目の週を表す
BYMONTH
- カンマ区切りの年の月を表す
- 有効値は1〜12
WKST
- 週の始まりの曜日を指定する(MO, TU, WE, TH, FR, SA, and SU)
- デフォルトは月曜
BYSETPOS
- ルールで指定された繰り返しのn番目の発生に対応する値をカンマ区切りで指定する
- 1つの
INTERVAL
内の一連の繰り返しに対して処理する - 例えば
FREQ=WEEKLY
の場合、毎週の先頭に対して作用する - 有効な値は1から366または-366から-1
BYxxx
と共に使用される必要がある- もし指定された場合、特定のルールの条件を満たすもののなかでn番目に発生するものを示す
例:月の最終就業日
FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1
その他
- 繰り返しルールは無効な繰り返しインスタンスを生成する可能性がある
- それらは無視し、ルールとしてカウント対象として認めない。
- ルールに含まれない情報は
DTSTART
から派生(継承)する FREQ=YEARLY;BYMONTH=1
は月の何日かを指定していないが、DTSTART
の日が使われる- BYxxxは何らかの方法で繰り返し回数を修正する。
- frequencyより大きいBYxxxの指定は通常発生回数を減らす
FREQ = DAILY; BYMONTH = 1
は毎日→1月のみになる
- frequencyより小さいBYxxxの指定は通常発生回数を増やす
FREQ = YEARLY; BYMONTH = 1,2
は 毎年1回から2回になる
評価順について
- 複数のBYxxxが指定されている場合、
FREQ
とINTERVAL
が評価されたあとで以下の順に適用される- BYMONTH
- BYWEEKNO
- BYYEARDAY
- BYMONTHDAY
- BYDAY
- BYHOUR
- BYMINUTE
- BYSECOND
- BYSETPOS
- COUNT / UNTIL
依存関係
表の意味
N/A
はそのFREQ
では使用できないBYDAY
はFREQ
に応じて特殊な振る舞いをする(Note1, 2を参照)- LimitはFREQの対象が狭まる
- ExpandはFREQの対象が広がる
SECONDLY | MINUTELY | HOURLY | DAILY | WEEKLY | MONTHLY | YEARLY |
---|---|---|---|---|---|---|
BYMONTH | Limit | Limit | Limit | Limit | Limit | Limit |Expand |
BYWEEKNO | N/A | N/A | N/A | N/A | N/A | N/A |Expand |
BYYEARDAY | Limit | Limit | Limit | N/A | N/A | N/A |Expand |
BYMONTHDAY | Limit | Limit | Limit | Limit | N/A | Expand |Expand |
BYDAY | Limit | Limit | Limit | Limit | Expand | Note 1 |Note 2 |
BYHOUR | Limit | Limit | Limit | Expand | Expand | Expand |Expand |
BYMINUTE | Limit | Limit | Expand | Expand | Expand | Expand |Expand |
BYSECOND | Limit | Expand | Expand | Expand | Expand | Expand |Expand |
BYSETPOS | Limit | Limit | Limit | Limit | Limit | Limit |Limit |
- Note 1. BYMONTHDAYがある場合は制限される。そうでなければMONTHLY用にExpandされる
- Note 2. BYYEARDAY or BYMONTHDAY がある場合は制限される。
- そうでなく
BYWEEKNO
がある場合はWEEKLY
が拡張される - そうでなく
BYMONTH
がある場合はMONTHLY
が拡張される - そうでない場合は
YEARLY
が拡張される
- そうでなく