delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback



Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi








Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (4)


Date String (any format) to TDateTimeFormat this article printer-friendly!Bookmark function is only available for registered users!
DateTimeStrEval()
Product:
Delphi 5.x (or higher)
Category:
Object Pascal
Skill Level:
Scoring:
Last Update:
11/05/2002
Search Keys:
delphi delphi3000 article borland vcl code-snippet "Format DateTime" "string to date" "string to time"
Times Scored:
17
Visits:
18562
Uploader: Mike Heydon
Company: EOH
Reference: mheydon@pgbison.co.za
 
Question/Problem/Abstract:
When extracting data from text or other operating systems the format of date strings can vary dramatically. Borland function StrToDateTime() converts a string to a TDateTime value, but it is limited to the fact that the string parameter must be in the format of the current locale’s date/time format.

eg. "MM/DD/YY HH:MM:SS"

This is of little use when extracting dates such as ..

  1)  "Friday 18 October 2002 08:34am (45 secs)"
  2)  "20020431"
  3)  "12.Nov.03"
  4)  "14 Hour 31 Minute 25 Second 321 MSecs"

This function will evaluate a DateTime string in accordance to the DateTime specifier format string supplied. The following specifiers are supported ...

dd      the day as a number with a leading zero or space (01-31).
ddd    the day as an abbreviation (Sun-Sat)
dddd  the day as a full name (Sunday-Saturday)
mm    the month as a number with a leading zero or space (01-12).
mmm  the month as an abbreviation (Jan-Dec)
mmmm the month as a full name (January-December)
yy        the year as a two-digit number (00-99).
yyyy    the year as a four-digit number (0000-9999).
hh       the hour with a leading zero or space (00-23)
nn       the minute with a leading zero or space (00-59).
ss       the second with a leading zero or space (00-59).
zzz     the millisecond with a leading zero (000-999).
ampm  Specifies am or pm flag hours (0..12)
ap       Specifies a or p flag hours (0..12)

NOTE : One assumption I have to make is that DAYS, MONTHS,  
            HOURS and MINUTES have a leading ZERO or
            SPACE (ie. are 2 chars long) and MILLISECONDS are 3  
            chars long (ZERO or SPACE padded)

Using function

DateTimeStrEval(const DateTimeFormat : string;
                         const DateTimeStr : string) : TDateTime;

The above Examples (1..4) can be evaluated as ...
(Assume DT1 to DT3 equals example strings 1..4)

1)  DateTimeStrEval('dddd dd mmmm yyyy hh:nnampm (ss xxxx)',DT1);

2)  DateTimeStrEval('yyyymmdd',DT2);

3)  DateTimeStrEval('dd-mmm-yy',DT3);

4) DateTimeStrEval('hh xxxx nn xxxxxx ss xxxxxx zzz xxxxx',DT4);


Answer:



uses SysUtils, DateUtils

// =============================================================================
// Evaluate a date time string into a TDateTime obeying the
// rules of the specified DateTimeFormat string
// eg. DateTimeStrEval('dd-MMM-yyyy hh:nn','23-May-2002 12:34)
//
// NOTE : One assumption I have to make that DAYS,MONTHS,HOURS and
//        MINUTES have a leading ZERO or SPACE (ie. are 2 chars long)
//        and MILLISECONDS are 3 chars long (ZERO or SPACE padded)
//
// Supports DateTimeFormat Specifiers
//
// dd    the day as a number with a leading zero or space (01-31).
// ddd the day as an abbreviation (Sun-Sat)
// dddd the day as a full name (Sunday-Saturday)
// mm    the month as a number with a leading zero or space (01-12).
// mmm the month as an abbreviation (Jan-Dec)
// mmmm the month as a full name (January-December)
// yy    the year as a two-digit number (00-99).
// yyyy the year as a four-digit number (0000-9999).
// hh    the hour with a leading zero or space (00-23)
// nn    the minute with a leading zero or space (00-59).
// ss    the second with a leading zero or space (00-59).
// zzz the millisecond with a leading zero (000-999).
// ampm  Specifies am or pm flag hours (0..12)
// ap    Specifies a or p flag hours (0..12)
//
//
// Delphi 6 Specific in DateUtils can be translated to ....
//
// YearOf()
//
// function YearOf(const AValue: TDateTime): Word;
// var LMonth, LDay : word;
// begin
//   DecodeDate(AValue,Result,LMonth,LDay);
// end;
//
// TryEncodeDateTime()
//
// function TryEncodeDateTime(const AYear,AMonth,ADay,AHour,AMinute,ASecond,
//                            AMilliSecond : word;
//                            out AValue : TDateTime): Boolean;
// var LTime : TDateTime;
// begin
//   Result := TryEncodeDate(AYear, AMonth, ADay, AValue);
//   if Result then begin
//     Result := TryEncodeTime(AHour, AMinute, ASecond, AMilliSecond, LTime);
//     if Result then
//       AValue := AValue + LTime;
//   end;
// end;
//
// =============================================================================

