Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2009-10

Why has StrToDate() failing under FPC 2.3.1 (64bit)

17 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Graeme Geldenhuys

Compiling the project works fine under FPC 2.3.1 (linux 64bit), but running it, i get a EConvertError and I don't know why.

I am telling sysutils what LongDateFormat is like, but it still fails. Any ideas?

-----------------------
program project1;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  ,SysUtils;
var
  s: string;
  d: TDateTime;
begin
  LongDateFormat := 'dd/mm/yyyy';
  s := '03/06/2004 12:45:15:000';
  d := StrToDate(s);
end.
-----------------------
Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 5 lines
Compiling the project works fine under FPC 2.3.1 (linux 64bit), but running it, i get a EConvertError and I don't know why. I am telling sysutils what LongDateFormat is like, but it still fails. Any ideas?

It is documented:

1. StrToDate uses shortdateformat.

2. StrToDate DOES NOT use shortdateformat to check the actual format; because it accepts only dates of the form N1/N2/N3
- it uses ShortDateFormat ONLY to determine the order of y,m,d
- it uses DateSeparator to determine the actual date separator to use instead of /

You make a common assumption, which is mistaken:
StrToDate(DateToStr(date)) generally does not work.

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt
Michael Van Canneyt wrote
You make a common assumption, which is mistaken: StrToDate(DateToStr(date)) generally does not work.

Crap! And that is pretty much what the tiOPF unit test is testing for.

So why is StrToDate() so different to Delphi? In Delphi, the above mentioned code works.

And to make matters worse, the tiOPF code is compiled with "$mode delphi" enabled.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: It is documented: 1. StrToDate uses shortdateformat. 2. StrToDate DOES NOT use…

On 20/10/2009, Michael Van Canneyt >

Show quoted text 7 lines
1. StrToDate uses shortdateformat. 2. StrToDate DOES NOT use shortdateformat to check the actual format; because it accepts only dates of the form N1/N2/N3 - it uses ShortDateFormat ONLY to determine the order of y,m,d - it uses DateSeparator to determine the actual date separator to use instead of /

So how come I still can't get this to work... I tried the following and various other options. Every single attempt gives me a conversion error. How am I supposed to solve this?

var
  s: string;
  d: TDateTime;
begin
// ShortDateFormat := 'dd/mm/yyyy';
// ShortDateFormat := 'dd/mm/yy';
  ShortDateFormat := 'd/m/y';
  DateSeparator := '/';
//  s := '03/06/04 12:45:15:000';
  s := '03/06/2004 12:45:15:000';
  d := StrToDate(s);
end.
Show quoted text 9 lines
You make a common assumption, which is mistaken: StrToDate(DateToStr(date)) generally does not work. Michael. _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys: Crap! And that is pretty much what the tiOPF unit test is testing for. So why is…
Graeme Geldenhuys wrote 9 lines
On 20/10/2009, Michael Van Canneyt wrote: > > You make a common assumption, which is mistaken: > StrToDate(DateToStr(date)) generally does not work. Crap! And that is pretty much what the tiOPF unit test is testing for. So why is StrToDate() so different to Delphi? In Delphi, the above mentioned code works.

Pure coincidence.

See the help of StrToDate in Delphi, it works 100% the same - as documented. Maybe they are more forgiving concerning the time part.

And to make matters worse, the tiOPF code is compiled with "$mode delphi" enabled.

That should have no effect whatsoever.

Michael.

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys: On 20/10/2009, Michael Van Canneyt > So how come I still can't get this to work... I…
Graeme Geldenhuys wrote 12 lines
On 20/10/2009, Michael Van Canneyt > > 1. StrToDate uses shortdateformat. > > 2. StrToDate DOES NOT use shortdateformat to check the actual format; > because it accepts only dates of the form N1/N2/N3 > - it uses ShortDateFormat ONLY to determine the order of y,m,d > - it uses DateSeparator to determine the actual date separator to use > instead of / So how come I still can't get this to work... I tried the following and various other options. Every single attempt gives me a conversion error. How am I supposed to solve this?

Strip the time part.

You are feeding a date/time pair to something that expects ONLY a date.

Michael.

