String to TDateTime

Hi everybody.

I'm trying to convert a date in a TEdit in the format dddd dd mmm yyyyy to a TDateTime and an EConvertError stops the application from running. Anybody knows what I'm doing wrong?

A sample code is hereunder for reference.

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

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Date: TDateTime;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  TEdit.Text := 'WEDNESDAY 28 JUN 2006';
  Date := StrToDate(Edit1.Text);
  Label1.Caption := FormatDateTime('dddd dd mmm yyyy',Date);
end;

end.

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

Regards
King_Diamond
LVL 1
King_DiamondAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
mikelittlewoodConnect With a Mentor Commented:
Here is a quick function to change the long date string to a short date string useable for converting to a date

function TForm1.LongDateToShort(sDate: String): String;
var
  i: Integer;
  sl: TStringList;
  sMon: string;
begin
  try
    // split out the long string (assume always same format)
    sl := TStringList.Create;
    sl.Delimiter := ' ';
    sl.DelimitedText := sDate;
    // loop through locale short month names and find index
    for i := 1 to 12 do
      if Uppercase(ShortMonthNames[i]) = Uppercase(sl.Strings[2]) then Break;
    // correct format
    sMon := IntToStr(i);
    if Length(sMon) = 1 then
      sMon := '0' + sMon;
    // rebuild date string
    Result := Trim( sl.Strings[1] + '/' + sMon + '/' + sl.Strings[3] );
  finally
    FreeAndNil(sl)
  end;
end;
0
 
atul_parmarCommented:
First, there are some typo.

  TEdit.Text := 'WEDNESDAY 28 JUN 2006'; >> Should be Edit1.Text := .........
  Date := StrToDate(Edit1.Text); >> Date should not be used as variable name. (it's the name of delphi function)

The string you are passing to the StrToDate might not be formatted as current date time format settings. So you need to pass the date time format when you do the conversion.
e.g.

var
  fs : TFormatSettings;
begin
  GetLocaleFormatSettings(LOCALE_SYSTEM_DEFAULT, fs);
  fs.DateSeparator := >> ;
  fs.ShortDateFormat := >>;
 then you can call
  MyDate := StrToDate(Edit1.Text, fs);
end;

But in your case, above will not work. because the StrToDate function uses the ShortDateTime format and the ShortDateTime format can not have the dddd mmm style. so it will fail.

No wonder ;)
0
 
bjones8888Connect With a Mentor PresidentCommented:
StrToDate has two forms.

1  function StrToDate ( const Date : string ) : TDateTime;
2  function StrToDate ( const Date : string; const FormatSettings : TFormatSettings ) : TDateTime;
 
 
The StrToDate function attempts to convert a date as a string Date into a TDateTime value.  The date string must adhere to the format of the ShortDateFormat value, and use the DateSeparator character to separate the day, month and year values.
 
The default format in the US is month/day/year, but most everywhere else is day/month/year.
 
Omitting the year results in the use of the current year.  

I've never tried using a text representation like you have here to convert directly to TDateTime.  I've always had to parse the string based on location of spaces, and create my own functions, like:


procedure TForm1.Button1Click(Sender: TObject);
begin
  TEdit.Text := 'WEDNESDAY 28 JUN 2006';
  Date := MyStrToDate(Edit1.Text);
  Label1.Caption := FormatDateTime('dddd dd mmm yyyy',Date);
end;

function TForm1.MyStrToDate(sDate: string): TDateTime;
var
  s: string;
  sDayNum, sMonth, sMonthNum, sYear: string;
  iPos: integer;
begin
  s := sDate;

  // Get day
  iPos := Pos(" ", s);
  s := Copy(s, iPos + 1, length(s));     // trims off the day name - not needed
  iPos := Pos(" ", s);
  sDayNum := RTrim(Copy(s, 1, iPos));

  // Get month
  s := Copy(s, iPos + 1, length(s));     // trims off the day number - no longer needed
  iPos := Pos(" ", s);
  sMonth := Uppercase(RTrim(Copy(s, 1, iPos)));
  if sMonth = 'JAN' then
    sMonthNum = 1
  else if sMonth = 'FEB' then
    sMonthNum = 2
  else if ....
  else
    sMonthNum = 12;

  // Get year
  s := LTrim(RTrim(Copy(s, iPos + 1, length(s))));     // trims off the month - only year remains
  result := StrToDate(sDayNum + '/' + sMonthNum + '/' + s);
end;
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
mikelittlewoodCommented:
What I don't understand is why you are converting the date at all if you are going to display it in the same format in the label as before.
Im assuming you are only doing this as an example to show your problem otherwise you would just equate the label and the edit.

