TryStrToDateTime игнорирует завершающие символы в строке («ложное срабатывание») - PullRequest
0 голосов
/ 03 февраля 2019

Я пишу утилиту импорта данных для импорта данных в приложение базы данных.Данные могут быть извлечены из буфера обмена (например, из Excel) или файла и первоначально хранятся в списке TStringlist.На следующем шаге пользователь может выбрать соответствующий разделитель столбцов (табуляция, запятая и т. Д.).После разбиения данных на столбцы (с использованием выбранного разделителя) каждое строковое значение (назовем его значением ячейки) проверяется на соответствие действительному типу поля базы данных.

Проблема, с которой я столкнулся, связана с датой и временемзначения (и, возможно, значение даты и / или времени, но я еще не проверял это).Если пользователь выбирает «неправильный» разделитель, данные не разделяются, и каждая строка содержит один столбец (что, конечно, правильно).В таком случае значение ячейки может содержать строку, подобную приведенной ниже (я показываю значение отладки для отображения правильного разделителя, в данном случае вкладка):

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

При использовании TryStrToDateTime или StrToDatetime это строковое значение «проходит», поскольку строка «обрезается» (т.е. игнорирует завершающий текст и возвращаетправильное значение даты-времени от 01.04.10).Если затем я передам значение ячейки (исходную строку) в качестве варианта функции сравнения диапазонов, то, очевидно, произойдет сбой с EVariantTypeCastError.

Есть ли метод (или существующая функция Delphi RTL)) проверить, чтобы строковое значение содержало только действительную дату (время) (т. е. без завершающего текста)?Не удалось найти функцию (или параметр функции) с учетом этого, я также думал о проверке длины строки, но мое программное обеспечение используется на международном уровне, и поэтому формат даты и времени будет различным и, следовательно, может иметь различную длину.

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 голосов
/ 05 февраля 2019

Похоже, что решение (по крайней мере для моего приложения) состоит в том, чтобы объединить 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');

Это оставляет меня с вопросом, означает ли это, что TryStrToDateTime неправильно реализован по сравнению с TryStrToDate?Как минимум, как представляется, существует противоречие с «дизайном» функций;«строковое значение равно a Date» против «строковое значение начинается с a DateTime».Если я что-то упустил ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...