Recent

Author Topic: [SOLVED] StrToTime - Not a valid time  (Read 10963 times)

Boboxx

  • New member
  • *
  • Posts: 9
[SOLVED] StrToTime - Not a valid time
« on: August 31, 2016, 08:51:16 pm »
Hello,

I'm trying to convert a time formated string to a TTime value but It'sgiving me a error saying that the time is not valid. Anyone know what the problem could be?

fs.TimeSeparator := ':';
fs.DecimalSeparator:='.';
fs.ShortTimeFormat := 'hh:mm:ss.zzz';
tt := StrToTime('09:44.8', fs); 

memo1.lines.add(FormatDateTime('hh:mm:ss.z',tt));

I'm using Lazarus 1.6 with FPC 3.0  OSX

Thanks
« Last Edit: September 02, 2016, 03:59:12 pm by Boboxx »

Thaddy

  • Hero Member
  • *****
  • Posts: 18676
  • Jungle wars. And failing health it seems.
Re: StrToTime - Not a valid time
« Reply #1 on: August 31, 2016, 09:00:15 pm »
Hours, minutes and seconds are separated by time separator, msecs are with the decimal, so:
Code: Pascal  [Select][+][-]
  1. program dt;
  2. {$ifdef fpc}{$mode delphi}{$endif}
  3. uses sysutils,DateUtils;
  4. var
  5.   fs:TFormatSettings;
  6.   tt:TDateTime;
  7. begin
  8. fs.TimeSeparator := ':';
  9. fs.DecimalSeparator:='.';
  10. fs.ShortTimeFormat := 'hh:nn:ss.zzz';
  11. tt := StrToTime('00:09:44.8', fs); // <-- note seconds separated by :
  12. writeln(FormatDateTime('hh:nn:ss.zzz',tt));
  13. writeln(FormatDateTime('nn:ss:zzz',tt));
  14. end./code]
  15.  
« Last Edit: September 01, 2016, 08:39:41 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Boboxx

  • New member
  • *
  • Posts: 9
Re: StrToTime - Not a valid time
« Reply #2 on: August 31, 2016, 09:12:25 pm »
tt := StrToTime('09:44:8', fs);

09 = Min
44 = Sec
8 = MSec

I have a csv file that looks like this:
Plate,Time
2,00:09:30.430
12,00:09:44.782
19,00:10:05.764
48,00:10:40.490
50,00:10:42.970
17,00:10:44.016
66,00:10:46.387
36,00:10:49.210
43,00:10:53.890
11,00:10:55.747
56,00:11:04.046
32,00:11:08.710
7,00:11:09.568
62,00:11:26.635
5,00:11:40.145
18,00:11:41.315
4,00:11:43.795
40,00:11:45.215
41,00:11:46.307

Thaddy

  • Hero Member
  • *****
  • Posts: 18676
  • Jungle wars. And failing health it seems.
Re: StrToTime - Not a valid time
« Reply #3 on: August 31, 2016, 09:24:03 pm »


09 = Min
44 = Sec
8 = MSec
And
00 = hours
tt := StrToTime('00:09:44:8', fs);

This is simply programmer error.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8835
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: StrToTime - Not a valid time
« Reply #4 on: September 01, 2016, 12:34:36 am »
This is sample case of how important to read the documentation before asking a question.
Quote
If two numbers are given... <click the link above to read the rest>
« Last Edit: September 01, 2016, 12:48:19 am by Leledumbo »

Thaddy

  • Hero Member
  • *****
  • Posts: 18676
  • Jungle wars. And failing health it seems.
Re: StrToTime - Not a valid time
« Reply #5 on: September 01, 2016, 08:39:16 am »
I have adapted my code example a bit to show you how you can display in format minutes,seconds, milliseconds format.
Your mask uses mm which is wrong, that means months You should nn for minutes.
The other way around does not work, to convert to datetime you still have to provide the hours too.
See my revised example, th output of which is now:
Code: [Select]
00:09:44.008
09:44:008
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

balazsszekely

  • Guest
