Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Converting date string to tdatetime (varied date format entry)

Posted on 2004-04-10
12
Medium Priority
?
678 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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 600 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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

636 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