Home > Mobile >  Counting days "Out of office" events with Apps Script Calendar Service
Counting days "Out of office" events with Apps Script Calendar Service

Time:11-02

I would like to count the days off I had in my Google Calendar at the end of every month.

With the following simple formula,

total days off = out of office days   bank holidays

Using a Calendar Service in Apps Script, I came up with that solution using a #dayoff tag trick and filtered on Mon-Fri only.

  const date = new Date()
  const currentMonth = date.getMonth()
  const currentYear = date.getFullYear()
  const start = new Date(currentYear, currentMonth, 1)
  const end = new Date(currentYear, currentMonth   1, 0)

  Logger.log(start.toLocaleDateString("fr-FR"))
  Logger.log(end.toLocaleDateString("fr-FR"))
  
  const events = CalendarApp.getDefaultCalendar().getEvents(start, end, {search: '#dayoff'})
    .filter(x => [1,2,3,4,5].includes(x.getStartTime().getDay()))
  
  const holidays = CalendarApp.getCalendarsByName('Holidays in France')[0].getEvents(start, end)
    .filter(x => [1,2,3,4,5].includes(x.getStartTime().getDay()))

  // MailApp.sendEmail('[email protected]', 'Timesheet', `${events.length} days off, ${holidays.length} bank holidays`)
  Logger.log(`${events.length} days`)
  Logger.log(`${holidays.length} days`)

I would like to share that script with my colleagues and remove the my #dayoff trick, how can I get the "Out of office" information directly from the API, and how do I handle multi days "Out of office" events?

CodePudding user response:

You can use the Calendar API with Apps Script and with the Events: list method you will receive an Event object. There you can filter by the eventType attribute to get the outOfOffice.

CodePudding user response:

I came up to this solution following Kessy's help, but can't get single-day out of office events

const howManyDays = () => {
  WEEK_DAYS = [1,2,3,4,5]

  // https://stackoverflow.com/a/25672779/1360476
  const countWeekDays = (start, end) => {
    const ndays = 1   Math.round((end-start)/(24*3600*1000))
    const sum = (a,b) => a   Math.floor((ndays   (start.getDay() 6-b) % 7)/7)

    return WEEK_DAYS.reduce(sum, 0)
  }

  const diffDays = (start, end) => {
    return Math.ceil(Math.abs(new Date(end) - new Date(start)) / (1000 * 60 * 60 * 24))
  }

  const date = new Date()
  const currentMonth = date.getMonth()
  const currentYear = date.getFullYear()
  const start = new Date(currentYear, currentMonth, 1)
  var end = new Date(currentYear, currentMonth   1, 0)

  const workDays = countWeekDays(start, end)
  const myCalendar = Calendar.Events.list('primary')
  const outOfOffice = myCalendar.items
    .filter(x => x.eventType == "outOfOffice")
    .map(x => {
      const {summary, start, end} = x
      return {summary, start: new Date(start.dateTime), duration: diffDays(start.dateTime,end.dateTime)}
    })
    .filter(x => start <= x.start && x.start <= end)
    .map(x => x.duration)   // FIXME: we only have duration >= 2 here
    .reduce((x, y) => x   y)

  const holidays = CalendarApp.getCalendarsByName('Holidays in France')[0].getEvents(start, end)
    .filter(x => WEEK_DAYS.includes(x.getStartTime().getDay()))
    .length

  message = `  ${workDays} working days from ${start.toLocaleDateString()} to ${end.toLocaleDateString()} \n`
            `-  ${outOfOffice} out of office days \n`
            `-  ${holidays} bank holidays \n`

  MailApp.sendEmail('[email protected]', 'My timesheet', message)
  Logger.log(message)
}
  • Related