調べて、学ぶ

検索したり実験したことを覚えとくブログ

docomoのスケジュールアプリを移行した

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件をインポート」となる)

試した手段

  1. vcsを扱えるアプリをインストールして使ってもらう
    ⇒ ない。 驚くぐらい見つからない。有料で対応しているようなことを書いているのもあるけど、どうも確証が得られない。却下。
  2. フリーウェアを探してvcsical変換をする
    • (フリーじゃないけど)outlookvcscsv変換
      ⇒ごめんなさい。outlook持ってないです。
    • MSNのoutlook.live.comからアップロード・icalでエクスポートできないか?
      ⇒ ファイルをアップロードしたらファイルサイズに引っかかった(10MBまでだった記憶)

いろいろググった結果、以下のが引っかかるが、どちらも希望は満たされず。

Q8.インポートできるファイル形式にはどのような種類がありますか。

iCalendar形式(.ics)とvCalendar形式(.vcs)に対応しています。iCalendarの文字コードはUTF8、 vCalendarの文字コードはSJISとなります。 

それだよ! と思わず声が出たのですが、実際に使ってみると「未来の予定しか登録しません」と言われてしまう。ぐむむむ...

で、何をしたか

今まで試したりググった中で分かったことは、

⇒自力でやるには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形式で定めていないので、次のレベルへチャレンジですわ…。