• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2237
  • Last Modified:

How do I convert 04:05:04 to seconds?

How do I convert a Time Picker Box layout format of 04:05:04 to actual seconds?
0
eNarc
Asked:
eNarc
  • 6
  • 4
  • 3
  • +2
3 Solutions
 
jimyXCommented:
Is that format HH:MM:SS and you want to convert it to Seconds only?
Can you clarify more please?
0
 
jimyXCommented:
If you need to convert Hours, minutes and Seconds to Total seconds then:
procedure TForm1.Button1Click(Sender: TObject);
var
  tim:TDateTime;
  Sec:Integer;
begin
  tim:=StrToTime('04:05:04');
  Sec := (HourOf(tim)*60*60) + (MinuteOf(tim)*60) + SecondOf(tim);
  showmessage(IntToStr(Sec));
end;

Open in new window

Is this what you mean?
0
 
Mahdi78Commented:
drop TEdit and DateTimePicker and use the following code


procedure TForm1.Button1Click(Sender: TObject);
var Hour, Min, Sec, MSec : word;
begin
DecodeTime(DatetimePicker1.Time, Hour, Min, Sec, MSec);
Edit1.Text := IntToStr((360* Hour) + (Min * 60) + Sec);
end;

Open in new window

0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Ephraim WangoyaCommented:
try this
uses
  DateUtils;

procedure TForm1.Button1Click(Sender: TObject);
var
  Secs: Int64;
begin
  Secs := ABS(SecondsBetween(Trunc(Now), DateTimePicker1.Time));
  ShowMessage(IntToStr(Secs));
end;

Open in new window

0
 
epasquierCommented:
that is a bit of all above :
Mahdi is the closest, and I recommend use of DecodeTime. He just missed a 0 converting hours (60x60=3600)

ewangoya method is a bit too much conversions and prone to errors, as Trunc(Now) will return a DateTime being 0h00:00 today, while DateTimePicker.Time will return the time without the day information (so Day 0, which is far from today)


Function TimeToSeconds(T:TTime):Cardinal;
var Hour, Min, Sec, MSec : word;
begin
 DecodeTime(T, Hour, Min, Sec, MSec);
 Result:=Hour*3600+Min*60+Sec;
end;

ShowMessage(
  Format('%d seconds since beginning of the day',
         [ TimeToSeconds(DatetimePicker1.Time) ] ) );

Open in new window

0
 
Ephraim WangoyaCommented:

Actually the DateTimePicker.Time returns todays date & time, but only shows the time portion, thats why the calculation gives the correct answer. However if you happen to put in yesterdays date or some other date, then you are screwed
0
 
Mahdi78Commented:
sorry for the mistake, i lost zero, hehe
this is new code


procedure TForm1.Button1Click(Sender: TObject);
var Hour, Min, Sec, MSec : word;
begin
DecodeTime(DatetimePicker1.Time, Hour, Min, Sec, MSec);
Edit1.Text := IntToStr((3600* Hour) + (Min * 60) + Sec);
end;

Open in new window

0
 
jimyXCommented:
Mine works just fine. Actually I do not see any difference between that method, except mine doesn't use unnecessary variables:
function ToSeconds(Tim:TDateTime):integer;
begin
  Result := (HourOf(Tim)*60*60) + (MinuteOf(Tim)*60) + SecondOf(Tim);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(IntToStr(ToSeconds(DateTimePicker1.DateTime)));  //or just DateTimePicker1.Time
end;

Open in new window

0
 
Ephraim WangoyaCommented:

LOL

All your methods end up calling more functions than a simple subtraction

jimyX
Your sample code calls DecodeTime three times so although you are not declaring the variables, you have a net effect of having the variables declared multiple times

Mahdi78
Thats the simplest version but DecodeTime still calls a couple of multiplication and divisions

Now what is more simpler than
 Secs := SecondsBetween(Trunc(Now), DateTimePicker1.Time)

Simply subtracting two float values and multiplying by Seconds per day

But I suppose performance is not the issue here

0
 
epasquierCommented:
Now what is more simpler than
 Secs := SecondsBetween(Trunc(Now), DateTimePicker1.Time)

Well ewangoya, to start ruining your day, I could say that one need to know how a TTime is coded to understand how possibly it could work (use of Trunc function which operates on float values). So, not so simple in a way. And as we said sooner, this method can give some bad results

Then, SecondBetween is a bit of work in itself, if you look at its code

