diff --git a/examples/General.ps1 b/examples/General.ps1 index c01d526..9a88ce6 100644 --- a/examples/General.ps1 +++ b/examples/General.ps1 @@ -2,3 +2,68 @@ .SYNOPSIS This is a general example of how to use the module. #> + +# Import required functions +. ./src/variables/private/UnitMap.ps1 +. ./src/functions/private/Format-UnitValue.ps1 +. ./src/functions/public/Format-TimeSpan.ps1 +. ./src/functions/public/Get-TimeSpan.ps1 + +Write-Host "=== TimeSpan Module Examples ===" -ForegroundColor Green + +# Example 1: Format existing TimeSpan +Write-Host "`n1. Formatting TimeSpan objects:" -ForegroundColor Yellow +$timespan = New-TimeSpan -Hours 2 -Minutes 30 -Seconds 15 +Write-Host "Original TimeSpan: $($timespan.ToString())" +Write-Host "Formatted: $(Format-TimeSpan $timespan)" +Write-Host "Formatted with precision 3: $(Format-TimeSpan $timespan -Precision 3 -FullNames)" + +# Example 2: Get TimeSpan using default behavior (returns Zero) +Write-Host "`n2. Default behavior (both Start and End use current time):" -ForegroundColor Yellow +$defaultResult = Get-TimeSpan +Write-Host "Get-TimeSpan with no parameters: $($defaultResult.ToString())" + +# Example 3: Get TimeSpan to future event +Write-Host "`n3. Getting TimeSpan to future events:" -ForegroundColor Yellow +$futureEvent = [DateTime]::Now.AddHours(3).AddMinutes(45) +$countdown = Get-TimeSpan -End $futureEvent +Write-Host "Event in future: $($futureEvent.ToString('yyyy-MM-dd HH:mm:ss'))" +Write-Host "Time until event: $($countdown.ToString())" +Write-Host "Formatted countdown: $(Format-TimeSpan $countdown -Precision 2 -FullNames)" + +# Example 4: Get TimeSpan between two specific times +Write-Host "`n4. Getting TimeSpan between specific Start and End times:" -ForegroundColor Yellow +$startTime = [DateTime]::Now.AddHours(-2) +$endTime = [DateTime]::Now.AddHours(1) +$duration = Get-TimeSpan -Start $startTime -End $endTime +Write-Host "Start time: $($startTime.ToString('yyyy-MM-dd HH:mm:ss'))" +Write-Host "End time: $($endTime.ToString('yyyy-MM-dd HH:mm:ss'))" +Write-Host "Duration: $($duration.ToString())" +Write-Host "Formatted duration: $(Format-TimeSpan $duration -Precision 2 -FullNames)" + +# Example 5: Handling negative values +Write-Host "`n5. Handling negative TimeSpan values:" -ForegroundColor Yellow +$pastDeadline = [DateTime]::Now.AddHours(-2) +$defaultResult = Get-TimeSpan -End $pastDeadline +$stopAtZeroResult = Get-TimeSpan -End $pastDeadline -StopAtZero + +Write-Host "Past deadline: $($pastDeadline.ToString('yyyy-MM-dd HH:mm:ss'))" +Write-Host "Default result (allows negative): $($defaultResult.ToString())" +Write-Host "StopAtZero result: $($stopAtZeroResult.ToString())" +Write-Host "Formatted negative: $(Format-TimeSpan $defaultResult -FullNames)" + +# Example 6: Pipeline usage +Write-Host "`n6. Pipeline usage:" -ForegroundColor Yellow +$events = @( + [DateTime]::Now.AddMinutes(15), + [DateTime]::Now.AddHours(2), + [DateTime]::Now.AddDays(1) +) + +Write-Host "Multiple upcoming events:" +$events | ForEach-Object { + $timeLeft = $_ | Get-TimeSpan + Write-Host " Event at $($_.ToString('HH:mm:ss')): $(Format-TimeSpan $timeLeft -Precision 2)" +} + +Write-Host "`n=== Examples Complete ===" -ForegroundColor Green diff --git a/src/functions/public/Get-TimeSpan.ps1 b/src/functions/public/Get-TimeSpan.ps1 new file mode 100644 index 0000000..971cef7 --- /dev/null +++ b/src/functions/public/Get-TimeSpan.ps1 @@ -0,0 +1,111 @@ +function Get-TimeSpan { + <# + .SYNOPSIS + Gets a TimeSpan representing the difference between two DateTime values. + + .DESCRIPTION + This function calculates the time difference between a Start DateTime and End DateTime. + By default, both Start and End parameters default to the current time ([DateTime]::Now). + If neither Start nor End is provided (both use defaults), the function returns TimeSpan.Zero. + The function allows negative values by default, but can return zero for negative values using the StopAtZero parameter. + + .EXAMPLE + $futureTime = [DateTime]::Now.AddMinutes(30) + Get-TimeSpan -End $futureTime + + Output: + ```powershell + 00:30:00 + ``` + + Returns a TimeSpan representing 30 minutes until the end time. + + .EXAMPLE + $pastTime = [DateTime]::Now.AddMinutes(-30) + Get-TimeSpan -End $pastTime + + Output: + ```powershell + -00:30:00 + ``` + + Returns a negative TimeSpan showing the end time was 30 minutes ago. + + .EXAMPLE + $pastTime = [DateTime]::Now.AddMinutes(-30) + Get-TimeSpan -End $pastTime -StopAtZero + + Output: + ```powershell + 00:00:00 + ``` + + Returns TimeSpan.Zero since the result would be negative and StopAtZero is specified. + + .EXAMPLE + $startTime = [DateTime]::Now.AddHours(-2) + $endTime = [DateTime]::Now + Get-TimeSpan -Start $startTime -End $endTime + + Output: + ```powershell + 02:00:00 + ``` + + Returns a positive TimeSpan showing the duration between start and end times. + + .EXAMPLE + Get-TimeSpan + + Output: + ```powershell + 00:00:00 + ``` + + Returns TimeSpan.Zero when both Start and End use their default values. + + .OUTPUTS + System.TimeSpan + + .NOTES + The TimeSpan representing the difference between the Start and End DateTime values (End - Start). + + .LINK + https://psmodule.io/TimeSpan/Functions/Get-TimeSpan/ + #> + [CmdletBinding()] + [OutputType([TimeSpan])] + param( + # The start DateTime. Defaults to current time. + [Parameter(ValueFromPipelineByPropertyName)] + [DateTime] $Start = [DateTime]::Now, + + # The end DateTime. Defaults to current time. + [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] + [DateTime] $End = [DateTime]::Now, + + # If specified, returns TimeSpan.Zero instead of negative values. + [Parameter()] + [switch] $StopAtZero + ) + + process { + # Check if both parameters are using their default values + $startIsDefault = $PSBoundParameters.Keys -notcontains 'Start' + $endIsDefault = $PSBoundParameters.Keys -notcontains 'End' + + if ($startIsDefault -and $endIsDefault) { + return [TimeSpan]::Zero + } + + # Calculate the time difference: End - Start + $timeSpan = $End - $Start + + # Handle negative values based on StopAtZero parameter + if ($timeSpan.TotalSeconds -lt 0 -and $StopAtZero) { + return [TimeSpan]::Zero + } + + return $timeSpan + } +} \ No newline at end of file diff --git a/tests/PSModuleTest.Tests.ps1 b/tests/PSModuleTest.Tests.ps1 index 0b49355..c8178a6 100644 --- a/tests/PSModuleTest.Tests.ps1 +++ b/tests/PSModuleTest.Tests.ps1 @@ -45,4 +45,80 @@ } } } + + Describe 'Get-TimeSpan' { + Context 'Get-TimeSpan - Default Behavior' { + It 'Get-TimeSpan - Returns Zero when both Start and End use defaults' { + $result = Get-TimeSpan + $result | Should -Be ([TimeSpan]::Zero) + } + } + + Context 'Get-TimeSpan - Future End DateTime' { + It 'Get-TimeSpan - Returns positive TimeSpan for future end datetime' { + $future = [DateTime]::Now.AddMinutes(30) + $result = Get-TimeSpan -End $future + $result.TotalMinutes | Should -BeGreaterThan 29 + $result.TotalMinutes | Should -BeLessThan 31 + } + } + + Context 'Get-TimeSpan - Past End DateTime' { + It 'Get-TimeSpan - Returns negative TimeSpan for past end datetime by default' { + $past = [DateTime]::Now.AddMinutes(-30) + $result = Get-TimeSpan -End $past + $result.TotalMinutes | Should -BeLessThan -29 + $result.TotalMinutes | Should -BeGreaterThan -31 + } + + It 'Get-TimeSpan - Returns Zero for past end datetime with StopAtZero' { + $past = [DateTime]::Now.AddMinutes(-30) + $result = Get-TimeSpan -End $past -StopAtZero + $result | Should -Be ([TimeSpan]::Zero) + } + } + + Context 'Get-TimeSpan - Start and End Parameters' { + It 'Get-TimeSpan - Calculates difference between Start and End' { + $start = [DateTime]::Now.AddHours(-2) + $end = [DateTime]::Now + $result = Get-TimeSpan -Start $start -End $end + $result.TotalHours | Should -BeGreaterThan 1.9 + $result.TotalHours | Should -BeLessThan 2.1 + } + + It 'Get-TimeSpan - Returns negative when End is before Start' { + $start = [DateTime]::Now + $end = [DateTime]::Now.AddHours(-1) + $result = Get-TimeSpan -Start $start -End $end + $result.TotalHours | Should -BeLessThan -0.9 + $result.TotalHours | Should -BeGreaterThan -1.1 + } + + It 'Get-TimeSpan - Returns Zero for negative difference with StopAtZero' { + $start = [DateTime]::Now + $end = [DateTime]::Now.AddHours(-1) + $result = Get-TimeSpan -Start $start -End $end -StopAtZero + $result | Should -Be ([TimeSpan]::Zero) + } + } + + Context 'Get-TimeSpan - Pipeline Support' { + It 'Get-TimeSpan - Accepts DateTime from pipeline as End parameter' { + $future = [DateTime]::Now.AddMinutes(15) + $result = $future | Get-TimeSpan + $result.TotalMinutes | Should -BeGreaterThan 14 + $result.TotalMinutes | Should -BeLessThan 16 + } + } + + Context 'Get-TimeSpan - Exact Same Time' { + It 'Get-TimeSpan - Returns near Zero for same Start and End times' { + $time = [DateTime]::Now + $result = Get-TimeSpan -Start $time -End $time + # Should be exactly zero for same time + $result.TotalMilliseconds | Should -Be 0 + } + } + } }