Solved

Converting date string to tdatetime (varied date format entry)

Posted on 2004-04-10
12
671 Views
Last Modified: 2010-04-05
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.
0
Comment
Question by:rjsand
  • 6
  • 3
  • 3
12 Comments
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 10797916
1. You can use TMaskEdit to let the user enter date in a single format.
2. You can divide the string and use function EncodeDate().
0
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 10797965
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],int[1]) else ShowMessage('invalid date format');
end;
0
 
LVL 12

Accepted Solution

by:
esoftbg earned 150 total points
ID: 10798229
Install this TeoEditDate into your Delphi components palette:

unit eoEditDate;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, StdCtrls,
  Dialogs, DateUtils;

type
  TDateMask          = (mm_dd_yyyy, mm_dd_yy);
  TeoEditDate          =   class(TEdit)
    private          { Private declarations }
      FDate:           TDate;
      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;
      destructor       Destroy; override;
    published        { Published declarations }
      property         Date: TDate read FDate write FDate;
      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;
  case FDateMask of
    mm_dd_yyyy: FSize := 10;
    mm_dd_yy:   FSize := 8;
  end;
end;

destructor             TeoEditDate.Destroy;
begin
  try
    inherited Destroy;
  except
  end;
end;

procedure              TeoEditDate.SetMask(const Value: TDateMask);
begin
  FDateMask := Value;
  case FDateMask of
    mm_dd_yyyy: FSize := 10;
    mm_dd_yy:   FSize := 8;
  end;
end;

function               Text_To_Date(T: string): TDate;
begin
  try
    Result := StrToDate(T);
  except
    Result := 0;
  end;
end;

procedure              TeoEditDate.Change;
begin
  if (FSize>0) then
  begin
    if (Length(Text)>FSize) then
      Text := Copy(Text, 1, FSize);
  end;
  FDate := Text_To_Date(Text);
  inherited;
end;

procedure              TeoEditDate.KeyPress(var Key: Char);
var
  B:                   Boolean;
  I:                   Integer;
  J:                   Integer;
  L:                   Integer;
begin
  if (FSize>0) then
  begin
    if (Length(Text)>FSize-1) and (Key<>#8) then
      Key := #0;
  end
  else
  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;
end;

end.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:esoftbg
ID: 10798348
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;
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 10800018
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.
0
 

Author Comment

by:rjsand
ID: 10814757
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.

0
 

Author Comment

by:rjsand
ID: 10814797
I meant in the previous post "If the user enters 4/5/03 or 4/05/2003"  etc.
0
 
LVL 11

Expert Comment

by:ZhaawZ
ID: 10815073
rjsand, why don't you use my example?
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 10815417
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.
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 10815455
It is better to use the last version of the component. I see you are accepted the first version wich has some errors.
0
 

Author Comment

by:rjsand
ID: 10816153
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.
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 10816361
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.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
code issue 8 177
Mobile Keyboard covers the display of the TMemo 3 100
Working with hours 3 72
How to insert .png images to TClientDataSet .cds file? 2 67
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

679 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question