前人未踏の領域へ WEB・インフラ・プログラミング全般編

フロントエンド、バックエンド、インフラ、言語など、アプリ開発、IOT以外の記録

RRULEに関するメモ書き

カレンダーの予定のような繰り返しのデータ定義を実装するにあたり、RFC5545(旧RFC2445)のRRULEというのがあるのを知ったので それについて調べたメモ。中でも 3.3.10. Recurrence Rule についてのみ取り扱っている。

比べると、記述方法が若干変わっていた。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時間付きの日付として指定されなければならない
  • STANDARDDAYLIGHTサブコンポーネントの場合、UNTILルールパートは常にUTC時間付きの日付として指定されなければならない
  • DATE-TIME値として指定されているなら、それはUTC時間フォーマットで指定されなければならない
  • UNTIL が存在しない場合、およびCOUNTルール部分も存在しない場合、RRULE は永遠に繰り返されると見なされる。

COUNT

  • 出現回数を定義
  • DTSTARTの値は最初の出現としてカウントされる

BYSECOND

  • 1分以内の秒。カンマ区切りのリストで表される
  • 有効な値は0から60
  • DTSTARTDATE の場合は指定できない

BYMINUTE

  • 1時間以内の分。カンマ区切りのリストで表される
  • 有効な値は 0 - 59
  • DTSTARTDATE の場合は指定できない

BYHOUR

  • 1日の時間。カンマ区切りのリストで表される
  • 有効な値は 0 - 23
  • DTSTARTDATE の場合は指定できない

BYDAY

  • カンマ区切りの曜日のリストを表す
  • FREQ=MONTHLY ルールでは +1MO はその月の最初の月曜日を意味し、 -1MO は最後の月曜を意味する
  • FREQ=YEARLY の場合、BYMONTH で指定した月のオフセットに対応し、 BYWEEKNO または BYMONTH が存在する年内のオフセットに対応する。 (注:仕様書上BYMONTHが2回出てくるので文章が間違ってるかも)
  • 数値が指定されていない場合、毎週実行される
  • FREQ=MONTHLYまたはYEARLYでない場合は数値は指定できない
  • FREQ=YEARLYBYWEEKNO が指定されている場合は BYDAY に数値は指定できない

BYMONTHDAY

  • カンマ区切りの月の日のリストを表す
  • 有効な値は1から31または-31から-1
  • -10はその月の最後の日から10日を表す
  • FREQ=WEEKLY の場合には指定できない

BYYEARDAY

  • カンマ区切りの年の通算日を表す
  • 有効な値は1から366または-366から-1
  • -1は年の最後の日(12月31日)を表す
  • -306は、その年の最後の日から306日前(3月1日)を表す
  • FREQDAILY,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が指定されている場合、FREQINTERVALが評価されたあとで以下の順に適用される
    1. BYMONTH
    2. BYWEEKNO
    3. BYYEARDAY
    4. BYMONTHDAY
    5. BYDAY
    6. BYHOUR
    7. BYMINUTE
    8. BYSECOND
    9. BYSETPOS
    10. COUNT / UNTIL

依存関係

表の意味

  • N/A はそのFREQでは使用できない
  • BYDAYFREQに応じて特殊な振る舞いをする(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が拡張される

参考

/* Responsive: yes */