Search code examples
powershellamazon-web-servicesamazon-ec2aws-powershell

Calculate time difference in hours


This is supposed to be a query for a virtual machine in Amazon EC2, it lists the instances by it's instanceID and LaunchTime (when it was turned up) - and I want to calculate another column that is it's LaunchTime - Current Date/Time to get a "uptime" statistic called HoursSinceBoot.

#get instances
$instances = foreach($i in (get-ec2instance)) {$i.RunningInstance | Select-Object InstanceId,LaunchTime}
$instances | Add-Member -type NoteProperty -name HoursSinceBoot -value (Foreach-object -inputobject     $instances {New-TimeSpan -End (get-date) -Start $_.LaunchTime} | select -expandproperty hours)
$instances

This is the error I get the error below, which seems to indicate Launchtime is not a datetime type, which sure enough when I run a get-member it sure as crap is. Now I know if I run $[0].LaunchTime this code will work, but for some reason using simply the $ variable it all goes to hell. I've tried a few date time conversion techniques like [datetime] but they have similar error "can't convert to type datetime" consequences.

New-TimeSpan : Cannot convert 'System.Object[]' to the type 'System.DateTime' required by parameter 'Start'. Specified method is not supported.
At C:\xxx\powershell\aws-watchdog.ps1:3 char:149
+ ... t-date) -Start $_.LaunchTime} | select -expandproperty hours)
+                    ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-TimeSpan], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewTimeSpanCommand

Solution

  • You may be better off calculating the new HoursSinceBoot property as part of your select.

    Here's an example:

    PS C:\> $launchData = Get-EC2Instance | `
                          % { $_.RunningInstance } | `
                          Select-Object InstanceId, LaunchTime, @{Name='HoursSinceBoot'; Expression={ ((Get-Date)-$_.LaunchTime).TotalHours } }
    PS C:\> $launchData | Format-Table -AutoSize
    
    InstanceId LaunchTime              HoursSinceBoot
    ---------- ----------              --------------
    i-abcd1234 6/11/2014 11:14:39 AM 1061.46170712353
    i-efgh5678 7/11/2014 11:02:24 AM 341.665873790194
    

    What's happening here:

    • Get-EC2Instance is piped into Foreach-Object (aliased by the percent symbol), which pulls the RunningInstance property off of each EC2 reservation object.
    • We pipe each RunningInstance to Select-Object to select InstanceId and LaunchTime, and then generate a new property called HoursSinceBoot.
    • There are parenthesis inside the expression as a matter of order-of-operations. It allows us to evaluate the current date before subtracting from LaunchTime, and the subtracted value before attempting to extract the TotalHours property from the generated DateTime.
    • I incorporated @andyb's suggestion for calculating DateTime difference.

    Also, for trivia's sake... you can double-check that value on the AWS console by checking under the Description tab of an EC2 instance:

    An image of a snippet of the AWS console, describing the launch time of one of my EC2 instances.