Show quoted text 40 lines
var s: string; d: TDateTime; begin // ShortDateFormat := 'dd/mm/yyyy'; // ShortDateFormat := 'dd/mm/yy'; ShortDateFormat := 'd/m/y'; DateSeparator := '/'; // s := '03/06/04 12:45:15:000'; s := '03/06/2004 12:45:15:000'; d := StrToDate(s); end. > > You make a common assumption, which is mistaken: > StrToDate(DateToStr(date)) generally does not work. > > Michael. > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal > -- Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/ _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: It is documented: 1. StrToDate uses shortdateformat. 2. StrToDate DOES NOT use…
Michael Van Canneyt wrote
It is documented:

and the documented example "ex19.pp" causes the same error!

--------------------------
$ cp /opt/fpcdocs_svn/sysutex/ex19.pp ex19.pas
$ fpc ex19.pas
Free Pascal Compiler version 2.3.1 [2009/10/08] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl
Target OS: Linux for x86-64
Compiling ex19.pas
Linking ex19
19 lines compiled, 0.1 sec

$ ./ex19
ShortDateFormat d/m/y
20-10-09 : 20-10-09
An unhandled exception occurred at $000000000042D54F : EConvertError : "05/05/1999" is not a valid date format $000000000042D54F
$00000000004002A1
$0000000000400424

---------------------------

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: Strip the time part. You are feeding a date/time pair to something that expects ONLY a…
Michael Van Canneyt wrote
Strip the time part. You are feeding a date/time pair to something that expects ONLY a date.

Surely it must be able to handle that? Delphi does. Extract what it needs and leave/ignore the rest?

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys
Graeme Geldenhuys wrote 11 lines
On 20/10/2009, Michael Van Canneyt wrote: > > Strip the time part. > > You are feeding a date/time pair to something that expects ONLY a date. Surely it must be able to handle that? Delphi does. Extract what it needs and leave/ignore the rest? From the Delphi help:

----------------------------------------------------------------- Call StrToDate to parse a string that specifies a date. If S does not contain a valid date, StrToDate raises an EConvertError exception.

S must consist of two or three numbers, separated by the character defined by the DateSeparator global variable or its TFormatSettings equivalent. The order for month, day, and year is determined by the ShortDateFormat global variable or its TFormatSettings equivalent--possible combinations are m/d/y, d/m/y, and y/m/d.

If S contains only two numbers, it is interpreted as a date (m/d or d/m) in the current year.

Year values between 0 and 99 are converted using the TwoDigitYearCenturyWindow. This value is stored either in a global variable (first form) or as a field in the FormatSettings parameter (second form) See "Currency and Date-Time Formatting Variables" for more information.

The first form of StrToDate is not thread-safe, because it uses localization information contained in global variables. The second form of StrToDate, which is thread-safe, refers to localization information contained in the FormatSettings parameter. Before calling the thread-safe form of StrToDate, you must populate FormatSettings with localization information. To populate FormatSettings with a set of default locale values, call GetLocaleFormatSettings.
-------------------------------------------------------------------

First lines say it all. "dd/mm/yyy hh:nn" is not supposed to work. If it does, it just means that Delphi's implementation is more forgiving.

There are countries (Belgium among them) which use space as a date separator char, so don't try a 'strip all to the first space' :)

Michael.

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys: and the documented example "ex19.pp" causes the same error! -------------------------- $…
Graeme Geldenhuys wrote 24 lines
On 20/10/2009, Michael Van Canneyt wrote: > > It is documented: and the documented example "ex19.pp" causes the same error! -------------------------- $ cp /opt/fpcdocs_svn/sysutex/ex19.pp ex19.pas $ fpc ex19.pas Free Pascal Compiler version 2.3.1 [2009/10/08] for x86_64 Copyright (c) 1993-2009 by Florian Klaempfl Target OS: Linux for x86-64 Compiling ex19.pas Linking ex19 19 lines compiled, 0.1 sec $ ./ex19 ShortDateFormat d/m/y 20-10-09 : 20-10-09 An unhandled exception occurred at $000000000042D54F : EConvertError : "05/05/1999" is not a valid date format $000000000042D54F $00000000004002A1 $0000000000400424

The error is correct, since 05/05/1999 is not a valid date. It should use - instead of / . I've adapted the example.

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: ----------------------------------------------------------------- Call StrToDate to parse…
Michael Van Canneyt wrote
----------------------------------------------------------------- Call StrToDate to parse a string that specifies a date. If S does

[...]

First lines say it all. "dd/mm/yyy hh:nn" is not supposed to work.