function DateTimeStrEval(const DateTimeFormat : string;
                         const DateTimeStr : string) : TDateTime;
var i,ii,iii : integer;
    Retvar : TDateTime;
    Tmp,
    Fmt,Data,Mask,Spec : string;
    Year,Month,Day,Hour,
    Minute,Second,MSec : word;
    AmPm : integer;
begin
  Year := 1;
  Month := 1;
  Day := 1;
  Hour := 0;
  Minute := 0;
  Second := 0;
  MSec := 0;
  Fmt := UpperCase(DateTimeFormat);
  Data := UpperCase(DateTimeStr);
  i := 1;
  Mask := '';
  AmPm := 0;

  while i < length(Fmt) do begin
    if Fmt[i] in ['A','P','D','M','Y','H','N','S','Z'] then begin
      // Start of a date specifier
      Mask  := Fmt[i];
      ii := i + 1;

      // Keep going till not valid specifier
      while true do begin
        if ii > length(Fmt) then Break; // End of specifier string
        Spec := Mask + Fmt[ii];

        if (Spec = 'DD') or (Spec = 'DDD') or (Spec = 'DDDD') or
           (Spec = 'MM') or (Spec = 'MMM') or (Spec = 'MMMM') or
           (Spec = 'YY') or (Spec = 'YYY') or (Spec = 'YYYY') or
           (Spec = 'HH') or (Spec = 'NN') or (Spec = 'SS') or
           (Spec = 'ZZ') or (Spec = 'ZZZ') or
           (Spec = 'AP') or (Spec = 'AM') or (Spec = 'AMP') or
           (Spec = 'AMPM') then begin
          Mask := Spec;
          inc(ii);
        end
        else begin
          // End of or Invalid specifier
          Break;
        end;
      end;

      // Got a valid specifier ? - evaluate it from data string
      if (Mask <> '') and (length(Data) > 0) then begin
        // Day 1..31
        if (Mask = 'DD') then begin
           Day := StrToIntDef(trim(copy(Data,1,2)),0);
           delete(Data,1,2);
        end;

        // Day Sun..Sat (Just remove from data string)
        if Mask = 'DDD' then delete(Data,1,3);

        // Day Sunday..Saturday (Just remove from data string LEN)
        if Mask = 'DDDD' then begin
          Tmp := copy(Data,1,3);
          for iii := 1 to 7 do begin
            if Tmp = Uppercase(copy(LongDayNames[iii],1,3)) then begin
              delete(Data,1,length(LongDayNames[iii]));
              Break;
            end;
          end;
        end;

        // Month 1..12
        if (Mask = 'MM') then begin
           Month := StrToIntDef(trim(copy(Data,1,2)),0);
           delete(Data,1,2);
        end;

        // Month Jan..Dec
        if Mask = 'MMM' then begin
          Tmp := copy(Data,1,3);
          for iii := 1 to 12 do begin
            if Tmp = Uppercase(copy(LongMonthNames[iii],1,3)) then begin
              Month := iii;
              delete(Data,1,3);
              Break;
            end;
          end;
        end;


        // Month January..December
        if Mask = 'MMMM' then begin
          Tmp := copy(Data,1,3);
          for iii := 1 to 12 do begin
            if Tmp = Uppercase(copy(LongMonthNames[iii],1,3)) then begin
              Month := iii;
              delete(Data,1,length(LongMonthNames[iii]));
              Break;
            end;
          end;
        end;

        // Year 2 Digit
        if Mask = 'YY' then begin
          Year := StrToIntDef(copy(Data,1,2),0);
          delete(Data,1,2);
          if Year < TwoDigitYearCenturyWindow then
            Year := (YearOf(Date) div 100) * 100 + Year
          else
            Year := (YearOf(Date) div 100 - 1) * 100 + Year;
        end;

        // Year 4 Digit
        if Mask = 'YYYY' then begin
          Year := StrToIntDef(copy(Data,1,4),0);
          delete(Data,1,4);
        end;

        // Hours
        if Mask = 'HH' then begin
           Hour := StrToIntDef(trim(copy(Data,1,2)),0);
           delete(Data,1,2);
        end;

        // Minutes
        if Mask = 'NN' then begin
           Minute := StrToIntDef(trim(copy(Data,1,2)),0);
           delete(Data,1,2);
        end;

        // Seconds
        if Mask = 'SS' then begin
           Second := StrToIntDef(trim(copy(Data,1,2)),0);
           delete(Data,1,2);
        end;

        // Milliseconds
        if (Mask = 'ZZ') or (Mask = 'ZZZ') then begin
           MSec := StrToIntDef(trim(copy(Data,1,3)),0);
           delete(Data,1,3);
        end;


        // AmPm A or P flag
        if (Mask = 'AP') then begin
           if Data[1] = 'A' then
             AmPm := -1
           else
             AmPm := 1;
           delete(Data,1,1);
        end;

        // AmPm AM or PM flag
        if (Mask = 'AM') or (Mask = 'AMP') or (Mask = 'AMPM') then begin
           if copy(Data,1,2) = 'AM' then
             AmPm := -1
           else
             AmPm := 1;
           delete(Data,1,2);
        end;

        Mask := '';
        i := ii;
      end;
    end
    else begin
      // Remove delimiter from data string
      if length(Data) > 1 then delete(Data,1,1);
      inc(i);
    end;
  end;

  if AmPm = 1 then Hour := Hour + 12;
  if not TryEncodeDateTime(Year,Month,Day,Hour,Minute,Second,MSec,Retvar) then
    Retvar := 0.0;
  Result := Retvar;
