Как проверить, является ли строка допустимой строкой формата DateTime в Delphi - PullRequest
11 голосов
/ 04 декабря 2009

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

Ответы [ 5 ]

18 голосов
/ 04 декабря 2009

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

TryStrToDate
TryStrToTime
TryStrToDateTime

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

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

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

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

4 голосов
/ 04 декабря 2009

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

Я бы не стал особо подчеркивать, что они ввели «правильный формат». Вместо этого просто дайте им предварительный просмотр формата, который они ввели, используя текущую дату и время.

Редактировать : Обновление новой информации из OP

По этому вопросу было небольшое разъяснение:

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

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

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

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

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

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

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

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

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

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

1 голос
/ 04 декабря 2009

Даг и Gamecat, я полагаю, вы оба неправильно поняли вопрос.

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

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

1 голос
/ 04 декабря 2009

Чтобы расширить ответ 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;
0 голосов
/ 13 февраля 2013
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;
...