11

我希望用户能够在程序中手动输入日期时间字段的格式。我有 Tedit 组件。例如,如果用户输入“HH:nn”,那么这是一个有效的日期时间格式字符串,并且所有日期时间组件都应将格式属性更改为此,但如果他输入“asd”,则不是。有没有一种快速的方法来检查这一点,而无需编写我自己的函数?

4

6 回答 6

19

您可以使用以下功能:

TryStrToDate
TryStrToTime
TryStrToDateTime

他们尝试将字符串转换为日期/时间,如果转换成功,则返回 true。所以没有提出任何例外。

您可以使用可选的 TFormatSettings 参数来定义您自己的格式。

所有函数都在 SysUtils 中定义。

但是 VCL 中有一些日期/时间控件可用,例如 TDateTimePicker 和 TMonthCalendar。您也可以使用它们。

于 2009-12-04T11:44:50.980 回答
4

问题是,您如何定义“有效格式”?可能,您能做的最好的事情就是在格式字符串中搜索特定字母的存在。但是如果用户不关心看年份,或者不想看时间怎么办?

我不会过分强调验证他们是否输入了“有效格式”。而只是让他们预览他们使用当前日期时间输入的格式。

编辑:更新来自 OP 的新信息

关于这个问题有一点澄清:

实际上我需要在数据库中指定 TDateTimePicker 和 TDateTime 字段的 Format 属性。我希望用户能够更改这些格式。——托菲格·哈萨诺夫

这是一个重要的说明,也许您想将其包含在您的问题中?

重要的是格式字符串不仅会指示显示格式,还会指示编辑格式。现在,尽管几乎所有字符串都是有效的,但并非所有字符串都特别有用(尤其是对于编辑而言)。例如:

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

这是完全有效的,因为您的日期可以相应地格式化。但是,它对于设置月份并不是特别有用。

现在恕我直言,如果用户想通过在格式字符串中不包含月份字段来使他们的生活变得困难 - 很难!然而,问题在于格式规则有点技术性,用户可能会混淆数月和数分钟。例如FTimeFormat := 'HH:MM:SS'实际上是 <hours>:< months >:<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;

警告

您提到您想将其用于TDateTimeFieldTDateTimePicker。不幸的是,TDateTimePicker它只是简单地包装了一个不使用 FormatDateTime 的内置 Windows 控件,因此对其格式字符串也有不同的规则。

因此,恐怕您必须允许您的用户配置两种不同的格式字符串。:(

于 2009-12-04T14:09:38.900 回答
1

Doug 和 Gamecat,我相信你们都误解了这个问题。

  • 他不想从一个字符串转到一个日期。
  • 他有日期。
  • 他想根据用户指定的格式将该日期转换为字符串。
  • IEDisplayDate := FormatDateTime(UserDefinedFormat, Now());

可以使用StrToDateTime(或 TryStrToDateTime)的唯一方法是尝试循环“一致性检查”。但这并不好,因为不能保证用户想要查看日期/时间的所有元素。因此循环检查不起作用!

于 2009-12-04T17:53:26.467 回答
1

扩展 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;
于 2009-12-04T17:25:35.200 回答
0
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;
于 2013-02-13T19:59:35.780 回答
0

过程 TForm1.BitBtn1Click(Sender: TObject);
var
mydate,mydate1:TDateTime;
测试日期,测试日期1:字符串;
开始
测试日期:='13/15/2021';
TestDate1:='03/05/2021';

if IsValidDate(TestDate) then
begin
mydate:=strtodate(TestDate)
showmessage(TestDate+' is a valid date');
end
else
showmessage(TestDate+' 不是有效日期!');

if IsValidDate(TestDate1) then
begin
mydate:=strtodate(TestDat1e)
showmessage(TestDate1+' is a valid date');
end
else
showmessage(TestDate1+' 不是有效日期!');

结尾;

函数 IsValidDate(S:string):boolean;
var
FS: TFormatSettings;
DT:TD 日期时间;
开始
FS := TFormatSettings.Create('en-US');

如果 TryStrToDate(S,DT,FS) 则
结果:=true
否则
结果:=false;

结尾;

于 2021-07-31T16:12:48.857 回答