function SecondsBetween(const ANow, AThen: TDateTime): Int64;
begin
  Result := Abs(DateTimeToMilliseconds(ANow) - DateTimeToMilliseconds(AThen))
    div (MSecsPerSec);
end;
 that is 2 calls to DateTimeToMilliseconds, a substraction , a call to Abs and an integer division

function DateTimeToMilliseconds(const ADateTime: TDateTime): Int64;
var
  LTimeStamp: TTimeStamp;
begin
  LTimeStamp := DateTimeToTimeStamp(ADateTime);
  Result := LTimeStamp.Date;
  Result := (Result * MSecsPerDay) + LTimeStamp.Time;
end;
DateTimeToMilliseconds is a call to DateTimeToTimeStamp followed by a few calculations to translate a Date+ms into milliseconds

And DateTimeToTimeStamp, I will not post here as it is quite a load of ASM code to convert a float-based TDateTime into a TimeStamp structure (integer-based)

All those stacked calls are also quite costly in themselves.

on the other hand, DecodeTime is this :
procedure DecodeTime(const DateTime: TDateTime; var Hour, Min, Sec, MSec: Word);
var
  MinCount, MSecCount: Word;
begin
  DivMod(DateTimeToTimeStamp(DateTime).Time, SecsPerMin * MSecsPerSec, MinCount, MSecCount);
  DivMod(MinCount, MinsPerHour, Hour, Min);
  DivMod(MSecCount, MSecsPerSec, Sec, MSec);
end;
So only one call to DateTimeToTimeStamp, and 3 calls to DivMod which is an extremely compact and optimized function that "shift" the timestamp integer value into the Hour, Min, Sec and MSec.

In the end, DecodeTime is not only a lot easier to understand than your code using SecondsBetween, but I bet it is also faster by a factor of 3, maybe 4.

As a last word, I will say nevertheless that you are right about JimyX solution being much less effective than DecodeTime, as it is in fact calling it more than necessary behind the scene.
Never be afraid to declare 4 variables, that only cost 16 bytes in the stack, which are easily eaten up calling functions just to avoid them.
0
 
Ephraim WangoyaCommented:

epasquire

(This is now just a discussion not part of solution)

SecondsBetween uses SpanOfNowAndThen which is simply Date1-Date2

The entire code of SecondsBetween comprises of  
  SecsPerDay * SpanOfNowAndThen(ANow, AThen);

It does not touch DateTimeToMilliseconds function

I totally agree this can give you bad results and DecodeTime is surely much simpler and cleaner,

Now comparing one Trunc to three DivMode, I think the Trunc will be faster
0
 
epasquierCommented:
SecondsBetween uses SpanOfNowAndThen which is simply Date1-Date2

?? I gave you a complete analysis of the code from Delphi XE, how it is implemented. I have no SpanOfNowAndThen in that DateUtils code. Which Delphi version do you have ??
0
 
Ephraim WangoyaCommented:

Delphi 2010
0
 
Ephraim WangoyaCommented:

Same with Delphi 7, both use SpanOfNowAndThen

I don't have Delphi XE, so it seems they are implemented differently
0
 
epasquierCommented:
I have checked in Delphi 7 it is a better implementation than in Delphi XE...
Those routines do not exist in Delphi 5, that I use also.

Well, it can barely be more straightforward than DecodeTime if you want something that can compile reliably on all Delphi versions, otherwise, if the goal is to get sure not one CPU cycle is wasted, then :

Function TimeToSeconds(T:TTime):Cardinal;
begin
 Result:=Trunc(Frac(T)*3600*24);
end;

Open in new window


But you must admit that it is less readable for the regular guy who is not well aware of Delphi way of coding date/time

Ok, now I think we have made all the talking possible about that simple subject :o)
0
 
eNarcAuthor Commented:
Thankyou so much.
0
 
eNarcAuthor Commented:
These are the functions I'm using.
function A(a:String):int64;
var
  H,M,S,MS:word;
begin
  DecodeTime(StrToTime(a),H,M,S,MS);
  Result:=H*3600+M*60+S;
end;

function B(a:String):int64;
var
  t:TDateTime;
begin
  t:=StrToTime(a);
  Result:=(HourOf(t)*60*60)+(MinuteOf(t)*60)+SecondOf(t);
end;

Open in new window

0
 
eNarcAuthor Commented:
>>>>ID:35731252 Author:epasquier

your code works Perfectly and is such a simple way, I hadn't seen it until I accepted. Apologies.
function C(a:String):Int64;
begin
 Result:=Trunc(Frac(StrToTime(a))*3600*24);
end;

Open in new window

0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 6
  • 4
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now