Private/ConvertTo/ConvertTo-TimeSpan.ps1
<# .SYNOPSIS Converts various input types to a [TimeSpan] instance. .DESCRIPTION Accepts input as: - [TimeSpan] instances - Numeric values (interpreted as seconds) - Strings (parsed into TimeSpan) The string parser supports standard .NET TimeSpan formats (c, g, G) as well as compact token formats like "1d2h30m15s250ms" (order-insensitive, any subset). .PARAMETER InputObject The input value to convert to a TimeSpan. .EXAMPLE # From TimeSpan $ts = [TimeSpan]::FromHours(1.5) ConvertTo-TimeSpan -InputObject $ts .EXAMPLE # From numeric seconds ConvertTo-TimeSpan -InputObject 90 .EXAMPLE # From string ConvertTo-TimeSpan -InputObject "1d2h30m15s250ms" .OUTPUTS System.TimeSpan #> function ConvertTo-TimeSpan { [CmdletBinding()] [OutputType('System.TimeSpan')] param( [Parameter(Mandatory)] [object]$InputObject ) # 1) Already a TimeSpan if ($InputObject -is [TimeSpan]) { return $InputObject } # 2) Numeric => seconds if ($InputObject -is [int] -or $InputObject -is [long] -or $InputObject -is [double] -or $InputObject -is [decimal]) { return [TimeSpan]::FromSeconds([double]$InputObject) } # 3) String parsing if ($InputObject -is [string]) { $s = $InputObject.Trim() # Try .NET built-in formats first: "c", "g", "G" (e.g., "00:30:00", "1.02:03:04") $ts = [TimeSpan]::Zero if ([TimeSpan]::TryParse($s, [ref]$ts)) { return $ts } # Compact tokens: 1d2h30m15s250ms (order-insensitive, any subset) if ($s -match '^(?i)(?:\s*(?<d>\d+)\s*d)?(?:\s*(?<h>\d+)\s*h)?(?:\s*(?<m>\d+)\s*m)?(?:\s*(?<s>\d+)\s*s)?(?:\s*(?<ms>\d+)\s*ms)?\s*$') { $days = [int]::Parse(('0' + $Matches['d'])) $hrs = [int]::Parse(('0' + $Matches['h'])) $min = [int]::Parse(('0' + $Matches['m'])) $sec = [int]::Parse(('0' + $Matches['s'])) $msec = [int]::Parse(('0' + $Matches['ms'])) return [TimeSpan]::new($days, $hrs, $min, $sec, $msec) } throw "Invalid TimeSpan format: '$s'. Try '00:30:00', '1.02:03:04', or tokens like '1d2h30m15s'." } throw "Cannot convert value of type [$($InputObject.GetType().FullName)] to [TimeSpan]." } |