Re: StrToTime - Not a valid time
« Reply #6 on: September 01, 2016, 08:51:24 am »
I would go with TryStrToTime function instead. The function check for errors internally.
Code: Pascal  [Select][+][-]
  1. var
  2.   fs:TFormatSettings;
  3.   tt:TDateTime;
  4. begin
  5.   fs.TimeSeparator := ':';
  6.   fs.DecimalSeparator:='.';
  7.   fs.ShortTimeFormat := 'hh:nn:ss.zzz';
  8.   if TryStrToTime('00:09:44.888', tt, fs) then
  9.     ShowMessage(FormatDateTime('hh:nn:ss.zzz',tt))
  10.   else
  11.     ShowMessage('Cannot convert string to time!');
  12. end;
  13.  

Boboxx

  • New member
  • *
  • Posts: 9
Re: StrToTime - Not a valid time
« Reply #7 on: September 01, 2016, 02:42:14 pm »
Thank you everyone, I was able to load my times :)

CM630

  • Hero Member
  • *****
  • Posts: 1579
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] StrToTime - Not a valid time
« Reply #8 on: April 14, 2022, 12:00:36 pm »

I tried
Code: Pascal  [Select][+][-]
  1. StrToTime ('17:00:41,038486480712890625');
but I got "17:00:41,038486480712890625 is not a valid time.".
Then I tried

Code: Pascal  [Select][+][-]
  1. ShortTimeFormat:='hh:nn:ss.zzzzzzzzzzzzzzzzzz';
  2. StrToTime ('17:00:41,038486480712890625');

but I got the same error again.

Code: Pascal  [Select][+][-]
  1. StrToTime ('17:00:41,038');
works just fine.
I will find a workaround, but I wonder if there is a bug in fpc?


Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: [SOLVED] StrToTime - Not a valid time
« Reply #9 on: April 14, 2022, 01:21:48 pm »
Hi

You are not allowed to use more than 3 digits for the milliseconds due to the fact that there is the maximum length in the formatstring of zzz.

As you are working outside the definition I don't know if this is a bug.

Workaround:

Split the time string into hh:nn:ss and the milliseconds.
Use StrToFloat for the ms.
Divide it by (24*60*60*1000).
Add it to your time.

Winni

Zvoni

  • Hero Member
  • *****
  • Posts: 3226
Re: [SOLVED] StrToTime - Not a valid time
« Reply #10 on: April 14, 2022, 03:18:19 pm »
and check your decimal separator between seconds and milliseconds......
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

wp

  • Hero Member
  • *****
  • Posts: 13328
Re: StrToTime - Not a valid time
« Reply #11 on: April 14, 2022, 05:20:15 pm »
Code: Pascal  [Select][+][-]
  1. tt := StrToTime('00:09:44.8');
  2.  

Be very careful with the fractional part of the seconds if it does not consist of three digits. This part is the count of milliseconds rather than a mathematical decimal fraction. So, above time string "00:09:44.8" does not mean "9 minutes 44 seconds and 800 milliseconds" - no, it means "9 minutes 44 seconds and 8 milliseconds".

Code: Pascal  [Select][+][-]
  1. program dt;
  2. uses
  3.   SysUtils;  
  4. procedure SplitTimeString(Str: String);
  5. var
  6.   fs: TFormatSettings;
  7.   t: TDateTime;
  8.   h, m, s, ms: Word;
  9. begin
  10.   fs := DefaultFormatSettings;
  11.   fs.DecimalSeparator := '.';
  12.   t := StrToTime(Str, fs);
  13.   DecodeTime(t, h,m,s,ms);
  14.   WriteLn(Str, ' --> ', h, ' hours ', m, ' minutes ', s, ' seconds ', ms, ' milliseconds');
  15. end;
  16.  
  17. begin
  18.   SplitTimeString('00:09:44.8');
  19.   SplitTimeString('00:09:44.81');
  20.   SplitTimeString('00:09:44.812');
  21.   SplitTimeString('00:09:44.008');
  22.   SplitTimeString('00:09:44.081');
  23. end.
« Last Edit: April 14, 2022, 05:29:59 pm by wp »

CM630

  • Hero Member
  • *****
  • Posts: 1579
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: [SOLVED] StrToTime - Not a valid time
« Reply #12 on: April 15, 2022, 08:52:33 am »
...Workaround:

Split the time string into hh:nn:ss and the milliseconds.
Use StrToFloat for the ms.
Divide it by (24*60*60*1000).
Add it to your time.
...

