Recent

Author Topic: [RESOLVED] Problems translating Milliseconds from String to DateTime  (Read 3129 times)

ASBzone

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
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: July 24, 2020, 11:54:53 pm by ASBzone »
-ASB: https://www.BrainWaveCC.com/

Lazarus v2.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

ASBzone

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
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.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

ASerge

  • Hero Member
  • *****
  • Posts: 2242
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: 2242
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

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
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.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

ASBzone

  • Hero Member
  • *****
  • Posts: 678
  • Automation leads to relaxation...
    • Free Console Utilities for Windows (and a few for Linux) from BrainWaveCC
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.2.7-ada7a90186 / FPC v3.2.3-706-gaadb53e72c
(Windows 64-bit install w/Win32 and Linux/Arm cross-compiles via FpcUpDeluxe on both instances)

My Systems: Windows 10/11 Pro x64 (Current)

 

TinyPortal © 2005-2018