Как проверить, является ли строка допустимой строкой формата DateTime в Delphi

Я хочу, чтобы пользователь мог вручную вводить формат полей даты и времени в программе. У меня есть компонент Tedit. Например, если пользователь вводит "HH:nn", то это допустимая строка формата datetime, и все компоненты datetime должны изменить свойство format на это, но если он вводит "asd", это не так. Есть ли быстрый способ проверить это, не записывая мою собственную функцию?

5 ответов


вы можете использовать функции:

TryStrToDate
TryStrToTime
TryStrToDateTime

они пытаются преобразовать строку в дату/время и если преобразование успешно, то возвращает true. Поэтому исключений не возникает.

для определения собственного формата можно использовать необязательный параметр TFormatSettings.

все функции определены в SysUtils.

но в VCL есть некоторые элементы управления датой/временем, такие как TDateTimePicker и TMonthCalendar. Вы также можете использовать их.


проблема в том, как вы определяете 'формат'? Возможно, лучшее, что вы можете сделать, это поиск определенных букв в строке формата. Но что делать, если пользователь не заботится о том, чтобы увидеть год, или не хочет видеть время?

Я бы не стал подчеркивать слишком много о проверке того, что они вошли в "действительный формат". Скорее просто дайте им предварительный просмотр формата, который они ввели, используя текущую дату-время.

редактировать: обновление для новая информация от ОП

там было небольшое уточнение по вопросу:

на самом деле мне нужно указать свойство Format полей TDateTimePicker и TDateTime в базе данных. И я хочу, чтобы пользователь мог изменять эти форматы. - Тофиг Гасанов!--7-->

это важное уточнение, возможно, вы хотите включить его в свой вопрос?

важно то, что строка формата будет указывать не только на Формат отображения, а также формат редактирования. Теперь, хотя в значительной степени любая строка действительна, не все из них особенно полезны (особенно для редактирования). Например:

FDateTimeFormat := '"The day is "d" of this month of the year "yy';

это совершенно справедливо в том смысле, что ваша дата может быть соответствующим образом отформатирован. Тем не менее, это не особенно полезно для установки месяца.

теперь IMHO, если пользователь хочет сделать свою жизнь сложной, не включая поля месяца в строку формата-жестко! Проблема однако приходит в том, что правила формата немного технические, и пользователь может перепутать месяцы и минуты. Е. Г. FTimeFormat := 'HH:MM:SS' что на самом деле :месяцев>:

тем не менее, я поддерживаю свое первоначальное предложение (с одной незначительной настройкой): скорее просто дайте им предварительный просмотр формата, который они ввели, используя текущая дата-время предопределенная дата-время, которое должно подчеркивать "ошибки" в строке формата.

если у вас есть диалог настройки, в котором пользователь должен задать этот параметр:

  • добавить TComboBox (затем вы можете "предварительно загрузить" его с образцами строк, чтобы направлять пользователя; также они могут просто выбрать один из Ваших уже подходящих вариантов.
  • добавьте метку, в которой вы иллюстрируете пример поведения выбранной строки формата.
  • Выполнить TComboBox.OnChange, чтобы проиллюстрировать эффект выбора пользователя.

следующий код должен сделать трюк:

procedure TConfigDialog.DateTimeFormatChange(Sender: TObject);
var
  LCheckDate: TDateTime;
  LFormattedDate: String;
begin
  LCheckDate := EncodeDate(1999, 12, 31) + EncodeTime(20, 45, 50, 123);
  LFormattedDate := FormatDateTime(DateTimeFormat.Text, LCheckDate);
  DateFormatSample.Caption := 'Fri 31 December 1999 at 8:45:50.123 would be displayed as: ' + LFormattedDate;
end;

предупреждение

вы упомянули, что хотите использовать это для обоих TDateTimeField и TDateTimePicker. К сожалению, TDateTimePicker просто обертывает встроенный элемент управления Windows, который не использует FormatDateTime, и, следовательно, также имеет различные правила для его строк формата.

поэтому, боюсь, вам придется разрешить пользователям настраивать две разные строки формата. :(


чтобы расширить ответ Gamecat

If not tryStrToDateTime(Edit1.text,MyDateTimeVar) then
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');

Если вы просто хотите проверить его, не настраивая переменную MyDateTimeVar для передачи в tryStrToDateTimeVar, вы можете просто использовать обработку исключений

try
StrToDateTime(Edit1.Text);
except
ShowMessage('You need to make your entry look like a date...how about yy/mm/dd');
end;

дуг и Gamecat, я считаю, что вы оба неправильно поняли вопрос.

  • Он не хочет переходить от строки к дате.
  • у него есть дата.
  • Он хочет, чтобы преобразовать дату в строку в соответствии с форматом, указанным пользователем.
  • т. е. DisplayDate := FormatDateTime(UserDefinedFormat, Now());

единственное, что StrToDateTime (или TryStrToDateTime) мог бы используется для того, чтобы попытка круговая последовательность проверь. Но это было бы нехорошо, потому что нет никакой гарантии, что пользователь хочет видеть все элементы даты/времени. Следовательно, круговая проверка не может работать!


function to_date(p_format,p_string:string): TDateTime;
var
  v_day,           //dd
  v_month,         //mm
  v_year:Integer;  //yyyy
  v_hour,          //hh
  v_minute,        //nn
  v_second:Integer;//ss

  v_date:TDateTime;
  v_time:TDateTime;
begin
  v_day:=Pos('dd',p_format);
  v_month:=Pos('mm',p_format);
  v_year:=Pos('yyyy',p_format);

  v_hour:=Pos('hh',p_format);
  v_minute:=Pos('nn',p_format);
  v_second:=Pos('ss',p_format);

  v_day:=StrToInt(Copy(p_string,v_day,2));
  v_month:=StrToInt(Copy(p_string,v_month,2));
  v_year:=StrToInt(Copy(p_string,v_year,4));

  v_hour:=StrToInt(Copy(p_string,v_hour,2));
  v_minute:=StrToInt(Copy(p_string,v_minute,2));
  v_second:=StrToInt(Copy(p_string,v_second,2));

  v_date:=EncodeDate(v_year,v_month,v_day);
  v_time:=EncodeTime(v_hour,v_minute,v_second,0);
  ReplaceTime(v_date,v_time);
  Result:=v_date;
end;