Convert seconds to hh:mm:ss,fff format in PowerShell
Asked Answered
C

3

22

I have a string representing a time in seconds and milliseconds. I want to convert it to a string in the format "hh:mm:ss,fff".

My solution still has the flaw that hours less than 10 are shown with one decimal instead of two:

PS> $secs = "7000.6789"
PS> $ts =  [timespan]::fromseconds($s)
PS> $res = "$($ts.hours):$($ts.minutes):$($ts.seconds),$($ts.milliseconds)"
PS> $res
PS> 1:56:40,679

What is the right way to achieve this? I'm sure there is a more elegant way with -f and datetime.

Centuplicate answered 18/2, 2014 at 0:41 Comment(1)
Does $res.ToString() not fill your requirements? It does skip milliseconds if there are no relevant digits and it does append days if the hours would otherwise be higher than 23, which might not suit you. If that doesn't work, look into the TimeSpan.ToString(string) method, which takes a format string. The format string can either be a standard timespan format or a custom timespan format.Suggestive
C
50

In PowerShell 4.0

$s = "7000.6789"
$ts =  [timespan]::fromseconds($s)
("{0:hh\:mm\:ss\,fff}" -f $ts)

Output: 01:56:40,679


In PowerShell 2.0

$s = "7000.6789"
$ts =  [timespan]::fromseconds($s)
"{0:hh:mm:ss,fff}" -f ([datetime]$ts.Ticks)

Output: 01:56:40,679


And to go back the other way...

$text = "01:56:40,679"
$textReformat = $text -replace ",","."
$seconds = ([TimeSpan]::Parse($textReformat)).TotalSeconds
$seconds

Output: 7000.679

Chlorohydrin answered 18/2, 2014 at 2:25 Comment(5)
Thank you andyb, this works very well! (I was so free and inserted the full example, feel free to roll back). How would an example look for the complete reverse of this? For example from 01:56:40,697 to 7000.6789Centuplicate
The PowerShell V2 solution worked for some of my scenarios, but for durations of >= 13 hours, the hh field returns 01-12.Quidnunc
Thanks @RegisteredUser. I've modified the format strings to use the 24-hour version.Chlorohydrin
For your PowerShell 4.0 solution, I don't think the format string can include uppercase 'H' because this results in an error. (Probably 2016-06-16 edit?) Changing it to lowercase 'h' ("{0:hh\:mm\:ss\,fff}") doesn't result in an error but I'm guessing accuracy of timespan format string will be limited to 12 hours or less. The error in PowerShell 4.0 is: Error formatting a string: Input string was not in a correct format.. At line:1 char:1 + ("{0:HH\:mm\:ss\,fff}" -f $ts)Halmstad
Yes, @JasDev, I think you are right. It seems the formatting logic for timespan does not support HH. I will revert back to 'hh'.Chlorohydrin
S
15

You could just use the ToString method on the TimeSpan object and specify the format you want to use. Either use one of the standard timespan formats or use a custom timespan format. For example, the following custom format gives the output you want:

$ts =  [timespan]::fromseconds("7000.6789")
$ts.ToString("hh\:mm\:ss\,fff")

This will output

01:56:40,679

Update: Updating to provide functions working in PowerShell v2

The above solution works well in PowerShell v4, but not in v2 (since the TimeSpan.ToString(string) method wasn't added until .NET Framework 4).

In v2 I guess you'll have to either create the string manually (like you are doing in the question) or doing an ordinary ToString() and manipulate the string. I suggest the former. Here's a function which works fine for that:

function Format-TimeSpan
{
    PARAM (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [TimeSpan]$TimeSpan
    )

    #Current implementation doesn't handle days.

    #By including the delimiters in the formatting string it's easier when we contatenate in the end
    $hours = $TimeSpan.Hours.ToString("00")
    $minutes = $TimeSpan.Minutes.ToString("\:00")
    $seconds = $TimeSpan.Seconds.ToString("\:00")
    $milliseconds = $TimeSpan.Milliseconds.ToString("\,000")

    Write-Output ($hours + $minutes + $seconds + $milliseconds)
}

Testing it using

$ts =  [timespan]::fromseconds("7000.6789")

Format-TimeSpan -TimeSpan $ts
$ts | Format-TimeSpan

Yields the following output:

01:56:40,679
01:56:40,679
Suggestive answered 18/2, 2014 at 16:52 Comment(1)
Thank you Robert, I wasn't aware that the TimeSpan.ToString(string) was added later.Centuplicate
S
5

One line conversion :

[timespan]::fromseconds(354801857.86437).tostring()

return 4106.12:04:17.8640000

Succedaneum answered 10/4, 2017 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.