Mega Code Archive

 
Categories / Delphi / Forms
 

Date String (any format) to TDateTime

Title: Date String (any format) to TDateTime Question: 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 locales 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 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 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;