TryStrToDateTime会忽略字符串中的结尾字符(“假阳性”)

时间:2019-02-03 11:09:50

标签: string validation datetime delphi

我正在编写一个数据导入实用程序,以将数据导入数据库应用程序。可以从剪贴板(例如从Excel)或文件中检索数据,并且最初将其存储在TStringlist中。在下一步中,用户可以选择适当的列分隔符(制表符,逗号等)。将数据划分为列(使用选定的分隔符)后,将根据适用的数据库字段类型检查每个字符串值(我们称其为单元格值)的有效性。

我遇到的问题是日期时间值(可能还有日期和/或时间值,但是我还没有检查)。如果用户选择“错误的”分隔符,则不会拆分数据,并且每一行都包含一列(当然是正确的)。在这种情况下,单元格值可能包含类似于下面的字符串(在这种情况下,我正在显示调试值以显示正确的分隔符,制表符):

'04 / 01/10 00:00'#9'2.50'#9'100'#9'Text value'

使用TryStrToDateTime或StrToDatetime时,此字符串值“通过”,因为该字符串已“剪切”(即忽略尾随文本并返回正确的日期时间值04/01/10)。然后,如果我在稍后的阶段将单元格值(原始字符串)作为变体传递给范围比较函数,则它显然会失败,并出现EVariantTypeCastError。

是否存在一种方法(或现有的Delphi RTL函数)来检查字符串值,使其仅包含有效的日期(时间)(即无尾随文本)?无法找到考虑到这一点的函数(或函数参数),我也一直在考虑检查字符串长度,但是我的软件在国际上使用,因此datetime格式将有所不同,因此长度可能会有所不同。

PS:我在此处添加了以下示例代码,因为无法将其添加到评论中。

procedure TForm1.Button1Click(Sender: TObject);
var
  lStrVal: string;
  lIsDateTime: boolean;
  lDateTimeVal: TDateTime;
begin

  lStrVal := '01/01/2019 10:00' + chr(9) + '120.00' + chr(9) + 'Some text';

  lIsDateTime := TryStrToDateTime(lStrVal, lDateTimeVal);

  if lIsDateTime then
    messageDlg('String value is a date/time! ' + #13#10 + 'String: ' + lStrVal + #13#10 + 'Date/time is: ' + DateTimeToStr(lDateTimeVal), mtInformation, [mbOK], 0)
  else
    messageDlg('String value cannot be converted to a date/time!', mtWarning, [mbOK], 0);
end;

1 个答案:

答案 0 :(得分:0)

看来,解决方案(至少对于我的应用程序而言)是组合 TryStrToDateTime和TryStrToDate。为了演示,请启动一个新的VCL应用程序,并在窗体上放置一个ListBox和TButton(保留标准名称)。将以下代码粘贴到TButton OnClick处理程序中:

var
  lDateVal, lDateTimeVal: TDateTime;
  lStrVal: string;
  lResult: boolean;
begin
  ListBox1.Items.Clear;

  lStrVal := '01/01/2019 10:00' + '-120.00' + '-Some text';
  ListBox1.Items.Add('String value : ' + lStrVal);

  lDateVal := EncodeDate(2000, 1, 1);
  lDateTimeVal := EncodeDate(2000, 1, 1) + EncodeTime(1, 0, 0, 0);

  lResult := TryStrToDate(lStrVal, lDateVal);
  if lResult then
    ListBox1.Items.Add(' - TryStrToDate : TRUE')
  else
    ListBox1.Items.Add(' - TryStrToDate : FALSE');
  ListBox1.Items.Add('DateTime value: ' + DateTimeToStr(lDateVal));

  lResult := TryStrToDateTime(lStrVal, lDateTimeVal);
  if lResult then
    ListBox1.Items.Add(' - TryStrToDateTime : TRUE')
  else
    ListBox1.Items.Add(' - TryStrToDateTime : FALSE');
  ListBox1.Items.Add('DateTime value: ' + DateTimeToStr(lDateTimeVal));

  // Reset
  lDateVal := EncodeDate(2000, 1, 1);
  lDateTimeVal := EncodeDate(2000, 1, 1) + EncodeTime(1, 0, 0, 0);

  lResult := TryStrToDateTime(lStrVal, lDateTimeVal) and TryStrToDate(lStrVal, lDateVal);
  if lResult then
    ListBox1.Items.Add(' - Combined : TRUE')
  else
    ListBox1.Items.Add(' - Combined : FALSE');
  ListBox1.Items.Add('DateTime value: ' + DateTimeToStr(lDateTimeVal));

  ListBox1.Items.Add('');
  lStrVal := '01/01/2019 10:00';
  ListBox1.Items.Add('String value : ' + lStrVal);

  lResult := TryStrToDateTime(lStrVal, lDateTimeVal) and TryStrToDate(lStrVal, lDateVal);
  if lResult then
    ListBox1.Items.Add(' - Combined : TRUE')
  else
    ListBox1.Items.Add(' - Combined : FALSE');

  try
    lDateTimeVal := VarToDateTime(lStrVal);
    lResult := true;
  except
    lResult := false;
  end;

  if lResult then
    ListBox1.Items.Add(' - Using Variant : TRUE')
  else
    ListBox1.Items.Add(' - Using Variant : FALSE');

这给我留下了一个问题,即与TryStrToDate相比,TryStrToDateTime是否实现不正确?至少,似乎在功能的“设计”上存在矛盾。 “字符串值是一个日期”与“字符串值开始于一个DateTime”。除非我缺少什么...