Domanda

Can someone advise me on the best way to convert a duration formated HH:MM:SS to seconds or minutes only?

ie. 00:01:49 = 109secs

I´m using this code but not work

var
i: real;
j: integer;
begin
i := frac(real(StrToTime('00:00:01')));
j := trunc(frac(real(StrToTime('01:00:00'))) / i );
memo2.lines.add(inttostr(j));

when I try the code with 00:10:00 return 599

thanks

È stato utile?

Soluzione 2

A very flexibel tool for handling durations is TTimeSpan found in unit System.TimeSpan. You can get the result in different units (second, minutes, hours, ...) and format that to your needs.

var
  timeSpan: TTimeSpan;
begin
  timeSpan := TTimeSpan.Parse('00:01:49');
  memo2.lines.add(Format('%1.1f min', [timeSpan.TotalMinutes]));
end;

Altri suggerimenti

Using the DateUtils unit:

WriteLn(SecondOfTheDay(StrToTime('00:10:00')));
WriteLn(MinuteOfTheDay(StrToTime('00:10:00')));

Outputs:

600
10

The reason why your code is not working is that floating point values often can not be exactly represented. To avoid all implementation details about how a TDateTime represents the time, use the built in functions in SysUtils and DateUtils, see Date and Time Support.

Use DecodeTime:

http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.DecodeTime

So your code should look like this:

DecodeTime(StrToTime('00:00:01'), Hour, Min, Sec, MSec);

A function that returns the seconds should look something like this:

function GetSeconds(ATimeString: string): Integer;
var
  Hour, Min, Sec, MSec: Word;
begin
  DecodeTime(StrToTime(ATimeString), Hour, Min, Sec, MSec);
  Result := Hour * 3600 + Min * 60 + Sec;
end;

Timespan fails for example with '47:50' (overflow, I don't know why). My answer:

function GetSecondsFromString(ATimeString: string): Double;
var
  arr: TStringdynArray;
  J, I: Integer;
  tf: TFormatSettings;
begin
  Result:= 0;
  arr:= StrUtils.SplitString(ATimeString, ':');
  I:= High(arr);
  if I < 1 then
    exit;
  if I = 2 then
  begin
    if StrTointDef(arr[0], 0) > 23 then
      exit;
    Result:= StrtoIntDef(arr[0], 0) * 3600;
  end;
  Result:= Result + (StrToIntDef(arr[I - 1], 0) * 60);
  J:= Pos('.', arr[I]);
  if (J > 1) and (J < arr[I].Length) then
  begin
    tf:= TFormatSettings.Create;
    tf.DecimalSeparator:= '.';
    Result:= Result + StrToFloat('0' + Copy(arr[I], Pos('.', arr[I])), tf);
    arr[I]:= Copy(arr[I], 1, Pos('.', arr[I]) - 1);
  end;
  Result:= Result + StrToIntDef(arr[I], 0);
end;

This is not a standalone answer but just an extension to Uwe's answer. Upvote his answer.

{ Converts a string formatted like 'hh:mm:ss' to seconds.
  Returns -1 is the string does not contain a valid time. 

    StringToSeconds('00:01:30')     // returns 90 (sec)
    StringToSeconds('01:30')        // returns 5400 (sec)
    StringToSeconds('10')           // returns 864000 (sec)
    StringToSeconds('1.30')         // returns -1
    StringToSeconds('x')            // returns -1                           }

function StringToSeconds(CONST s: String): integer;
VAR
  TimeSpan: TTimeSpan;
begin
  TRY
   TimeSpan:= System.TimeSpan.TTimeSpan.Parse(s);
   Result := round(TimeSpan.TotalSeconds);
  EXCEPT
   Result:= -1;
  end;
end;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top