That's up for discussion! :-) It says the string must specify a date. It does not say it must ONLY specify a date. It parses the string from the left extracting what it needs, once it has all required information to build a date, it ignores the rest.

Also, do I specify a date from the 17th century? Does StrToDate() limit itself forever to only assume 19xx & 20xxx dates?

Why does StrToDate() use the ShortDateFormat - didn't we learn our lesson with the Y2K bug?

PS:
Oh and a nice hidden little features (I couldn't find documentation for). When you specify a date format as 'yyyy/mm/dd' or dd/mm/yy etc... The '/' character is NOT the separator! The '/' in that formatting string means the separator specified by the global DateSeparator variable.

Yet if you specify 'yyyy-mm-dd', then the '-' character IS the date separator to use, ignoring global DateSeparator variable.

Maybe the FPC docs could be extended to include this little gem. By the way, I tested the above theory with Kylix 3 and Delphi 7.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: The error is correct, since 05/05/1999 is not a valid date. It should use - instead of /…
Michael Van Canneyt wrote
The error is correct, since 05/05/1999 is not a valid date. It should use - instead of / . I've adapted the example.

But couldn't you simply have forced DateSeparator to "-".

Also could we try not to have such an obscure example - using day and month as the same value.! It would be much better and informative, if the day value was greater than 12. Clearly distinguish between day and month values.

eg:

Begin
  Writeln ('ShortDateFormat ',ShortDateFormat);
  TestStr(DateTimeToStr(Date));
  TestStr('16'+DateSeparator+'05'+DateSeparator+'1999');
  TestStr('16'+DateSeparator+'9');
  TestStr('16');
End.

Now you can clearly see when and where the day and month are specified. If this causes issues on various locales, then maybe the example could be hard-coded to the International ISO 8601 date format.

eg:

Begin
  ShortDateFormat = 'y-m-d';
{or maybe even better
  ShortDateFormat = 'y/m/d';
  DateSeparator = '-';
  TestStr(1999-05-16');

}

  Writeln ('ShortDateFormat ',ShortDateFormat);
  TestStr(DateTimeToStr(Date));
  TestStr('16'+DateSeparator+'05'+DateSeparator+'1999');
  TestStr('16'+DateSeparator+'9');
  TestStr('16');
End.
Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Graeme Geldenhuys: [...] That's up for discussion! :-) It says the string must specify a date. It does not…
Graeme Geldenhuys wrote
PS: Oh and a nice hidden little features (I couldn't find documentation for). When you specify a date format as 'yyyy/mm/dd' or dd/mm/yy etc... The '/' character is NOT the separator!

Correction, that applies to FormateDateTime(), not StrToDate(). I got a bit confused.

Here is an example of what I meant:

-----------------------------
procedure TestDate(S: string);
begin
 writeln(s + ' formatting  => ' + FormatDateTime(s, Date));
end;
begin
 DateSeparator := '?';  // force separator to ? character
 Writeln('DateSeparator = ', DateSeparator);
 Writeln('-------');
 TestDate('yyyy-mm-dd');
 TestDate('yyyy~mm~dd');
 TestDate('yyyy/mm/dd');
 TestDate('yyyy''/''mm''/''dd');
end.

-----------------------------

And here follows the output:

c:\temp>project1
DateSeparator = ?
-------
yyyy-mm-dd formatting => 2009-10-20
yyyy~mm~dd formatting => 2009~10~20
yyyy/mm/dd formatting => 2009?10?20
yyyy'/'mm'/'dd formatting => 2009/10/20

As you can see. If you want to force '/' as your date delimiter, irrespective to what DateSeparator is set at, you have to place the the '/' in qoutes so it doesn't get interpreted as a place-holder for DateSeparator. Sneaky code!

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys: [...] That's up for discussion! :-) It says the string must specify a date. It does not…
Graeme Geldenhuys wrote 13 lines
On 20/10/2009, Michael Van Canneyt wrote: > ----------------------------------------------------------------- > Call StrToDate to parse a string that specifies a date. If S does [...] > First lines say it all. "dd/mm/yyy hh:nn" is not supposed to work. That's up for discussion! :-) It says the string must specify a date. It does not say it must ONLY specify a date. It parses the string from the left extracting what it needs, once it has all required information to build a date, it ignores the rest.

I'll adapt the docs and insert the 'only'.

Show quoted text 6 lines
Also, do I specify a date from the 17th century? Does StrToDate() limit itself forever to only assume 19xx & 20xxx dates? Why does StrToDate() use the ShortDateFormat - didn't we learn our lesson with the Y2K bug?

Y2K is not relevant.
My ShortDateFormat is set to dd/mm/yyyy, perfectly Y2K safe.

Only the relative order of y,m,d is needed from shortdateformat. So the actual number, 1,2 or 4 ys is not relevant. You are still thinking that it uses the actual dateformat, when it does not.

Show quoted text 6 lines
PS: Oh and a nice hidden little features (I couldn't find documentation for). When you specify a date format as 'yyyy/mm/dd' or dd/mm/yy etc... The '/' character is NOT the separator! The '/' in that formatting string means the separator specified by the global DateSeparator variable.

Ehm. This is so since day 1, it's even documented ?

Show quoted text 6 lines
Yet if you specify 'yyyy-mm-dd', then the '-' character IS the date separator to use, ignoring global DateSeparator variable. Maybe the FPC docs could be extended to include this little gem. By the way, I tested the above theory with Kylix 3 and Delphi 7.

It is mentioned in topic 'Date and time formatting characters' of the FPC docs.

Michael.

Reply by email

Michael Van Canneyt
to Graeme Geldenhuys: Correction, that applies to FormateDateTime(), not StrToDate(). I got a bit confused.…
Graeme Geldenhuys wrote 47 lines
On 20/10/2009, Graeme Geldenhuys wrote: > PS: > Oh and a nice hidden little features (I couldn't find documentation > for). When you specify a date format as 'yyyy/mm/dd' or dd/mm/yy > etc... The '/' character is NOT the separator! Correction, that applies to FormateDateTime(), not StrToDate(). I got a bit confused. Here is an example of what I meant: ----------------------------- procedure TestDate(S: string); begin writeln(s + ' formatting => ' + FormatDateTime(s, Date)); end; begin DateSeparator := '?'; // force separator to ? character Writeln('DateSeparator = ', DateSeparator); Writeln('-------'); TestDate('yyyy-mm-dd'); TestDate('yyyy~mm~dd'); TestDate('yyyy/mm/dd'); TestDate('yyyy''/''mm''/''dd'); end. ----------------------------- And here follows the output: c:\temp>project1 DateSeparator = ? ------- yyyy-mm-dd formatting => 2009-10-20 yyyy~mm~dd formatting => 2009~10~20 yyyy/mm/dd formatting => 2009?10?20 yyyy'/'mm'/'dd formatting => 2009/10/20 As you can see. If you want to force '/' as your date delimiter, irrespective to what DateSeparator is set at, you have to place the the '/' in qoutes so it doesn't get interpreted as a place-holder for DateSeparator. Sneaky code!

But perfectly documented...

I agree that it is tricky. I often had to correct code from people who didn't understand this and inserted some kind of formatdatetime('mm/dd/yyy') in an SQL statement and were surprised to see '04 09 2005' in their SQL, which of course generated an error.

Michael.

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: I'll adapt the docs and insert the 'only'. Y2K is not relevant. My ShortDateFormat is set…
Michael Van Canneyt wrote
It is mentioned in topic 'Date and time formatting characters' of the FPC docs.

I blame my mistake on the broken IPF output generated from 'fpdoc'. My new INF help viewer, 'docview', did not find any help on "formatting characters", so I thought it wasn't documented. On closer inspection, fpdoc's IPF output skips "related topics" in the help generated. [added to my list of things to fix in fpdoc] :-)

Looking at the PDF documentation I can now see that it is indeed documented. Another gold star to the documentation writer! ;-)

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email

Graeme Geldenhuys
to Michael Van Canneyt: I'll adapt the docs and insert the 'only'. Y2K is not relevant. My ShortDateFormat is set…
Michael Van Canneyt wrote
Only the relative order of y,m,d is needed from shortdateformat. So the actual number, 1,2 or 4 ys is not relevant. You are still thinking that it uses the actual dateformat, when it does not.

Ah, I get it now! Sorry, I'm was a bit slow there. :-( I now see what you mean.

Regards, - Graeme - _______________________________________________ fpGUI - a cross-platform Free Pascal GUI toolkit http://opensoft.homeip.net/fpgui/

Reply by email