rrule.js簡易メモ

icalのrruleから該当日付を計算してくれるjavascriptライブラリ。
超便利、だが色々問題があったのでメモ。

ビルド環境:node + bower + webpack
※BowerWebpackPluginでbower取得したモジュールはパス書かなくてもいいようにしている。

mainのパスが違います問題

bowerで最新版(2.1.0)取得後、とりあえずライブラリを読み込んで

var RRule = require('rrule').RRule;

ビルド。

Module not found: Error: Cannot resolve 'file' or 'directory' ./rrule.js in ・・・

なぜ・・・

rruleのbower.jsonを確認すると、"main": "rrule.js"となっているが、実際はlib/rrule.jsにある。勘弁して。
とりあえず"main": "lib/rrule.js"に直すと、ビルドエラーは解消。

README.mdが間違ってます問題

12月の土日を指定するrruleを指定してみる。

var rrule = new RRule({
    freq: RRule.WEEKLY,
    byweekday: [RRule.SA, RRule.SU],
    dtstart: new Date(2016, 11, 1),  // 2016/12/01
    until: new Date(2016, 11, 31)    // 2016/12/31
});

実行すると

Uncaught TypeError: Cannot read property 'WEEKLY' of undefined

なぜ・・・スペルミスとかしてないし。
デバッグするとRRuleがundefinedになっている。というわけで、

// var RRule = require('rrule').RRule;
var RRule = require('rrule');

にすると正常に。webpack使っているから? それならREADME.mdが間違っているとは言えない。

と思いきや、調べる過程でソースを読んでいて気づいた。

    module.exports = {
        RRule: RRule
        // rruleset: rruleset
    }

rrulesetが公開されてない?
gitのrrule.jsと比較すると、ソースが全然違う。。。
どうやらgitに表示されているソースはREADME.mdは2.2.0-devで、正式リリースの2.1.0ではない様子。
できればRRuleSetも使いたかったが、管理が怪しげな2.2.0-devを使う気にはなれないので、そこは諦めることにする。

動作確認

根本のソースは正しいロジックなのか疑心暗鬼になりつつ動作確認してみる。

// 12月の木土
var rrule = new RRule({
    freq: RRule.WEEKLY,
    byweekday: [RRule.TH, RRule.SU],
    dtstart: new Date(2016, 11, 1),  // 2016/12/01(木)
    until: new Date(2016, 11, 31)    // 2016/12/31(土)
});
rrule.all();
=> 結果がDate配列で返される
Thu Dec 01 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 03 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 08 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 10 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 15 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 17 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 22 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 24 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 29 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 31 2016 00:00:00 GMT+0900 (東京 (標準時))

dtstart ≦ ● ≦ untilで木・土が列挙されているので問題なさそう。

between()で期間を絞ってみる。

// 12/08(木)から12/24(土)の間だけ取得する
rrule.between(new Date(2016, 11, 8), new Date(2016, 11, 24));
=>
Sat Dec 10 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 15 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 17 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 22 2016 00:00:00 GMT+0900 (東京 (標準時))

rrule.between(new Date(2016, 11, 8), new Date(2016, 11, 24), true);
=>
Thu Dec 08 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 10 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 15 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 17 2016 00:00:00 GMT+0900 (東京 (標準時))
Thu Dec 22 2016 00:00:00 GMT+0900 (東京 (標準時))
Sat Dec 24 2016 00:00:00 GMT+0900 (東京 (標準時))

第3引数にtrue指定すると、between()引数の日時も含んでくれる。

RRuleSetが使えないは残念だが、rrule解析してくれるだけでもかなりありがたい。