### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Problems translating Milliseconds from String to DateTime  (Read 539 times)

#### ASBzone

• Sr. Member
• Posts: 327
##### Problems translating Milliseconds from String to DateTime
« on: October 11, 2019, 07:58:48 pm »
The code snippet below shows an issue with how the milliseconds in a TDateTime variable are interpreted:

The following should be identical:
01:02:03.1
01:02:03.10
01:02:03.100

But the first will be converted to ".001" and the second to ".010"

Likewise, ".02" and ".020" should be treated the same, but are not.  Leading zeros are ignored, up to a total of 4 digits provided.

Code: Pascal  [Select]
1. { This program demonstrates a problem with how milliseconds are converted from STRING to DATETIME }
2.
3. Uses sysutils;
4.
5. Procedure TestStr (S : String);
6. begin
7.   Writeln (S:25, ' .... ', FormatDateTime('mm/dd/yyyy hh:nn:ss.zz', StrToDateTime(S)));
8. end;
9.
10. Begin
11.   TestStr(DateTimeToStr(Now));
12.   writeln;
13.   TestStr('5/5/1999 15:50:10.1');
14.   TestStr('5/5/1999 15:50:10.10');
15.   TestStr('5/5/1999 15:50:10.100');
16.   writeln;
17.   TestStr('1/1/2019 15:50:10.2');
18.   TestStr('1/1/2019 15:50:10.02');
19.   TestStr('1/1/2019 15:50:10.020');
20.   TestStr('1/1/2019 15:50:10.0200');
21. End.
22.

Is anyone seeing the same thing?

This is with FPC/Lazarus Fixes branch (see sig for current build)
« Last Edit: October 11, 2019, 09:21:13 pm by ASBzone »
-ASB: https://www.BrainWaveCC.com

Lazarus v2.0.7 r62681 / FPC v3.2.0-beta-r44391 (via FpcUpDeluxe) -- Windows 64-bit install w/32-bit cross-compile
Primary System: Windows 10 Pro x64, Version 1909 (Build 18363.720)
Other Systems: Windows 10 Pro x64, Version 1909 or greater

#### ASBzone

• Sr. Member
• Posts: 327
##### Re: Problems translating Milliseconds from String to DateTime
« Reply #1 on: October 11, 2019, 09:32:32 pm »
It looks like the issue is that miliseconds are decoded directly as integers without accounting for them being fractional.

Currently, I'm working around the issue by grabbing the millisecond portion as a string, padding it to 3 characters, and then evaluating those three characters as an integer before recoding it.

Code: Pascal  [Select]
1. // This program demonstrates a problem with how milliseconds are converted from STRING to DATETIME, with a fix
2.
3. Uses sysutils, strutils, dateutils;
4.
5. const
6.   DateTimeFmtExt = 'mm/dd/yyyy hh:nn:ss.zz';
7.
8.
9. function StrToDateTime2(const DateTimeString: string): TDateTime;
10.
11. var
12.   MyDateTime: TDateTime;
13.   MyDateTimeStr: string;
14.   NewMS: Word;
15.
16. begin
17.   MyDateTime := SysUtils.StrToDateTime(DateTimeString);
18.   NewMS      := StrToInt(LeftStr(ExtractDelimited(2, DateTimeString, ['.']) + '000', 3));
19.   if (NewMS = 0) then
20.     MyDateTimeStr := FormatDateTime(DateTimeFmtExt, MyDateTime)
21.   else
22.     MyDateTimeStr := FormatDateTime(DateTimeFmtExt, RecodeMilliSecond(MyDateTime, NewMS));
23.
24.   Result := SysUtils.StrToDateTime(MyDateTimeStr);
25. end;
26.
27.
28. Procedure TestStr (S : String);
29. begin
30.   Writeln ('Old: ', S:25, ' .... ', FormatDateTime(DateTimeFmtExt, StrToDateTime(S)));
31.   Writeln ('New: ', S:25, ' .... ', FormatDateTime(DateTimeFmtExt, StrToDateTime2(S)));
32.   Writeln;
33. end;
34.
35.
36. Begin
37.   TestStr(DateTimeToStr(Now));
38.   writeln;
39.   TestStr('5/5/1999 15:50:10.1');
40.   TestStr('5/5/1999 15:50:10.10');
41.   TestStr('5/5/1999 15:50:10.100');
42.   writeln;
43.   TestStr('1/1/2019 15:50:10.2');
44.   TestStr('1/1/2019 15:50:10.02');
45.   TestStr('1/1/2019 15:50:10.020');
46.   TestStr('1/1/2019 15:50:10.0200');
47. End.
-ASB: https://www.BrainWaveCC.com

