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

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

Ответ 1

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

TryStrToDate
TryStrToTime
TryStrToDateTime

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

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

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

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

Ответ 2

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

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

Изменить: обновить новую информацию от OP

Было немного разъяснений по вопросу:

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

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

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

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

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

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

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

Предполагая, что у вас есть диалоговое окно конфигурации, в котором вы намереваетесь позволить пользователю определить этот параметр:

  • Добавьте 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, и, следовательно, также имеет разные правила для своих строк формата.

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

Ответ 3

Чтобы расширить ответ 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;

Ответ 4

Дуг и Гамекат, я считаю, что вы оба недооцениваете вопрос.

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

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

Ответ 5

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;