Functions/Public/Get-TimeElapsed.ps1
|
function Get-TimeElapsed { <# .SYNOPSIS Calculates and formats the time elapsed since a given date. .DESCRIPTION The Get-TimeElapsed function calculates the difference between a given date/time and the current time, returning it in various formats. Supports both DateTime objects and string inputs with configurable date formats. .PARAMETER DateTime The starting date/time to calculate from. Can be a DateTime object or a string. .PARAMETER DateFormat When DateTime is a string, specifies the format to parse it. Default is 'yyyy-MM-ddTHH:mm:ss' (ISO 8601). Common formats: 'MM/dd/yyyy HH:mm:ss', 'dd-MM-yyyy', 'yyyy-MM-dd' .PARAMETER OutputFormat Controls the output format: - 'Friendly' (default): Returns "2d 5h ago" or "3h ago" - 'Days': Returns just the number of days as an integer - 'Hours': Returns total hours as a decimal - 'TimeSpan': Returns the raw TimeSpan object - 'Verbose': Returns "2 days, 5 hours, 30 minutes ago" .INPUTS System.DateTime or System.String. You can pipe dates to Get-TimeElapsed. .OUTPUTS Varies based on OutputFormat parameter. .EXAMPLE Get-TimeElapsed -DateTime (Get-Date).AddDays(-5) Returns: "5d 0h ago" .EXAMPLE Get-TimeElapsed -DateTime "01/15/2026 10:30:00" -DateFormat "MM/dd/yyyy HH:mm:ss" Parses the string date and returns elapsed time. .EXAMPLE Get-TimeElapsed -DateTime $lastLogin -OutputFormat Days Returns the number of days since last login as an integer. .EXAMPLE "2026-01-01T00:00:00" | Get-TimeElapsed -OutputFormat Verbose Returns: "35 days, 14 hours, 22 minutes ago" .NOTES Author: Sune Alexandersen Narud Version: 1.0.0 Date: February 2026 This function replaces the separate Get-DaysSince and Get-TimeSince functions by combining their functionality with additional output options. .LINK Format-TimeSpan #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] $DateTime, [Parameter()] [string]$DateFormat = 'yyyy-MM-ddTHH:mm:ss', [Parameter()] [ValidateSet('Friendly', 'Days', 'Hours', 'TimeSpan', 'Verbose')] [string]$OutputFormat = 'Friendly' ) process { # Parse the input to DateTime $parsedDate = $null if ($DateTime -is [DateTime]) { $parsedDate = $DateTime } elseif ($DateTime -is [string]) { # Try multiple common formats $formats = @( $DateFormat, 'yyyy-MM-ddTHH:mm:ss', 'yyyy-MM-ddTHH:mm:ssZ', 'MM/dd/yyyy HH:mm:ss', 'dd/MM/yyyy HH:mm:ss', 'yyyy-MM-dd HH:mm:ss', 'yyyy-MM-dd' ) foreach ($fmt in $formats) { try { $parsedDate = [DateTime]::ParseExact($DateTime, $fmt, [System.Globalization.CultureInfo]::InvariantCulture) break } catch { continue } } if ($null -eq $parsedDate) { # Last resort: try Parse try { $parsedDate = [DateTime]::Parse($DateTime) } catch { throw "Unable to parse date string '$DateTime'. Please specify the format using -DateFormat parameter." } } } else { throw "DateTime parameter must be a DateTime object or a string. Received: $($DateTime.GetType().Name)" } # Calculate the time difference $now = Get-Date $timeDifference = $now - $parsedDate # Handle negative timespan (future dates) $isFuture = $timeDifference.TotalSeconds -lt 0 if ($isFuture) { $timeDifference = $parsedDate - $now } # Format output based on requested format switch ($OutputFormat) { 'Days' { return [int]$timeDifference.Days } 'Hours' { return [math]::Round($timeDifference.TotalHours, 2) } 'TimeSpan' { return $timeDifference } 'Verbose' { # Use Format-TimeSpan with Full precision for detailed output $suffix = if ($isFuture) { 'from now' } else { 'ago' } $formatted = Format-TimeSpan -TimeSpan $timeDifference -Precision Full return "$formatted $suffix" } 'Friendly' { # Use Format-TimeSpan with Compact for short output $suffix = if ($isFuture) { 'from now' } else { 'ago' } $formatted = Format-TimeSpan -TimeSpan $timeDifference -Compact return "$formatted $suffix" } } } } |