Powershell 格式持续时间为小时和分钟

Powershell Format Duration as Hours and Minutes

我正在尝试将 TimeSpan 的字符串输出格式化为 $h Hours $m Minutes,以解决复数问题。现在,我有下面的代码,效果很好;但是,当遇到小于一个小时的 TimeSpan 时,它将显示为 0 $m minutes.

Function FormatDuration ([TimeSpan]$Duration) {
    [string]$DurationStr = [math]::floor($Duration.TotalMinutes/60).ToString()
    if ([math]::floor($Duration.TotalMinutes/60) -eq 1) {
        $DurationStr = $DurationStr+" hour"
    } elseif ([math]::floor($Duration.TotalMinutes/60) -ne 0) {
        $DurationStr = $DurationStr+" hours"
    }
    if ($Duration.Minutes -eq 1){
        $DurationStr = $DurationStr+" "+$Duration.Minutes+" minute"
    # Does not display minutes if value is 0
    } elseif ($Duration.Minutes -ne 0) {
        $DurationStr = $DurationStr+" "+$Duration.Minutes+" minutes"
    }
    return $DurationStr
}

我试着寻找其他人是否已经解决了这个问题,但我能找到的最接近的是 zuallauz' solution in this C# thread

不幸的是,似乎 TimeSpans 在 Powershell 中的行为有所不同,它们将分别显示天数和小时数,这意味着 25 小时 45 分钟的 TimeSpan 将存储为:

New-TimeSpan -Hours 25 -Minutes 45

Days              : 1
Hours             : 1
Minutes           : 45
Seconds           : 0
Milliseconds      : 0
Ticks             : 927000000000
TotalDays         : 1.07291666666667
TotalHours        : 25.75
TotalMinutes      : 1545
TotalSeconds      : 92700
TotalMilliseconds : 92700000

任何人都可以指出正确的方向来解决这个问题吗?我的第一个想法是将小时和分钟的处理分开,然后在最后而不是在每个 if-else 语句中将它们连接起来。

编辑:

在 Sambardo 的 的帮助下,我能够创建以下函数:

Function FormatDuration ([TimeSpan]$Duration) {
    $h = $Duration.Days * 24 + $Duration.Hours
    $m = $Duration.Minutes

    switch ($h) {
        0 {$HourStr=$null}
        1 {$HourStr="$h hour"}
        {$_ -ge 1} {$HourStr="$h hours"}
    }
    switch ($m) {
        0 {$MinuteStr=$null}
        1 {$MinuteStr="$m minute"}
        {$_ -ge 1} {$MinuteStr="$m minutes"}
    }
    if ($HourStr -gt 0 -and $MinuteStr -gt 0) {
        [String]$DurationStr=$HourStr+" "+$MinuteStr
    } else {
        $DurationStr=$HourStr+$MinuteStr
    }

    return $DurationStr
}

谢谢大家的帮助!

也许我遗漏了一些关于你的问题的信息,但为什么不把天数变成小时数,然后检查小时数是否大于 0 来调整你的字符串呢?

$TimeSpan = New-TimeSpan -Minutes 45
$h = $TimeSpan.Days * 24 + $TimeSpan.Hours
$m = $TimeSpan.Minutes
if($h -gt 0){"$h hours $m minutes"}
else{"$m minutes"}

要使它看起来像您想要的那样有点烦人,但这会满足您的要求。

$Duration = New-TimeSpan -Hours 25 -Minutes 1
$TotalHours = $Duration.Hours + ( $Duration.Days * 24 )

$String = "$TotalHours Hour"
if ( $TotalHours -gt 1 )
{
    $String += 's'
}
$String += " $($Duration.Minutes) Minute"
if ( $Duration.Minutes -gt 1 )
{
    $String += 's'
}

return $String

Returns 值

25 Hours 1 Minute

只需要在末尾添加一个else条件即可。当 floor Duration 不为 1 且与零相同时,floor Duration 剩下的唯一可能值为零。因此,在您的 else 中,您可以通过清空字符串来管理零值。

if ([math]::floor($Duration.TotalMinutes/60) -eq 1) {
    $DurationStr = $DurationStr+" hour"
} elseif ([math]::floor($Duration.TotalMinutes/60) -ne 0) {
    $DurationStr = $DurationStr+" hours"
} else {
    $DurationStr = ""
}
Function FormatDuration ([TimeSpan]$Duration) {
    $DurHours = [math]::floor($Duration.TotalHours)
    $DurMins  = $Duration.Minutes
    if ($DurHours-1){$PlHours='s'} else {$PlHours=''}
    if ($DurMins -1){$PlMins='s'}  else {$PlMins=''}
    return "{0} hour$($PlHours) {1} minute$($PlMins)" -f $DurHours,$DurMins
}

FormatDuration (New-TimeSpan -Hours 25 -Minutes 45)
FormatDuration (New-TimeSpan -Hours  1 -Minutes 45)
FormatDuration (New-TimeSpan -Hours  1 -Minutes  1)
FormatDuration (New-TimeSpan -Hours  0 -Minutes  1)

示例输出:

25 hours 45 minutes
1 hour 45 minutes
1 hour 1 minute
0 hours 1 minute