カレンダーデータの解析パッケージをリリースした

no extension

今までカレンダーデータ(iCalendar あるいは iCal フォーマット)の解析は PuloV/ics-golang を使っていた。 ただし,オリジナルは2019年を最後に更新されていないため Go Modules にも対応しておらず,並行処理部分で不具合が多いため自分のリポジトリに fork して使っていた。

以前から「こりゃあ自前でいちから書き直したほうが早いか?」と思っていたのだが, GitHub の他人様のリポジトリを眺めてたらソースとして io.Reader 型を受け付けるシンプルな apognu/gocal がよさげな感じなので,これをコアとした並行処理版を作ってみた。

まずは単一ソースの場合:

parser := concal.NewParser(
    concal.WithStartTime(time.Date(2026, time.January, 1, 0, 0, 0, 0, time.UTC)),
    concal.WithEndTime(time.Date(2026, time.December, 31, 23, 59, 59, 0, time.UTC)),
)
events, err := parser.ParseOne(context.Background(), "./calendar.ics")
if err != nil {
    fmt.Fprintln(os.Stderr, err)
    return
}
for _, event := range events {
    fmt.Println(event.Summary)
}

concal.NewParser() 関数の引数は Functional Options パターンで与える。

  • concal.WithStartTime() はイベント取得開始時点を指定する
  • concal.WithEndTime() はイベント取得終了時点を指定する
  • concal.WithLocationAllDayEvent() は終日イベントを取得する際の時差を指定する
  • concal.WithLocationMap() は時差の独自名(MyTZ など)を定義する(複数指定可)
  • concal.WithHTTP11Client() は,強制的に HTTP/1.1 でアクセスする

開始・終了時点を指定しない場合は現時点から90日間を既定値としてイベントを取得する。

ParseOne() メソッドで指定するソースにはローカルファイルまたは Web 上のリソース(http(s):// で始まる URL)を指定できる(文字列から自動判定)。

解析結果は gocal.Event 型の slice で返ってくる。

次に,複数ソースを一度に処理する場合:

parser := concal.NewParser(
    concal.WithStartTime(time.Date(2026, time.January, 1, 0, 0, 0, 0, time.UTC)),
    concal.WithEndTime(time.Date(2026, time.December, 31, 23, 59, 59, 0, time.UTC)),
)
conc := concal.NewConcurrent(context.Background(), parser)
defer func() { _ = conc.Close() }() // TODO: Error handling is required

for _, source := range []string{
    "./calendar-a.ics",
    "https://example.com/calendar.ics",
} {
    if err := conc.Submit(source); err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }
}
go conc.Wait() // start waiting in a separate goroutine

for event := range conc.Events() {
    fmt.Println(event.Summary)
}

手順としては:

  1. 並行処理用のインスタンスを生成
  2. ソースを Submit() メソッドで登録(複数指定可)
  3. Wait() メソッドを別ゴルーチンで実行して解析終了を待ち合わせる(Wait() 後は Submit() できない)
  4. Events() からイベント出力チャネルを取得

という感じ。 Fork/Join パターンに似た構成になっているが,ソースの数が不確定なので Wait() メソッドのタイミングで入力を打ち切っている。 イベント出力チャネルからの出力順はソートされていないので,取り出した側で整理する必要がある。

「とりあえず組んでみた」な状態なので,バグ潰しやリファクタリングを続けてブラッシュアップしていく予定である。

参考図書

thumbs
プログラミング言語Go - 丸善出版 理工・医学・人文社会科学の専門書出版社
明解で効率的なプログラムを描くための書。 柴田 芳樹 訳
 
Release 2016-06-15
評価     

[Comment] 著者のひとりは,あの “K&R” の K のほうである。この本は Go 言語の教科書と言ってもいいだろう。と思ったら絶版状態らしい(2025-01 現在)。復刊を望む!

Powered by linkcard

photo
Go言語 100Tips ありがちなミスを把握し、実装を最適化する impress top gearシリーズ
Teiva Harsanyi (著), 柴田 芳樹 (著)
インプレス 2023-08-18 (Release 2023-08-18)
Kindle版
B0CFL1DK8Q (ASIN)
評価     

[Comment] 版元で PDF 版を購入可能。事実上の Effective Go とも言える充実の内容。オリジナルは敢えてタイトルに “tips” という単語を入れるのを避けたのに邦題が「100 Tips」とかなっていて,原作者がお怒りとの噂(あくまで噂)

reviewed by Spiegel on 2023-08-18 (powered by PA-APIv5)

photo
Go言語で学ぶ並行プログラミング 他言語にも適用できる原則とベストプラクティス impress top gearシリーズ
James Cutajar (著), 柴田 芳樹 (著)
インプレス 2024-12-04 (Release 2024-12-04)
Kindle版
B0DNYMMBBQ (ASIN)
評価     

[Comment] 読書会のために購入。インプレス社の本は Kindle 版より版元で PDF 版を買うのがオススメ。「並行処理」について原理的な解説から丁寧に書かれている。 Go で解説されているが Go 以外の言語でも応用できる。

reviewed by Spiegel on 2025-01-25 (powered by PA-APIv5)