Recent

Author Topic: StrToDateTime rise EConvertError...  (Read 10260 times)

Shebuka

  • Sr. Member
  • ****
  • Posts: 425
StrToDateTime rise EConvertError...
« on: October 11, 2011, 04:10:49 pm »
Hi all,
i need to import from time to time some units from windows version of ours application (it is always the first to get new functionalities) and i got to a point that i can't understand why a function of an utility unit crashes. The function in question must convert from String received in a message from Windows client to TDateTime with StrToDateTime()

The call:
Code: [Select]
    self.Timestamp := UT_StrToDate(UT_msg_unescape(fields[3]));         //fields[3] is '2011-10-11 15-53'I have also tried this:
Code: [Select]
    self.Timestamp := UT_StrToDate(Utf8ToAnsi(ISO_8859_1ToUTF8(UT_msg_unescape(fields[3]))));
Utility.pas
Code: [Select]
...

function UT_StrToDate(str: string): TDateTime;
var frmstg: TFormatSettings;
begin
  //GetLocaleFormatSettings(0, frmstg);       //This one is not present in Lazarus...
  frmstg.DateSeparator := '-';
  frmstg.ShortDateFormat := 'yyyy-mm-dd';
  frmstg.TimeSeparator := '-';
  frmstg.LongTimeFormat := 'hh-nn';

  result := StrToDateTime(str, frmstg);        // <-- Here i get EConvertError
end;

Please help, what is the problem???

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 9091
  • FPC developer.
Re: StrToDateTime rise EConvertError...
« Reply #1 on: October 11, 2011, 04:48:46 pm »
You run the strtodate (what is the UT_ stuff about ?) essentially without initializing the tformatsettings. Anything can happen.

Econverterrror is a normal exception, thrown when the date in the string and formatsettings don't match in format.

These routines are all documented.

Shebuka

  • Sr. Member
  • ****
  • Posts: 425
Re: StrToDateTime rise EConvertError...
« Reply #2 on: October 11, 2011, 06:17:19 pm »
You run the strtodate (what is the UT_ stuff about ?) essentially without initializing the tformatsettings. Anything can happen.

Econverterrror is a normal exception, thrown when the date in the string and formatsettings don't match in format.

These routines are all documented.
UT_ stays for UTility and is added to avoid conflict with any of default system functions. Inside UT_StrToDate i initialize the TFormatSettings parameters listened here: http://www.delphibasics.co.uk/RTL.asp?Name=StrToDateTime

Also StrToDateTime rise the EConvertError exception like in 70% of strings i pass to it.

Shebuka

  • Sr. Member
  • ****
  • Posts: 425
Re: StrToDateTime rise EConvertError...
« Reply #3 on: October 13, 2011, 10:03:21 am »
Still don't know why it fails so randomly, so i fixed it this way...

Code: [Select]
function UT_StrToDate(str: string): TDateTime;
var frmstg: TFormatSettings;
begin
  //GetLocaleFormatSettings(0, frmstg);
  frmstg.DateSeparator := '-';
  frmstg.ShortDateFormat := 'yyyy-mm-dd';
  frmstg.TimeSeparator := '-';
  frmstg.LongTimeFormat := 'hh-nn';

  if not TryStrToDateTime(str, Result, frmstg) then
    Result := Now();
end;

It'n not really the same behavior i need, but for now it's ok.

Shebuka

  • Sr. Member
  • ****
  • Posts: 425
Re: StrToDateTime rise EConvertError...
« Reply #4 on: October 19, 2011, 06:38:10 pm »
I found that this actually a fpc rtl bug... look at this:

Quote
function TryStrToDateTime(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean;
var
  I: integer;
  dtdate, dttime :TDateTime;
begin
  result:=false;
  I:=Pos(FormatSettings.TimeSeparator,S);
  If (I>0) then
    begin
      While (I>0) and (S[ I ]<>' ') do
        Dec(I);
      If I>0 then
        begin
          if not TryStrToDate(Copy(S,1,I-1),dtdate,Formatsettings) then
            exit;
          if not TryStrToTime(Copy(S,i+1, Length(S)-i),dttime,Formatsettings) then
            exit;
          Value:=ComposeDateTime(dtdate,dttime);
          result:=true;
        end
      else
         result:=TryStrToTime(s,Value,Formatsettings);
    end
  else
    result:=TryStrToDate(s,Value,Formatsettings);
end;

if you use this string '2011-10-11 15-53' and set DateSeparator := '-' and TimeSeparator := '-', Pos will give you first occurrence of TimeSeparator inside string, wich is in date part!!! so after while cycle you get I := 0 and TryStrToTime fails because it expects only time string and not datetime.


There is also similar bug in other time functions like:

Quote
function StrToDateTime(const s: AnsiString; const UseFormat : TFormatSettings): TDateTime;
var
  I: integer;
begin
  I:=Pos(TimeSeparator,S);
  If (I>0) then
    begin
    While (I>0) and (S[ I ]<>' ') do
      Dec(I);
    If I>0 then
      result:=ComposeDateTime(StrToDate(Copy(S,1,I-1),UseFormat.ShortDateFormat,UseFormat.DateSeparator),
                              StrToTime(Copy(S,i+1, Length(S)-i),UseFormat.TimeSeparator))
    else
      result:=StrToTime(S,UseFormat.TimeSeparator)
    end
  else
    Result:=StrToDate(S,UseFormat.ShortDateFormat,UseFormat.DateSeparator);
end;

Here you can see that it doesn't use the passed UseFormat but default TimeSeparator for Pos. This one will fail if you pass as string something that has DateSeparator same as default TimeSeparator... I use '-' as TimeSeparator so Pos will return I = 0 and call StrToDate that fails because expect only date in string and not datetime.

Edit: reported as http://bugs.freepascal.org/bug_view_advanced_page.php?bug_id=20522 and http://bugs.freepascal.org/bug_view_advanced_page.php?bug_id=20523
« Last Edit: October 19, 2011, 06:56:21 pm by Shebuka »

 

TinyPortal © 2005-2018