简体   繁体   中英

Can we convert such 20:72:84(hh:mm:ss) duration to 21:13:24 (hh:mm:ss) format Without Loop?

Is it Possible in VBScript to convert such 20:72:84(hh:mm:ss) duration to 21:13:24 (hh:mm:ss) format?

Yes obviously we can Loop through it but I want to avoid such Loopy technique.

CODE

As per the Siddharth solution - I just modified the code as it to fit with VBScript platform

Option Explicit


    Dim S
    S=Convert("23:61:61")
    MsgBox(s)


Function Convert(strTime) 'As String
    Dim timeArray() 
    Dim h , m , s 

    MsgBox("Hi")

    'On Error Resume Next

    timeArray = Split(strTime, ":")

    h = timeArray(0): m = timeArray(1): s = timeArray(2)

    REM If err then

        REM MsgBox(err)
        REM err.clear
        REM Exit Function
    REM End if

    Do Until s < 60
        s = s - 60
        m = m + 1
    Loop

    Do Until m < 60
        m = m - 60
        h = h + 1
    Loop

    Do Until h < 24
        h = h - 24
    Loop

    Convert = Format(h, "00") & ":" & Format(m, "00") & ":" & Format(s, "00")

    'on Error Goto 0
    'Exit Function
'Whoa:
    'Convert = "Error! CYDD!" '<~~ CYDD : Check Your Data Dude :)
End Function

EDIT1 I am getting an error as Type mismatch to the line timeArray = Split(strTime, ":")

Thanks,

Is this what you are trying?

Option Explicit

Sub Sample()
    Debug.Print Convert("23:61:61")
    Debug.Print Convert("24:61:61")
    Debug.Print Convert("20:72:84")
    Debug.Print Convert("Hello World")
End Sub

Function Convert(strTime As String) As String
    Dim timeArray() As String
    Dim h As Long, m As Long, s As Long

    On Error GoTo Whoa

    timeArray = Split(strTime, ":")

    h = timeArray(0): m = timeArray(1): s = timeArray(2)

    Do Until s < 60
        s = s - 60
        m = m + 1
    Loop

    Do Until m < 60
        m = m - 60
        h = h + 1
    Loop

    Do Until h < 24
        h = h - 24
    Loop

    Convert = Format(h, "00") & ":" & Format(m, "00") & ":" & Format(s, "00")

    Exit Function
Whoa:
    Convert = "Error! CYDD!" '<~~ CYDD : Check Your Data Dude :)
End Function

SNAPSHOT

在此处输入图片说明

EDIT (FOLLOWUP)

The code that I gave above is for VBA-Excel ( as it is one of your tags )

For VB-Script , use this code

MsgBox Convert("23:61:61")
MsgBox Convert("24:61:61")
MsgBox Convert("20:72:84")
MsgBox Convert("Hello World")

Function Convert(strTime)
    Dim timeArray
    Dim h, m, s, hh, mm, ss

    On Error Resume Next

    timeArray = Split(strTime, ":", -1, 1)

    h = timeArray(0): m = timeArray(1): s = timeArray(2)

    If Err Then
        Err.Clear
        Exit Function
    End If

    Do Until s < 60
        s = s - 60
        m = m + 1
    Loop

    Do Until m < 60
        m = m - 60
        h = h + 1
    Loop

    ' As per latest request
    'Do Until h < 24
        'h = h - 24
    'Loop

    If Len(Trim(h)) = 1 Then hh = "0" & h Else hh = h
    If Len(Trim(m)) = 1 Then mm = "0" & m Else mm = m
    If Len(Trim(s)) = 1 Then ss = "0" & s Else ss = s

    Convert = hh & ":" & mm & ":" & ss

    On Error GoTo 0
End Function