I did:
Code: Pascal  [Select][+][-]
  1. function StringToTime(aString: string; DecSeparator: char): TDateTime;
  2. var
  3.   fs:TFormatSettings;
  4. begin
  5.   fs.DecimalSeparator:=DecSeparator;
  6.   fs.TimeSeparator := ':';
  7.   if pos(DecSeparator,aString)=0
  8.     then Result:= StrToTime (aString)
  9.   else
  10.   begin
  11.     fs.ShortTimeFormat := 'hh:nn:ss.zzz';
  12.     Result:= StrToTime (aString.split([DecSeparator])[0],fs)
  13.           + StrToFloat('0' + DecSeparator + aString.split([DecSeparator])[1],fs)/86400;
  14.   end; //else
  15. end;
  16.  
It works, but for some reason, an exception was shown the first (only the first ?!?!?) time when I closed the app.

Quote from: wp
Be very careful with the fractional part of the seconds if it does not consist of three digits. This part is the count of milliseconds rather than a mathematical decimal fraction. So, above time string "00:09:44.8" does not mean "9 minutes 44 seconds and 800 milliseconds" - no, it means "9 minutes 44 seconds and 8 milliseconds".

Do you have an idea what „17:00:41,038486480712890625“ could mean? Because of the leading zero after the comma, I assume that this should be 0,038486480712890625 seconds but such a long value still seems odd.
« Last Edit: April 15, 2022, 10:28:20 am by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

wp

  • Hero Member
  • *****
  • Posts: 13328
Re: [SOLVED] StrToTime - Not a valid time
« Reply #13 on: April 15, 2022, 10:47:56 am »
It is the decimal fraction of seconds. But as I said, this is not compatible with the time/string conversion routines which require the number of milliseconds after the decimal separator, i.e. a number between 0 and 999. As winni suggested, split off the decimal part and handle the parts differently - the part before the decimal separator goes into the StrToTime function, and the time after the decimal separator is considered as a decimal fraction and - after prepending '0'+DecSep - goes into StrToFloat (not StrToTime!):

Code: Pascal  [Select][+][-]
  1. function StringToTime(aString: string; DecSeparator: char): TDateTime;
  2. var
  3.   p: Integer;
  4.   fs: TFormatSettings;
  5.   ms_value: Double;
  6. begin
  7.   p := pos(DecSeparator, aString);
  8.   if p > 0 then
  9.   begin
  10.     fs := FormatSettings;
  11.     fs.DecimalSeparator := DecSeparator;
  12.     // Convert the fractional seconds to a floating point number, normalized to 1 day = 24*60*60 seconds.
  13.     ms_value := StrToFloat('0' + DecSeparator + Copy(aString, p+1), fs) / (24*60*60);
  14.     // remove the fractional seconds from the input string
  15.     aString := Copy(aString, 1, p-1);
  16.   end else
  17.     // No milliseconds in the input string
  18.     ms_value := 0;
  19.   // Convert the string up to the decimal separator to a number and add the value corresponding to the milliseconds
  20.   Result := StrToTime(aString) + ms_value;
  21. end;

Or, if you allow the milliseconds to be off by 1 (i.e. 0.384864 becomes 384 ms rather than 385 ms), you can skip the string-to-float conversion of the ms part:
Code: Pascal  [Select][+][-]
  1. function StringToTime(aString: string; DecSeparator: char): TDateTime;
  2. var
  3.   p: Integer;
  4.   fs: TFormatSettings;
  5. begin
  6.   fs := FormatSettings;
  7.   fs.DecimalSeparator := DecSeparator;
  8.   p := pos(DecSeparator, aString);
  9.   if p > 0 then
  10.   begin
  11.     if Length(AString) >= p+3 then
  12.       // Truncate the string to 3 digits after the decimal separator
  13.       SetLength(AString, p+3)
  14.     else
  15.       // Append trailing '0' if there are less than 3 digits after the decimal separator.
  16.       while Length(AString) < p + 3 do AString := AString + '0';
  17.   end;
  18.   Result := StrToTime(AString, fs);
  19. end;
« Last Edit: April 15, 2022, 02:01:13 pm by wp »

 

TinyPortal © 2005-2018