rjsand
asked on
Converting date string to tdatetime (varied date format entry)
I would like to find a function that would allow user to enter a date into an edit box in the format of any of these: mm/dd/yy or m/d/y or mm/dd/yyyy or m/d/yy, etc. and return a valid tdatetime, or return false if unable to convert to a tdatetime. I've tried to figure it out by looking at the date formatting stuff in Delphi 6, but I'm so confused now I thought I'd go to the experts.
I would think this would be an often-used function.
Can you steer me towards the answer? Thanks.
I would think this would be an often-used function.
Can you steer me towards the answer? Thanks.
procedure TForm1.Edit1Change(Sender: TObject);
var
dt : TDateTime;
s : string;
str : array [0..2] of string;
int : array [0..2] of word;
err : array [0..2] of integer;
ValidDate : boolean;
begin
s := Edit1.Text;
str[0] := copy(s,1,pos('/',s) - 1); delete(s,1,pos('/',s));
str[1] := copy(s,1,pos('/',s) - 1); delete(s,1,pos('/',s));
str[2] := copy(s,1,length(s));
Val(str[0],int[0],err[0]);
Val(str[1],int[1],err[1]);
Val(str[2],int[2],err[2]);
ValidDate := true;
if err[0] or err[1] or err[2] <> 0 then ValidDate := false;
if (int[0] = 0) or (int[0] > 12) then ValidDate := false;
{add checking for day of month}
{add checking for year}
if ValidDate then dt := EncodeDate(int[2],int[0],i nt[1]) else ShowMessage('invalid date format');
end;
var
dt : TDateTime;
s : string;
str : array [0..2] of string;
int : array [0..2] of word;
err : array [0..2] of integer;
ValidDate : boolean;
begin
s := Edit1.Text;
str[0] := copy(s,1,pos('/',s) - 1); delete(s,1,pos('/',s));
str[1] := copy(s,1,pos('/',s) - 1); delete(s,1,pos('/',s));
str[2] := copy(s,1,length(s));
Val(str[0],int[0],err[0]);
Val(str[1],int[1],err[1]);
Val(str[2],int[2],err[2]);
ValidDate := true;
if err[0] or err[1] or err[2] <> 0 then ValidDate := false;
if (int[0] = 0) or (int[0] > 12) then ValidDate := false;
{add checking for day of month}
{add checking for year}
if ValidDate then dt := EncodeDate(int[2],int[0],i
end;
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
The function would be:
type
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
function Text_To_Date(T: string): TDateRec;
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := 0;
Result.Ok := False;
end;
end;
type
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
function Text_To_Date(T: string): TDateRec;
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := 0;
Result.Ok := False;
end;
end;
An improved version:
unit eoEditDate;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls,
Dialogs, DateUtils;
type
TDateMask = (mm_dd_yyyy, mm_dd_yy, m_d_yy, m_d_y);
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
TeoEditDate = class(TEdit)
private { Private declarations }
FDate: TDate;
FDateOk: Boolean;
FDateMask: TDateMask;
FKeyPress: TNotifyEvent;
FSize: Integer;
protected { Protected declarations }
procedure Change; override;
procedure KeyPress(var Key: Char); override;
procedure SetMask(const Value: TDateMask);
public { Public declarations }
constructor Create(AOwner: TComponent); override;
function Text_To_Date(T: string): TDateRec;
destructor Destroy; override;
published { Published declarations }
property Date: TDate read FDate write FDate;
property DateOk: Boolean read FDateOk write FDateOk;
property DateMask: TDateMask read FDateMask write SetMask default mm_dd_yyyy;
property Size: Integer read FSize write FSize default 10;
property OnKeyPress: TNotifyEvent read FKeyPress write FKeyPress;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EOSoft ', [TeoEditDate]);
end;
constructor TeoEditDate.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FDateMask := mm_dd_yyyy;
FSize := 10;
end;
procedure TeoEditDate.SetMask(const Value: TDateMask);
begin
FDateMask := Value;
case FDateMask of
mm_dd_yyyy: FSize := 10;
mm_dd_yy: FSize := 8;
m_d_yy: FSize := 6;
m_d_y: FSize := 5;
end;
end;
function TeoEditDate.Text_To_Date(T : string): TDateRec;
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := 0;
Result.Ok := False;
end;
end;
procedure TeoEditDate.Change;
var
DateRec: TDateRec;
begin
if (FSize>0) then
begin
if (Length(Text)>FSize) then
Text := Copy(Text, 1, FSize);
end;
DateRec := Text_To_Date(Text);
FDateOk := DateRec.Ok;
FDate := DateRec.Date;
inherited;
end;
procedure TeoEditDate.KeyPress(var Key: Char);
var
B: Boolean;
I: Integer;
J: Integer;
L: Integer;
begin
B := False;
inherited;
if Assigned(FKeyPress) then
FKeyPress(Self);
try
J := 0;
L := Length(Text);
if (L>1) then
begin
for I := 1 to L do
if (Text[I]=DateSeparator) then
Inc(J);
if (J<2) then
B := not (Key in ['0'..'9', DateSeparator, #8])
else
B := not (Key in ['0'..'9', #8])
end
else
B := not (Key in ['0'..'9', DateSeparator, #8]);
finally
if B then Key := #0;
end
end;
destructor TeoEditDate.Destroy;
begin
inherited Destroy;
end;
end.
unit eoEditDate;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls,
Dialogs, DateUtils;
type
TDateMask = (mm_dd_yyyy, mm_dd_yy, m_d_yy, m_d_y);
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
TeoEditDate = class(TEdit)
private { Private declarations }
FDate: TDate;
FDateOk: Boolean;
FDateMask: TDateMask;
FKeyPress: TNotifyEvent;
FSize: Integer;
protected { Protected declarations }
procedure Change; override;
procedure KeyPress(var Key: Char); override;
procedure SetMask(const Value: TDateMask);
public { Public declarations }
constructor Create(AOwner: TComponent); override;
function Text_To_Date(T: string): TDateRec;
destructor Destroy; override;
published { Published declarations }
property Date: TDate read FDate write FDate;
property DateOk: Boolean read FDateOk write FDateOk;
property DateMask: TDateMask read FDateMask write SetMask default mm_dd_yyyy;
property Size: Integer read FSize write FSize default 10;
property OnKeyPress: TNotifyEvent read FKeyPress write FKeyPress;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EOSoft
end;
constructor TeoEditDate.Create(AOwner:
begin
inherited Create(AOwner);
FDateMask := mm_dd_yyyy;
FSize := 10;
end;
procedure TeoEditDate.SetMask(const Value: TDateMask);
begin
FDateMask := Value;
case FDateMask of
mm_dd_yyyy: FSize := 10;
mm_dd_yy: FSize := 8;
m_d_yy: FSize := 6;
m_d_y: FSize := 5;
end;
end;
function TeoEditDate.Text_To_Date(T
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := 0;
Result.Ok := False;
end;
end;
procedure TeoEditDate.Change;
var
DateRec: TDateRec;
begin
if (FSize>0) then
begin
if (Length(Text)>FSize) then
Text := Copy(Text, 1, FSize);
end;
DateRec := Text_To_Date(Text);
FDateOk := DateRec.Ok;
FDate := DateRec.Date;
inherited;
end;
procedure TeoEditDate.KeyPress(var Key: Char);
var
B: Boolean;
I: Integer;
J: Integer;
L: Integer;
begin
B := False;
inherited;
if Assigned(FKeyPress) then
FKeyPress(Self);
try
J := 0;
L := Length(Text);
if (L>1) then
begin
for I := 1 to L do
if (Text[I]=DateSeparator) then
Inc(J);
if (J<2) then
B := not (Key in ['0'..'9', DateSeparator, #8])
else
B := not (Key in ['0'..'9', #8])
end
else
B := not (Key in ['0'..'9', DateSeparator, #8]);
finally
if B then Key := #0;
end
end;
destructor TeoEditDate.Destroy;
begin
inherited Destroy;
end;
end.
ASKER
I loaded the eoEditDate component, but it stops after any keypress with a convert error. Am I missing something in using the component?
Also, what I need is the ability to accept any string that could be interpreted as a valid date, without knowing ahead of time how the date format will be used. If the user enters 4/5/03 or 405/2003, then they would both be able to be accepted and converted to a datetime value.
Thank you for your responses, and I sure would appreciate some additional feedback.
Also, what I need is the ability to accept any string that could be interpreted as a valid date, without knowing ahead of time how the date format will be used. If the user enters 4/5/03 or 405/2003, then they would both be able to be accepted and converted to a datetime value.
Thank you for your responses, and I sure would appreciate some additional feedback.
ASKER
I meant in the previous post "If the user enters 4/5/03 or 4/05/2003" etc.
rjsand, why don't you use my example?
Hi rjsand,
If you set the DateMask property to m_d_y then the component doesn't allow to be entered more than 5 symbols. In this case you must enter 4/5/3 and it will be interpreted as 04/05/2003
If you set the DateMask property to mm_dd_yyyy then the component doesn't allow to be entered more than 10 symbols. In this case you can enter 4/5/3 and 4/5/03 and 04/5/03 and 04/05/03 and 04/05/2003 it will be interpreted as 04/05/2003
Thank you for the feedback. If you want I will improve the component as you need.
If you set the DateMask property to m_d_y then the component doesn't allow to be entered more than 5 symbols. In this case you must enter 4/5/3 and it will be interpreted as 04/05/2003
If you set the DateMask property to mm_dd_yyyy then the component doesn't allow to be entered more than 10 symbols. In this case you can enter 4/5/3 and 4/5/03 and 04/5/03 and 04/05/03 and 04/05/2003 it will be interpreted as 04/05/2003
Thank you for the feedback. If you want I will improve the component as you need.
It is better to use the last version of the component. I see you are accepted the first version wich has some errors.
ASKER
Thanks for your help. This is the first time I've used this site, and I didn't really understand how the process worked. Hopefully, my next time will be better for everyone. I meant to accept the last version. My mistake.
Here is the last version (I hope it is error free):
unit eoEditDate;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls,
Dialogs, DateUtils;
type
TDateMask = (mm_dd_yyyy, mm_dd_yy, m_d_yy, m_d_y);
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
TeoEditDate = class(TEdit)
private { Private declarations }
FDate: TDate;
FDateOk: Boolean;
FDateMask: TDateMask;
FKeyPress: TNotifyEvent;
FSize: Integer;
protected { Protected declarations }
procedure Change; override;
procedure KeyPress(var Key: Char); override;
procedure SetMask(const Value: TDateMask);
public { Public declarations }
constructor Create(AOwner: TComponent); override;
function Text_To_Date(T: string): TDateRec;
destructor Destroy; override;
published { Published declarations }
property Date: TDate read FDate write FDate;
property DateOk: Boolean read FDateOk write FDateOk;
property DateMask: TDateMask read FDateMask write SetMask default mm_dd_yyyy;
property Size: Integer read FSize write FSize default 10;
property OnKeyPress: TNotifyEvent read FKeyPress write FKeyPress;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EOSoft ', [TeoEditDate]);
end;
constructor TeoEditDate.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FDateMask := mm_dd_yyyy;
FSize := 10;
end;
procedure TeoEditDate.SetMask(const Value: TDateMask);
begin
FDateMask := Value;
case FDateMask of
mm_dd_yyyy: FSize := 10;
mm_dd_yy: FSize := 8;
m_d_yy: FSize := 8;
m_d_y: FSize := 8;
end;
end;
function TeoEditDate.Text_To_Date(T : string): TDateRec;
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := EncodeDate(1,1,1);
Result.Ok := False;
end;
end;
procedure TeoEditDate.Change;
var
I: Integer;
DateRec: TDateRec;
begin
if (FSize>0) then
begin
I := SelStart;
if (Length(Text)>FSize) then
Text := Copy(Text, 1, FSize);
SelLength := 0;
SelStart := I;
end;
DateRec := Text_To_Date(Text);
FDateOk := DateRec.Ok;
FDate := DateRec.Date;
inherited;
end;
procedure TeoEditDate.KeyPress(var Key: Char);
var
B: Boolean;
I: Integer;
J: Integer;
L: Integer;
begin
B := False;
inherited;
if Assigned(FKeyPress) then
FKeyPress(Self);
try
J := 0;
L := Length(Text);
if (L>1) then
begin
for I := 1 to L do
if (Text[I]=DateSeparator) then
Inc(J);
if (J<2) then
B := not (Key in ['0'..'9', DateSeparator, #8])
else
B := not (Key in ['0'..'9', #8])
end
else
B := not (Key in ['0'..'9', DateSeparator, #8]);
finally
if B then Key := #0;
end
end;
destructor TeoEditDate.Destroy;
begin
inherited Destroy;
end;
end.
unit eoEditDate;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, StdCtrls,
Dialogs, DateUtils;
type
TDateMask = (mm_dd_yyyy, mm_dd_yy, m_d_yy, m_d_y);
TDateRec = record
Ok: Boolean;
Date: TDate;
end;
TeoEditDate = class(TEdit)
private { Private declarations }
FDate: TDate;
FDateOk: Boolean;
FDateMask: TDateMask;
FKeyPress: TNotifyEvent;
FSize: Integer;
protected { Protected declarations }
procedure Change; override;
procedure KeyPress(var Key: Char); override;
procedure SetMask(const Value: TDateMask);
public { Public declarations }
constructor Create(AOwner: TComponent); override;
function Text_To_Date(T: string): TDateRec;
destructor Destroy; override;
published { Published declarations }
property Date: TDate read FDate write FDate;
property DateOk: Boolean read FDateOk write FDateOk;
property DateMask: TDateMask read FDateMask write SetMask default mm_dd_yyyy;
property Size: Integer read FSize write FSize default 10;
property OnKeyPress: TNotifyEvent read FKeyPress write FKeyPress;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('EOSoft
end;
constructor TeoEditDate.Create(AOwner:
begin
inherited Create(AOwner);
FDateMask := mm_dd_yyyy;
FSize := 10;
end;
procedure TeoEditDate.SetMask(const Value: TDateMask);
begin
FDateMask := Value;
case FDateMask of
mm_dd_yyyy: FSize := 10;
mm_dd_yy: FSize := 8;
m_d_yy: FSize := 8;
m_d_y: FSize := 8;
end;
end;
function TeoEditDate.Text_To_Date(T
begin
try
Result.Date := StrToDate(T);
Result.Ok := True;
except
Result.Date := EncodeDate(1,1,1);
Result.Ok := False;
end;
end;
procedure TeoEditDate.Change;
var
I: Integer;
DateRec: TDateRec;
begin
if (FSize>0) then
begin
I := SelStart;
if (Length(Text)>FSize) then
Text := Copy(Text, 1, FSize);
SelLength := 0;
SelStart := I;
end;
DateRec := Text_To_Date(Text);
FDateOk := DateRec.Ok;
FDate := DateRec.Date;
inherited;
end;
procedure TeoEditDate.KeyPress(var Key: Char);
var
B: Boolean;
I: Integer;
J: Integer;
L: Integer;
begin
B := False;
inherited;
if Assigned(FKeyPress) then
FKeyPress(Self);
try
J := 0;
L := Length(Text);
if (L>1) then
begin
for I := 1 to L do
if (Text[I]=DateSeparator) then
Inc(J);
if (J<2) then
B := not (Key in ['0'..'9', DateSeparator, #8])
else
B := not (Key in ['0'..'9', #8])
end
else
B := not (Key in ['0'..'9', DateSeparator, #8]);
finally
if B then Key := #0;
end
end;
destructor TeoEditDate.Destroy;
begin
inherited Destroy;
end;
end.
2. You can divide the string and use function EncodeDate().