HTH

  1. Split the array
  2. Add each part to an empty time using dateadd()
  3. rebuild the time to a well formatted string using a stringbuilder

     ' This splits the string in an hours, minutes and seconds part. ' the hours will be in dArr(0), minutes in dArr(1) and seconds in dArr(2) dArr = split("20:72:84", ":") ' Add the hours to an empty date and return it to dt1 dt1 = dateadd("h", dArr(0), empty) ' Add the minutes to dt1. Note: Minutes are noted as "n" and not "m" because the ' "m" is reserved for months. To find out more about the dateadd() please look here: ' http://www.w3schools.com/vbscript/func_dateadd.asp ' When the minutes are bigger than they fit in the date, it automatically falls over to ' next hour. dt1 = dateadd("n", dArr(1), dt1) ' Also add the seconds (the third part of the array) to dt1, also the seconds ' automatically fall over when too large. dt1 = dateadd("s", dArr(2), dt1) ' Now that we created a date, we only have to format it properly. I find it the most easy ' way to do this is with a dotnet stringbuilder, because we can separate code and ' format. The CreateObject creates the stringbuilder. We chain the AppendFormat ' and the ToString methods to it, so actually these are three statements in one. ' Mind the HH in the HH:mm:ss format string, hh means 12 hour notation, HH means 24 ' hour notation. msgbox CreateObject("System.Text.StringBuilder").AppendFormat("{0:HH:mm:ss}", dt1).toString() 

outputs 21:13:24

EDIT: Extra comments by request of TS

This seems to be quite obviously an " XY Problem ": the OP is seeking a workaround to deal with a malformed piece of data, instead of figuring how the data is becoming malformed in the first place (and preventing it from happening).

20:72:84 is not a logical representation of duration by any standard, and whatever created that string is erroneous.

Technically , according to ISO-8601 (considered the "international standard for covering exchange of date and time related data"), duration should be expressed as PnYnMnDTnHnMnS .

That said, I would also opt for HH:MM:SS ... but it should [obviously?] never show more than 59 seconds or 59 minutes, any more than our decimal (aka, Base 10 ) number system should count ...0.8, 0.9, 0.10, 0.11... . (lol, "zero point eleven" )


Fixing the Duration

Regardless, it's an old question and we don't know how you got this strange number, but as others have suggested, I would use Split to fix it, although my preference is a more compressed form:

Function fixWonkyDuration(t As String) As String
    fixWonkyDuration = Format(((Split(t, ":")(0) * 60 + Split(t, ":")(1)) _
        * 60 + Split(t, ":")(2)) / 86400, "HH:mm:ss")
End Function

The function above will fix a "wonky" duration by converting each section into seconds, summing, then converting temporarily to a Date before using Format to display it as intended.

It's important to note that neither the input nor output is a valid Excel DateTime ( Date ), so both are declared as String s.

Example Usage:

MsgBox fixWonkyDuration("20:72:84")  'returns "21:13:24"

Convert to Seconds (for comparison, calculations, etc)

Incidentally, when you have a valid duration in HH:MM:SS format, but want to do calculations or comparisons with it, it's easiest to first convert it to seconds with the help of TimeValue and CDbl .

The quickest method:

Function DurationToSeconds(d As String) As Long
    DurationToSeconds = CDbl(TimeValue(d)) * 86400#
End Function

Example Usage:

MsgBox DurationToSeconds("21:13:24")  'returns 76404

Well, you can split into 3 variables: h,m and s. And then check if s>60. And if it is, m=m+s/60 and s=s%60. The same for the m variable:

if(m>60) then
    h=h+m/60
    m=m%60

Then, concate h, m and s.

This is too much text to put in a comment.

When you enter 20:72:33 into any cell that is on General format it will show you a serial number. Eg 0.883715278

Then you change the cell format to Time . And it gives you the format and data you want to see.

HOWEVER ,

The above statement only works as long as your seconds are below 60 . If you enter 60, 61, 84 , '100', etc. It doesn't work.

So perhaps you can jam it like all the jamming codes perhaps you are using right now. ;)

It's as ugly as it could get. Do mod 60 on seconds and then change cell format to Time. Or just as might as use what Alex shows up there in his answer. It's clean and gurantees your the desired output mathematically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM