Tabii ki her modern programlama dilinin bu sorunları aşmak için hazır fonksiyon/kütüphaneleri vardır. Delphi’nin de var. Ancak bizim makalemize konu olacak gibi değil
Genellikle, kullanıcılarımıza tarih ve saat verilerini girebilmeleri için, veri biçimlendirme denetimleri kullanırız. Bunların başında sanıyorum ki hepimizin kullandığı TDateTimePicker gelir. Ancak TDateTimePicker bileşeni bile tarih saat girmek için aslında meşakkatli bir bileşendir. Bu bileşenle uğraşmak istemeyenler TMaskEdit’in tarih saat formatındaki maskelerini kullanarak giriş işleminin yapılmasını sağlamak isterler. Ancak bu bileşen TDateTimePicker’dan bile daha yorucudur. Bu bileşenlerin birbirlerine göre güzel tarafları bulunmakla birlikte her ikisi de tam manası ile kusursuz tarih/saat girişleri için yeterlidir denilemez. TDateTimePicker’ın hem tarih hem saat gösterme ve değiştirmesine yarayan format harici bir property’si yokken, Format kullanıldığında da çeşitli garipliklerle karşılaşırız. TMaskEdit’in ise geçersiz tarih formatı hatalarından hem size hemde kullanıcılara eminim gına gelmiştir.
Herhangi bir tarihe 07 ay 25 gün 06 saat 05 dk 48 saniye eklemek istesek, bahsedilen bileşenler ile bunu yapmamız son derece zor olacaktır. Evet tüm bu zorlukları yaşadığınızı, yada siz yaşamasanız bile yazdığınız programın kullanıcılarının yaşadıklarını biliyorum. Belki artık onlar daha iyi bir alternatife rastlamadıkları için bu durumu kanıksamış olabilirler ama biz şimdi tarih/saat girişlerindeki kalıplaşmış yapıyı kırmaya hazırlanıyoruz.. Nasıl mı ?
Önce biraz hayalinizde canlandırmanızı istiyorum. Herhangi bir TDateTime verisini tutan bir veribilinçli denetimde aşağıdaki şekilde girişler yapabildiğinizi düşünün:
+5g -> Mevcut tarihten 5 gün sonrası
+5a -> Mevcut tarihten 5 ay sonrası
+5y -> Mevcut tarihten 5 yıl sonrası
+5s -> Mevcut tarihten 5 saat sonrası
+5dk-> Mevcut tarihten 5 dakika sonrası
+5sn-> Mevcut tarihten 5 saniye sonrası
+5g* -> Bugünden 5 gün sonrası
+5a* -> Bugünden 5 ay sonrası
+5y* -> Bugünden 5 yıl sonrası
+5s* -> Bugünden 5 saat sonrası
+5dk* -> Bugünden 5 dakika sonrası
+5sn* -> Bugünden 5 saniye sonrası
bugün-> Bugünün tarihi
bugun-> Bugünün tarihi
şimdi -> Bugünün tarihi
simdi -> Bugünün tarihi
today -> Bugünün tarihi
now -> Bugünün tarihi
yarın -> Yarının tarihi
yarin -> Yarının tarihi
tomorrow -> Yarının tarihi
dün -> Dün
dun -> Dün
yesterday -> Dün
23052009 -> 23/05/2009
230509 -> 23/05/2009
23/05 -> 23/05/2009
23.05 -> 23/05/2009
23.05/2009 -> 23/05/2009
23/05.2009 -> 23/05/2009
23.05/09 -> 23/05/2009
23/05.09 -> 23/05/2009
Tabii yukarıda + olarak verdiğim örneklerin – olarak da çalışacağını söylemeye gerek duymuyorum.Sanırım yazdığımız programların kullanıcıları bu durumdan son derece memnun olacaklardır. Ayrıca belki bazı hesaplamalarda kodsal anlamda bizimde işimize yarayacaktır. Bu kadar kêlamın ardından arzu ederseniz bu sihirli metodu sizlerin beğenisine sunayım:
Kod: Tümünü seç
function ConvertToDateTime(const AOldValue, AValue : String) : TDateTime;
type
TSeperator = record
AlphaSection : String;
NumSection : Integer;
UseCurrentDate: Boolean;
end;
function Parse(const Value : String) : TSeperator;
var
iCounter : Integer;
sNum,
sValue : String;
TAlpha : set of Char; //'a'..'z';
TNums : set of Char; //'0'..'9';
begin
sNum := '';
sValue := LowerCase(Value);
TAlpha := ['a'..'z'];
TNums := ['0'..'9'];
Result.AlphaSection := '';
Result.NumSection := 0;
Result.UseCurrentDate := false;
for iCounter := 1 to Length(sValue) do
begin
if sValue[iCounter] in TAlpha then Result.AlphaSection := Result.AlphaSection + sValue[iCounter];
if sValue[iCounter] in TNums then sNum := sNum + sValue[iCounter];
if sValue[iCounter] = '*' then Result.UseCurrentDate := true;
end;
if sNum <> '' then
Result.NumSection := StrToIntDef(sNum, 0);
end;
var
sVal : String;
iMultiplier : Integer;
OldDate : TDateTime;
Separator : TSeperator;
begin
Result := 0;
iMultiplier := 1;
OldDate := Now;
if Trim(AOldValue) <> '' then
OldDate := StrToDateTimeDef(Trim(AOldValue), Now);
sVal := Trim(AValue);
sVal := StringReplace(sVal, 'Ü', 'ü', [rfReplaceAll]);
sVal := StringReplace(sVal, 'Ş', 'ş', [rfReplaceAll]);
sVal := StringReplace(sVal, 'İ', 'i', [rfReplaceAll]);
sVal := LowerCase(sVal);
sVal := StringReplace(sVal, '.', DateSeparator, [rfReplaceAll]);
sVal := StringReplace(sVal, ',', DateSeparator, [rfReplaceAll]);
sVal := StringReplace(sVal, '/', DateSeparator, [rfReplaceAll]);
if Pos(DateSeparator, sVal) <> 0 then
begin
try
Result := StrToDate(sVal);
Exit;
except
end;
end;
if Length(sVal) = 0 then Exit;
if (sVal = 'bugün') or
(sVal = 'bugun') or
(sVal = 'şimdi') or
(sVal = 'simdi') or
(sVal = 'today') or
(sVal = 'now') then
begin
Result := Now;
Exit;
end;
if (sVal = 'yarın') or
(sVal = 'yarin') or
(sVal = 'tomorrow') then
begin
Result := Now + 1;
Exit;
end;
if (sVal = 'dün') or
(sVal = 'dun') or
(sVal = 'yesterday') then
begin
Result := Now - 1;
Exit;
end;
if sVal[1] = '-' then iMultiplier := -1;
if (sVal[1] in ['-', '+']) and (Length(sVal) >= 3) then
begin
Delete(sVal, 1, 1); // -, +
Separator := Parse(sVal);
if Separator.AlphaSection = '' then Separator.AlphaSection := 'g';
if Separator.AlphaSection = 'g' then // Gün
begin
if Separator.UseCurrentDate
then Result := IncDay(Now, iMultiplier * Separator.NumSection)
else Result := IncDay(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
if Separator.AlphaSection = 'a' then // Ay
begin
if Separator.UseCurrentDate
then Result := IncMonth(Now, iMultiplier * Separator.NumSection)
else Result := IncMonth(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
if Separator.AlphaSection = 'y' then // Yıl
begin
if Separator.UseCurrentDate
then Result := IncYear(Now, iMultiplier * Separator.NumSection)
else Result := IncYear(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
if Separator.AlphaSection = 's' then // Saat
begin
if Separator.UseCurrentDate
then Result := IncHour(Now, iMultiplier * Separator.NumSection)
else Result := IncHour(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
if Separator.AlphaSection = 'dk' then // Dakika
begin
if Separator.UseCurrentDate
then Result := IncMinute(Now, iMultiplier * Separator.NumSection)
else Result := IncMinute(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
if Separator.AlphaSection = 'sn' then // Saniye
begin
if Separator.UseCurrentDate
then Result := IncSecond(Now, iMultiplier * Separator.NumSection)
else Result := IncSecond(OldDate, iMultiplier * Separator.NumSection);
Exit;
end;
end;
if (Length(sVal) mod 2) <> 0 then sVal := '0' + sVal;
if ( Length(sVal) = 6 ) or ( Length(sVal) = 8 ) then // 23052009 , 230509 gibi tarih girişleri
begin
Insert( DateSeparator, sVal, 5 );
Insert( DateSeparator, sVal, 3 );
TryStrToDate(sVal, Result);
Exit;
end;
raise Exception.Create('Tarih/Saat dönüşümlerinde hata.!');
end;
Ardından TDateTimeField türündeki field’ın olaylarından OnSetText‘e aşağıdaki gibi bir kod yazacağız;
Kod: Tümünü seç
procedure TForm1.ClientDataSet1SaleDateSetText(Sender: TField;
const Text: String);
begin
try
Sender.AsDateTime := ConvertToDateTime(Sender.AsString, Text);
except
Sender.AsString := Text;
end;
end;
Alıntıdır Kaynak : http://www.tugrulhelvaci.com/?p=209