Skip to main content
A newer version of this page is available. .

Using the SmartTextToDate Function

  • 5 minutes to read

As well as entering dates using the date editor’s dropdown calendar, a user can enter dates manually within the edit box. If the editor’s Properties.InputKind is set to ikStandard or ikRegExpr, then a user can type one of the predefined strings to enter specific dates. For instance, typing ‘today’ results in setting the present date in the editor. A date editor uses the global SmartTextToDate function for this purpose. It converts human readable strings such as “today”, “yesterday” or “Sunday” into TDateTime format. Strings supported by date editors and the SmartTextToDate function are stored as resource strings in the cxLibraryStrs unit. For more information on these strings, refer to the function description.

For localization purposes, you might want to substitute the value of a specific resource string. To change a resource string, use the cxSetResourceString procedure available within the dxCore unit. We recommend that you do not assign an empty string to any of these resource strings to avoid unexpected results when parsing input values with the global SmartTextToDate function.

For instance, to set cxSDateToday to a value of ‘current_day’, implement the following code:

cxSetResourceString(@cxSDateToday, 'current_day');

Note

If you want date editors to recognize the ‘current_day’ string, you need to rebuild the masks used by the editors. To do so, just call the GetFormats and NotifyListeners functions of the global format controller object:

cxFormatController.GetFormats;
  cxFormatController.NotifyListeners;
var
  VDate: TDateTime;
//...
  if SmartTextToDate('tomorrow', VDate) then
    ShowMessage(FormatDateTime('d mmmm yyyy', VDate));
  cxSetResourceString(@cxSDateTomorrow, 'next_day');
  if SmartTextToDate('tomorrow', VDate) then
    ShowMessage(FormatDateTime('d mmmm yyyy', VDate))
  else
    ShowMessage('No such constant');
  if SmartTextToDate('next_day', VDate) then
    ShowMessage(FormatDateTime('d mmmm yyyy', VDate));

While executing the code, you will see how resource constant changing works.

The first SmartTextToDate function call will be a success.

The second will fail because we have changed the value of the tomorrow constant to “next_day”.

The third call will be a success because we call the SmartTextToDate function with the changed constant.

These constants are mainly used with the SmartTextToDate function. The AText parameter of the SmartTextToDate function specifies the string which is compared with every embedded constant. If a match is found, the function places the associated value into the ADateTime parameter and returns True. If there is no match to the input string, the function simply returns False.

If the supplied constants are not sufficient, you can write your own parser function to parse the AText parameter and use it to convert your own constants into TDateTime type.

The following code provides a user parser function which recognizes “Independence_day” and “Christmas” strings and converts them into appropriate TDateTime values.

const
  cxIndependenceDay = 'Independence_day';
  cxChristmas = 'Christmas';
function MySmartTextToDate(const AText: string; var ADate: TDateTime): Boolean;
var
  Year: Integer;
begin
  if AnsiCompareText(AText, cxIndependenceDay) = 0 then
  begin
    //Getting the current year (see dxGetDateElement function in
    //cxDateUtils.pas).
    Year := dxGetDateElement(Date, deYear);
    //Encoding the 4th of July and current year.
    ADate := EncodeDate(Year, 7, 4);
    //Indicating that function was a success.
    Result := True;
  end
  else if AnsiCompareText(AText, cxChristmas) = 0 then
  begin
    //Getting the current year (see dxGetDateElement function in
    //cxDateUtils.pas).
    Year := dxGetDateElement(Date, deYear);
    //Encoding the 25th of December and current year.
    ADate := EncodeDate(Year, 12, 25);
    //Indicating that function was a success.
    Result := True;
  end
  else
    //Otherwise the function was a failure.
    Result := False;
end;

In order to use the parser function, you should use the SmartTextToDateFunc global variable (nil by default). If you assign your parser function to this variable, then it will be called when the built-in conversion fails. The SmartTextToDate function passes the AText and ADate parameters to your function and calls it. The following code demonstrates how to use the variable and function.

var
  VDate: TDateTime;
begin
  //Assigning user parser function to the global variable
  //SmartTextToDateFunc
  SmartTextToDateFunc := MySmartTextToDate;
  //Executing SmartTextToDate with a non-embedded constant
  //When it fails it will call MySmartTextToDate
  //And according to the MySmartTextToDate implementation
  //(see above) it will succeed.
  if SmartTextToDate(cxChristmas, VDate) then
    //Showing the message box to confirm successful
    //conversion.
    ShowMessage(FormatDateTime('d mmmm yyyy', VDate));
end;

If we assume that current year is 2002 you will see the following message box:

Although the SmartTextToDate function is now able to recognize the ‘Independence_day’ and ‘Christmas’ strings, a date editor does not allow you to enter these strings when regular expressions are used for input validation, i.e. when the editor’s Properties.InputKind property is set to ikRegExpr. To enable a date editor to recognize these strings, you need to modify the regular expression specified by the RegExprDateEditMask property of the global format controller. In a system with English(United States) regional settings, the regular expression is generated by default as follows:

(((0?[1-9]|1[012])|
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))'/'([012]?[1-9]|[123]0|31)'/'\d\d\d\d)|
((today|yesterday|tomorrow|Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|first|second|third|fourth|fifth|sixth|seventh|bom|eom|now)((\+|-)\d(\d(\d(\d?)?)?)?))

We will insert new strings after word ‘now’:

var
  ANewItems, ANewMask: string;
//...
  ANewItems := '|' + cxIndependenceDay + '|' + cxChristmas;
  with cxFormatController do
  begin
    ANewMask := RegExprDateEditMask;
    Insert(ANewItems, ANewMask, Length(ANewMask) - 27);
    RegExprDateEditMask := ANewMask;
  end;
See Also