Lazarus v2.0.7 r62681 / FPC v3.2.0-beta-r44391 (via FpcUpDeluxe) -- Windows 64-bit install w/32-bit cross-compile
Primary System: Windows 10 Pro x64, Version 1909 (Build 18363.720)
Other Systems: Windows 10 Pro x64, Version 1909 or greater

#### ASerge

• Hero Member
• Posts: 1503
##### Re: Problems translating Milliseconds from String to DateTime
« Reply #2 on: October 12, 2019, 12:01:31 am »
The following should be identical:
01:02:03.1
01:02:03.10
01:02:03.100

But the first will be converted to ".001" and the second to ".010"

Likewise, ".02" and ".020" should be treated the same, but are not.  Leading zeros are ignored, up to a total of 4 digits provided.
zzz is not an ISO 8601 SSS format (which is a fraction of a second), but milliseconds. In the documentation z is a millisecond. So .1 is 1 millisecond, not 1000, not 100 or other. And it is compatible with Delphi.
« Last Edit: October 12, 2019, 12:03:41 am by ASerge »

#### ASerge

• Hero Member
• Posts: 1503
##### Re: Problems translating Milliseconds from String to DateTime
« Reply #3 on: October 12, 2019, 12:15:00 am »
Code: Pascal  [Select]
1. ...
2.   TestStr('5/5/1999 15:50:10.1');
The code will be more correct if the time format, which depends on user settings, specify explicitly. And date at all to exclude:
Code: Pascal  [Select]
1. {\$MODE OBJFPC}
2. {\$APPTYPE CONSOLE}
3. {\$LONGSTRINGS ON}
4.
5. uses SysUtils;
6.
7. procedure TestStr(const S: string);
8. var
9.   FS: TFormatSettings;
10. begin
11.   FS := DefaultFormatSettings;
12.   FS.LongTimeFormat := 'hh:nn:ss.zzz';
13.   FS.TimeSeparator := ':';
14.   Writeln(S: 15, ' .... ', FormatDateTime('hh:nn:ss.zz', StrToTime(S, FS), FS));
15. end;
16.
17. begin
18.   TestStr(TimeToStr(Time));
19.   Writeln;
20.   TestStr('15:50:10.1');
21.   TestStr('15:50:10.10');
22.   TestStr('15:50:10.100');
23.   Writeln;
24.   TestStr('15:50:10.2');
25.   TestStr('15:50:10.02');
26.   TestStr('15:50:10.020');
27.   TestStr('15:50:10.0200');
29. end.

#### ASBzone

• Sr. Member
• Posts: 327
##### Re: Problems translating Milliseconds from String to DateTime
« Reply #4 on: October 13, 2019, 03:32:38 am »
Thanks, ASerge

Will check this out and let you know.

Good point about the ISO standard.  I did assume Delphi compatibility, though.

When I run it against the output that Windows has for the %TIME% variable (which displays only 2 decimal places), it is clear that the correct answer on Windows is for that fractional part to be padded. (i.e.  .24 = .240, not .024)
-ASB: https://www.BrainWaveCC.com

Lazarus v2.0.7 r62681 / FPC v3.2.0-beta-r44391 (via FpcUpDeluxe) -- Windows 64-bit install w/32-bit cross-compile
Primary System: Windows 10 Pro x64, Version 1909 (Build 18363.720)
Other Systems: Windows 10 Pro x64, Version 1909 or greater

• Sr. Member
• Posts: 327