在powershell中添加六十进制时间

Add sexagesimal times in powershell

我正在使用 ffprobe 获取六十进制时间,在修剪最后三个(不必要的)数字后,我得到以下格式:

#examples
 0:05:51.15 
11:03:15.24

有没有办法将这 2 个相加,使结果为 11:09:06.39

您可以将字符串转换为 [timespan] 类型,这允许您对结果对象执行算术运算,并对输出应用自定义格式:

PS> ([timespan] ' 0:05:51.15' + [timespan] '11:03:15.24').ToString('h\:mm\:ss\.ff')
11:09:06.39

注意:如果结果时间跨度有可能超过24小时,则需要更多工作。[1]

请注意如何使用 \-转义将输出分隔符 指定为文字 .
在这种情况下,更简单的 .ToString('g') 会产生相同的输出,但仅在使用 . 作为小数点分隔符 的 文化中,因为标准 g 格式说明符是 culture-sensitive。 请参阅 [timespan]::ToString() documentation as well as the documentation on standard and custom 时间跨度格式说明符。

相比之下,PowerShell 在解释输入格式时使用 invariant culture 转换为 [timespan],其中 . 是小数分隔符;类似地,在 可扩展字符串 中使用 [timespan] 实例 会产生文化不变表示;例如:

  • [timespan] '11:03:15.24' 总是 有效,无论当前的文化如何,因为不变的文化期望 . 作为小数点分隔符。
  • "$([timespan] '1' - 1)" 始终 产生 23:59:59.9999999,与当前文化无关[2].

作为No Refunds No Returns notes, if you're dealing with differently formatted input, possibly from a different culture, you can use [timespan]::Parse() / [timespan]::ParseExact() / [timespan]::TryParseExact()


解析给定文化的标准格式

[timespan]::Parse(' 0:05:51,15', 'fr-FR') # OK

注意 , 作为小数点分隔符。

如果您省略文化参数(或传递$null),则应用当前文化。请注意,这与使用 [timespan] cast 有何不同,它始终是 culture-invariant(并假设 . 作为小数点分隔符)。


使用自定义格式解析:

[timespan]::ParseExact(' 0:05:51,15'.Trim(), 'h\:mm\:ss\,ff', $null) # OK

请注意,使用这样的文字自定义格式是从不文化敏感,因为所有分隔符必须指定为 - 转义 - 文字(例如,\:),因此 $null 作为文化参数传递(IFormatProvider) .
相反,传递特定文化仅对文化敏感的 standard 格式说明符 gG.

有意义

使用文化感知自定义格式进行解析:

如果您不知道哪种文化会在运行时生效,但又想尊重该文化的小数点分隔符并结合自定义格式,您需要在您的自定义格式字符串中动态嵌入当前区域性的小数点分隔符:

$tsText = ' 0:05:51.15'
[timespan]::ParseExact($tsText.Trim(), 
  ('h\:mm\:ss\{0}ff' -f [cultureinfo]::CurrentCulture.NumberFormat.NumberDecimalSeparator),
  $null
) # OK in cultures that use "." as the decimal separator

[1] hhh 仅反映输入时间跨度中 未包含在全天 中的小时数。为了也反映天数,在前面添加类似 d\. 的内容 - no 格式说明符允许您表达多天的总小时数,但您可以使用通用字符串格式来实现这一点 - 但是请注意,您还需要 自定义解析代码 以便将结果字符串转换回来到 [timespan] 个实例:
$ts = [timespan] ' 1:05:51.15' + [timespan] '23:03:15.24'
'{0}:{1:mm\:ss\.ff}' -f [Math]::Floor($ts.TotalHours), $ts

[2] 在 .NET 级别,对对象调用 .ToString() 通常会产生文化 -sensitive 表示(如果类型支持它),但是 [timespan] 输出恰好是文化不变的。相比之下,PowerShell 在强制转换和字符串插值的幕后明确使用了 不变文化 ,因此 "$var"$var.ToString() 可能 不会 产生相同的表示 - 详情请参阅 this answer