GAS で Google カレンダーの1日の空き時間を取得する

最近予定が詰まっているのでスキマ時間がどれくらいあるのか取得したくなった。ので GAS で書いた。

function myFunction() {
  const calendar = CalendarApp.getCalendarById('hogehogei@example.com');

  const date = new Date();
  
  const freeTime = getFreeTimeMinutes(calendar, new Date());

  // あとは気分に応じて Slack に投げたりする
}

function getFreeTimeMinutes(calendar, date){
  const events = calendar.getEventsForDay(date);
  
  // 終了時間の昇順にした後に開始時間の昇順にする
  const sortedEvents = events.sort(function(a, b) {
    return a.getEndTime() - b.getEndTime();
  }).sort(function(a, b) {
    return a.getStartTime() - b.getStartTime();
  });
 
 // 時間がかぶっている予定をひとまとめに `block` とする
  const blocks = [];
  var block = {
    start: sortedEvents[0].getStartTime(),
    end: sortedEvents[0].getEndTime()
  };
  
  sortedEvents.forEach(function(event) {
    const start = event.getStartTime();
    const end = event.getEndTime();
    
    if(block.end < start){
      blocks.push({
        start: block.start,
        end: block.end
      });
      block.start = start;
      block.end = end;
    }
        
    if(block.end < end){
      block.end = end;
    }
  });
  
  blocks.push({
    start: block.start,
    end: block.end
  });
  
  // 9:30 - 18:00 を定時とする
  const bizStart = new Date(date.getYear(), date.getMonth(), date.getDate(), 9, 30, 0);
  const bizEnd = new Date(date.getYear(), date.getMonth(), date.getDate(), 18, 00, 0);
  
  // 完全に業務時間外の予定を省く
  const filteredBlocks = blocks.filter(function(block) {
     return bizStart < block.end && block.start < bizEnd
  });
  
  // 業務時間から溢れた分をカットする
  const cutOffBlocks = filteredBlocks.map(function(block){
    if(block.start < bizStart) block.start = bizStart;
    if(bizEnd < block.end) block.end = bizEnd;
    
    return block;
  });
 
 // 業務時間内で重複を取り除いた予定の合計時間
  var sumMinutes = 0;
  cutOffBlocks.forEach(function(block) {
    sumMinutes += (block.end.getTime() - block.start.getTime()) / (1000 * 60);
  });
  
  const bizMinutes = (bizEnd.getTime() - bizStart.getTime()) / (1000 * 60);
  
  return bizMinutes - sumMinutes;
}

業務時間外を省いているのは、飲み会とかの予定も入ってるから。 休憩時間とかフレックスは未対応です。

もっと効率よく書ける気はしている。