end;





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
Take the lazy way out
    Bill Artemik (Nov 14 2002 8:27PM)

I use the little know function VarToDateTime(const V: variant) : TDateTime. I've thrown all sorts of dates at this little gem and it's never failed me. From the Delphi help file:

function VarToDateTime(const V: Variant): TDateTime);

Description

VarToDateTime converts the given Variant to a TDateTime value. An EVariantError exception is raised if the conversion fails.
Respond

RE: Take the lazy way out
Mike Heydon (Nov 15 2002 11:51AM)

Interesting function. I did not know that it would take that it took different date string formats. What version of Delphi did it appear ?. I see it is in D5 and D6. I have tested it and it takes most formats. One exception was a string like "02:34am Friday 15th November". None the less a most interesting comment.
Respond

TryEncodeDate and TryEncodeTime functions
    Mike Shkolnik (Nov 5 2002 5:39PM)

You forgot to include TryEncodeDate and TryEncodeTime functions
Respond

RE: TryEncodeDate and TryEncodeTime functions
Mike Heydon (Nov 6 2002 11:41AM)

They are a little longer with other calls, but they are simple to emulate. They basically evaluate EncodeDate() and EncodeTime() with error checking into a VAR TDateTime variable. If any encode errors are found the function returns FALSE.

eg.

function TryEncodeDate(Year,Month,Day : word;
                                    out DT : TDateTime) : boolean;
var Retvar : boolean;
begin
  try
    DT := EncodeDate(Year,Month,Day);
    Retvar := true;
  except
    DT := 0.0;
    Retvar := false;
  end;
end;

TryEncodeTime() would be similar.
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


   


  Community Ad of
Hans Gulö
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)