docomoのスケジュールアプリはical形式じゃない
嫁さんがスマホを機種変したのですが、SIMはdocomoのまま、SIMフリースマホに変更しました。 googleアカウントもdocomoのメールアドレスも大したことなく移行できたのですが、まさかのスケジュールアプリで非常に困らされたので記録を残す。
前提
- 嫁さんのスケジュールアプリはdocomoスマホのプリインストールアプリ
このアプリはdocomo以外のスマホではプレイストアからインストールできない
⇒ SIMフリースマホではインストールできないこのアプリのバックアップ選択肢はdocomoクラウド or SDカードで、ファイル形式は(icalでもcvsでもcsvでもなく).vcs形式
SDにエクスポートしたvcsファイルのサイズは23MB(軽くめまいがした...)
同じアプリは使えないため、これを機にgoogleカレンダーに行ってもらいたいが、googleカレンダーは.vcsファイルを受け取らない(インポートしても「0件中0件をインポート」となる)
試した手段
- vcsを扱えるアプリをインストールして使ってもらう
⇒ ない。 驚くぐらい見つからない。有料で対応しているようなことを書いているのもあるけど、どうも確証が得られない。却下。 - フリーウェアを探してvcs⇒ical変換をする
いろいろググった結果、以下のが引っかかるが、どちらも希望は満たされず。
VCS to ICS Calendar Converter
⇒ 「WARNING: org.apache.commons.codec.net.QuotedPrintableCodec.decodeQuotedPrintable is not working properly on your system! Probably this is caused by a bug in Java.」と言われて何も起こらず。JREをインストールしても変わらず。iCalendar(.ics)→vCalendar(.vcs) 変換プログラム
⇒ perlのスクリプトっぽいのですが、perl未勉強のため環境構築からお勉強。それはちょっと...FavGCalScheduler
⇒QA
Q8.インポートできるファイル形式にはどのような種類がありますか。 iCalendar形式(.ics)とvCalendar形式(.vcs)に対応しています。iCalendarの文字コードはUTF8、 vCalendarの文字コードはSJISとなります。
それだよ! と思わず声が出たのですが、実際に使ってみると「未来の予定しか登録しません」と言われてしまう。ぐむむむ...
で、何をしたか
今まで試したりググった中で分かったことは、
- 出力されたvcsはutf8(BOMなし)のテキストファイル
- vcsファイルは、icalの下位バージョン(vcs:version1.0、ical:version2.0)
- vcsファイルは規定句でコンテンツを挟んで記述する、いわゆるマークアップ言語
カレンダーに使われるiCalendar形式について part1 RDFカレンダー:イベント情報の公開と活用によると、vcs⇒icalを行う上で最低限のデータは「DTSTART」「DTEND」「SUMMARY」のみ
vcsで記述されている項目は、ほとんどがdocomoの独自拡張ぽい。
vCalendarコンテンツフォーマット
⇒自力でやるにはvcs形式とical形式の勉強が必要かと思っていたら、意外とこれはイケるかも... ということで、vcsから必要なものだけ別ファイルにコピーするスクリプトを作成。(nodejsです)
vcsの SUMMARY:スケジュールの題名 はQUOTED-PRINTABLEという形式でエンコードされている(初めて聞いた)とのことなので、これをデコードする機能がないか探したら、 そのものずばりが見つかったのでインストール。
◆プロジェクトフォルダ作成(コマンドラインで実行)
mkdir decodeVCS cd decodeVCS npm install quoted-printable
◆プロジェクトフォルダにdocomoスケジュールからエクスポートした.vcsファイルを置く
◆プロジェクトフォルダにindex.jsを作成し、コードを書く
// index.js let quotedPrintable = require('quoted-printable'); let utf8 =require('utf8'); let fs= require('fs'); const path = require('path'); //変換対象(読み取り元)のvcs const targetVCS = '(vcsファイルの名前).vcs'; //変換先(フォーマット後)のvcs formatedVCS = 'newVCS.vcs'; //prodID('//会社名//個人名(プロダクト名)//国名' らしいけど、ブランク以外ならなんでもいい) const prodID = '//-//baba babao//JP'; //vcsを読み込む const text = String(fs.readFileSync(path.join(__dirname, targetVCS))).split('\r\n'); //読み込んだ内容によってはスキップすることもあるため、ストリームを使って書き込む const writeoption ={ encoding:'utf8' } const writeStream = fs.createWriteStream(path.join(__dirname, formatedVCS),writeoption); let arrline; let doFlg = true; let strtmp =''; //読み込んだvcsを1行ずつ展開 //日付がない場合は書き込みをスキップする text.map(line =>{ arrline = line.split(':'); switch(arrline[0]){ case 'BEGIN': if(arrline[1] === 'VCALENDAR'){ //icalファイルのヘッダ writeStream.write(line + '\r\n' + 'PRODID:' + prodID + '\r\n' + 'VERSION:2.0\r\n'); }else{ strtmp += line + '\r\n'; } break; case 'DTSTART': case 'DTEND': if(arrline[1]==='') { //日付が入ってなければこのイベントは書き込まない doFlg = false; } strtmp += arrline.join(':') + '\r\n'; break; case 'CATEGORIES': strtmp += arrline.join(':') + '\r\n'; break; case 'END': strtmp += arrline.join(':') + '\r\n'; //有効なイベント(DTSTART、DTENDがある)なら書き込み if(doFlg){ writeStream.write(strtmp); } //初期化 strtmp = ''; doFlg = true; break; default: //'SUMMARY;'から始まる場合は加工 if(arrline[0].search('SUMMARY;') === 0){ //quotedPrintableをデコードし、改行を文字を半角スペースに変換 //arrline[0]は 'SUMMARY;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE' となっているので、SUMMARY以後をカットして「:」付ける strtmp += 'SUMMARY:' + utf8.decode(quotedPrintable.decode(line.split(':')[1])).replace(/\n/g,' ') + '\r\n'; } } }) writeStream.end();
新たにnewVCSというファイルを作り出すので、そいつをgoogleカレンダーにインポートさせたら...読んだーーー!
嫁さんもこれで満足だろ...と思ったら、「今まで色分けしてたのに全部同じ色になっている」とのクレーム。 色の設定はical形式で定めていないので、次のレベルへチャレンジですわ…。