Label1.Caption := Edit1.Text;



procedure TForm1.Button1Click(Sender: TObject);
var
  dDate: TDate;
begin
  Edit1.Text := 'WEDNESDAY 28 JUN 2006';
  Date := StrToDate(Edit1.Text);
  Label1.Caption := FormatDateTime('dddd dd mmm yyyy',Date);
end;

atul_parmar is right you cant use the dddd or mmm long format dates and convert these.
You would have to convert it first to something like 28/06/2006
0
 
King_DiamondAuthor Commented:
Thanks for the explanation and sorry for the typing.

I wondered it was something like you are saying as I tried it with a shortdate (28/06/2006) and it worked. Is it possible to convert a longdate string to a TDateTime? A function like StrToDate perhaps?
0
 
atul_parmarCommented:
If you want to do that you will have to write your own routine. With standard Delphi routines you can not do it.
0
 
King_DiamondAuthor Commented:
Thanks to everyone for your help.

Can anyone help me with the routine to achieve this? I will increase the points by another 100 if anyone can give me the code.

bjones8888,
I tried to use your function but I have problems running it. Compiler saying undeclared identifier for RTrim. I don't know what this is. Sorry but I'm no delphi expert.

mikelittlewood,
Yes it's an example to identify what was happening. I need this date to compare it to the current date.

Any help is much appreciated.
0
 
mikelittlewoodCommented:
You would use it like

procedure TForm1.Button1Click(Sender: TObject);
var
  s: string;
begin
  Edit1.Text := 'WEDNESDAY 28 JUN 2006';
  s:= LongDateToShort(Edit1.Text);
  Label1.Caption := FormatDateTime('dddd dd mmm yyyy', StrToDate(s));
end;
0
 
bjones8888PresidentCommented:
My bad on the RTrim function.  I use so many programs.  RTrim is SQL format.  In Delphi just use Trim( ).
0
 
King_DiamondAuthor Commented:
mikelittlewood,

Thanks. Your function works fine. I just want to trap the EStringListError but I don't know where to put the ' except on E: EStringListError do ShowMessage (E.Message);' within your function. Can you help please?
0
 
Eddie ShipmanAll-around developerCommented:
First, on MikeLittlewood's post, the try should be AFTER the sl := TStringList.Create;
and to add the exception handler, you should add another try right after the first one
and the except block before the finally block.
0
 
Eddie ShipmanConnect With a Mentor All-around developerCommented:
Like this:

function TForm1.LongDateToShort(sDate: String): String;
var
  i: Integer;
  sl: TStringList;
  sMon: string;
begin
  // split out the long string (assume always same format)
  sl := TStringList.Create;
    try try
    sl.Delimiter := ' ';
    sl.DelimitedText := sDate;
    // loop through locale short month names and find index
    for i := 1 to 12 do
      if Uppercase(ShortMonthNames[i]) = Uppercase(sl.Strings[2]) then Break;
    // correct format
    sMon := IntToStr(i);
    if Length(sMon) = 1 then
      sMon := '0' + sMon;
    // rebuild date string
    Result := Trim( sl.Strings[1] + '/' + sMon + '/' + sl.Strings[3] );
    except
      on E: EStringListError do
        ShowMessage (E.Message);
    end;
  finally
    FreeAndNil(sl)
  end;
end;
0
 
mikelittlewoodCommented:
oops .. honestly I usually do it your way Eddie! he he
Don't know WHAT came over me  :o)
0
 
King_DiamondAuthor Commented:
Eddie, Mike

I tried your code but the except is not tapping the error!

I was also testing different date formats and would like to add the EConvertError as well.

Can you help please?
0
 
mikelittlewoodCommented:
How are you trying to generate the stringlist error?
In theory the code should not generate one.

As for adding another error just extend the except block

    except
      on E: EStringListError do
        ShowMessage (E.Message);
      on E: EConvertError do
        ShowMessage (E.Message);
    end;
0
 
King_DiamondAuthor Commented:
mikelittlewood,

The date should always have the same format but as I'm using the date from third parties, I don't know if the date format will change. Hence, since I want the application to continue running in the case the date format is changed, I'm trying to trap any possible errors due to possible different date formats.

However, the exceptions highlighted by you and Eddie are not trapping the errors. I had tried what you mentioned but the error continued popping up so I thought that I was doing something wrong. The error is still popping up and is terminating the application and not popping up the dialog box.
0
 
King_DiamondAuthor Commented:
Problem solved. I had a typing error.

Thanks to everyone.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.