Как проверить, является ли строка допустимой строкой формата DateTime в Delphi
-
12-09-2019 - |
Вопрос
Я хочу, чтобы пользователь мог вручную вводить формат полей даты и времени в программе.У меня есть компонент Tedit.Например, если пользователь вводит «ЧЧ: nn», то это допустимая строка формата даты и времени, и все компоненты даты и времени должны изменить на нее свойство формата, но если он вводит «asd», это не так.Есть ли быстрый способ проверить это, не написав собственную функцию?
Решение
Вы можете использовать функции:
TryStrToDate
TryStrToTime
TryStrToDateTime
Они пытаются преобразовать строку в дату/время, и если преобразование завершается успешно, возвращается true.Так что никаких исключений не предусмотрено.
Вы можете использовать дополнительный параметр TFormatSettings, чтобы определить свой собственный формат.
Все функции определены в SysUtils.
Но в VCL доступны некоторые элементы управления датой и временем, такие как TDateTimePicker и TMonthCalendar.Вы также можете использовать их.
Другие советы
Проблема в том, как определить «действительный формат»?Возможно, лучшее, что вы можете сделать, — это поискать наличие определенных букв в строке формата.Но что, если пользователя не интересует год или он не хочет видеть время?
Я бы не стал слишком беспокоиться о проверке того, что они ввели «действительный формат».Лучше просто дайте им предварительный просмотр формата, который они ввели, используя текущую дату и время.
Редактировать:Обновление новой информации от ОП
По вопросу было небольшое уточнение:
На самом деле мне нужно указать свойство Format полей TDateTimePicker и TDateTime в базе данных.И я хочу, чтобы пользователь мог изменять эти форматы.— Тофиг Гасанов
Это важное уточнение, возможно, вы захотите включить его в свой вопрос?
Важно то, что строка формата будет указывать не только формат отображения, но и формат редактирования.Хотя практически любая строка действительна, не все из них особенно полезны (особенно для редактирования).Например.:
FDateTimeFormat := '"The day is "d" of this month of the year "yy';
Это совершенно справедливо в том смысле, что ваше свидание возможно отформатирован соответствующим образом.Однако для установки месяца это не особенно полезно.
ИМХО, если пользователь хочет усложнить себе жизнь, не включая поля месяца в строку формата - это сложно!Однако проблема заключается в том, что правила формата немного технические, и пользователь может перепутать месяцы и минуты.Например. 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;