eNarc
asked on
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?
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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;
try this
uses
DateUtils;
procedure TForm1.Button1Click(Sender: TObject);
var
Secs: Int64;
begin
Secs := ABS(SecondsBetween(Trunc(Now), DateTimePicker1.Time));
ShowMessage(IntToStr(Secs));
end;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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;
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),
Simply subtracting two float values and multiplying by Seconds per day
But I suppose performance is not the issue here
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
div (MSecsPerSec);
end;
that is 2 calls to DateTimeToMilliseconds, a substraction , a call to Abs and an integer division
function DateTimeToMilliseconds(con
var
LTimeStamp: TTimeStamp;
begin
LTimeStamp := DateTimeToTimeStamp(ADateT
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
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.
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
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 ??
Delphi 2010
Same with Delphi 7, both use SpanOfNowAndThen
I don't have Delphi XE, so it seems they are implemented differently
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 :
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)
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;
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)
ASKER
Thankyou so much.
ASKER
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;
ASKER
>>>>ID:35731252 Author:epasquier
your code works Perfectly and is such a simple way, I hadn't seen it until I accepted. Apologies.
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;
Can you clarify more please?