Office 365 Calendar API - Calendar Availability

Hello Everyone, I am trying to reproduce the “Email Calendar” functionality in the traditional Outlook client using the Office 365 Calendar REST Api. For example, I am able to receive the appropriate response from Office 365 Calendar REST API (this is included in the link below) but I am having difficulties with splitting the data into the appropriate object.

Ultimately, I want to return a list of free and busy times for a given time frame and within normal working hours.

Here you can view the code that I have so far. Any help would be appreciated.

Here is how I would start tackling the challenge.

cls
$VerbosePreference = "SilentlyContinue"
[System.Collections.ArrayList]$CalEvents = Import-CliXML "D:\Temp\CalEventsObject.xml" | Sort-Object Start, End

$BusyTimes = Do {
    for ($i = 0; $i -lt $CalEvents.count; $i++) {
    Write-Verbose "CurrentRecord: $i"
    Write-Verbose "BusyStart: $BusyStart"
    Write-Verbose "BusyEnd: $BusyEnd"
        If ($BusyStart) {
            If ($CalEvents[$i].start -le $BusyEnd) {
                If ($CalEvents[$i].end -le $BusyEnd){
                    Write-Verbose "Event starts and ends within current Busytime: Removing from evaluation"
                    $CalEvents.Remove($CalEvents[$i])
                    $i--
                } ElseIf ($CalEvents[$i].end -gt $BusyEnd) {
                    Write-Verbose "Event starts within current Busytime but ends past current BusyEnd: Setting new BusyEnd"
                    $BusyEnd = $CalEvents[$i].end
                    $CalEvents.Remove($CalEvents[$i])
                    $i--
                }
            }
        } Else {
            Write-Verbose "Setting Inital Busy time:"
            Write-Verbose "`tStart: $($CalEvents[$i].start)"
            Write-Verbose "`tEnd: $($CalEvents[$i].end)"
            $BusyStart = $CalEvents[$i].start
            $BusyEnd = $CalEvents[$i].end
            $CalEvents.Remove($CalEvents[$i])
            $i--
        }
    }
    [pscustomobject]@{Start = $BusyStart; End = $BusyEnd}
    Remove-Variable BusyStart, BusyEnd
} While ($CalEvents)

For ($i = 0; $i -lt @($BusyTimes).count; $i++) {
    [pscustomobject]@{State = "Busy"; Start = [datetime]$BusyTimes[$i].Start; End = [datetime]$BusyTimes[$i].End}
    [pscustomobject]@{State = "Free"; Start = ([datetime]$BusyTimes[$i].End).AddSeconds(1); End = 
        If($BusyTimes[$i+1].End){
            ([datetime]$BusyTimes[$i+1].Start).AddSeconds(-1)
        }Else {
            ([datetime]$BusyTimes[$i].End).Date.AddDays(1).AddSeconds(-1)
        }
     }
}

With your provided input file:

Results:

State Start                End                  
----- -----                ---                  
Busy  8/11/2016 7:00:00 AM 8/14/2016 7:30:00 PM 
Free  8/14/2016 7:30:01 PM 8/14/2016 11:59:59 PM

It results in one busy time since the input file contains 3 events that all start at the same time and end at different times, so the total busy time is the start of the first event to the end of the last event.

Start                End                 
-----                ---                 
2016-08-11T12:00:00Z 2016-08-14T21:00:00Z
2016-08-11T12:00:00Z 2016-08-15T00:00:00Z
2016-08-11T12:00:00Z 2016-08-15T00:30:00Z

Free time is then calculated as 1 second past the end of the busy time to 1 second before the 0000 hours the next day. If there were another busy time, then the free time would be calculated to 1 second before the start of the next busy time.

Here are the results changing the start and end times to show different overlaps

Start                End                 
-----                ---                 
2016-08-12T12:00:00Z 2016-08-13T00:00:00Z
2016-08-13T12:00:00Z 2016-08-14T21:00:00Z
2016-08-14T12:00:00Z 2016-08-15T00:30:00Z

Results:

State Start                End                  
----- -----                ---                  
Busy  8/12/2016 7:00:00 AM 8/12/2016 7:00:00 PM 
Free  8/12/2016 7:00:01 PM 8/13/2016 6:59:59 AM 
Busy  8/13/2016 7:00:00 AM 8/14/2016 7:30:00 PM 
Free  8/14/2016 7:30:01 PM 8/14/2016 11:59:59 PM

Note the difference in the timestamp is due to it automatically adjusting for local timezone rather than UTC which is stored in the xml input file