Recent

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

ASBzone

  • Sr. Member
  • ****
  • Posts: 327
  • Automation leads to relaxation...
    • BrainWaveCC Utilities
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
  • Automation leads to relaxation...
    • BrainWaveCC Utilities
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');
  28.   Readln;
  29. end.

ASBzone

  • Sr. Member
  • ****
  • Posts: 327
  • Automation leads to relaxation...
    • BrainWaveCC Utilities
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

ASBzone

  • Sr. Member
  • ****
  • Posts: 327
  • Automation leads to relaxation...
    • BrainWaveCC Utilities
Re: Problems translating Milliseconds from String to DateTime
« Reply #5 on: October 13, 2019, 09:40:34 pm »
Ultimately, this is part of my routines for capturing and calculating execution durations of processes in Windows Shell Scripts, so I'm going to stick with my updates that pad the the decimal places to be compatible with Microsoft Windows time.
-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