【问题标题】:How to check if string is a valid DateTime Format string in Delphi如何在 Delphi 中检查字符串是否是有效的 DateTime 格式字符串
【发布时间】:2010-12-23 05:14:42
【问题描述】:

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

【问题讨论】:

    标签: delphi string datetime datetime-format


    【解决方案1】:

    您可以使用以下功能:

    TryStrToDate
    TryStrToTime
    TryStrToDateTime
    

    他们尝试将字符串转换为日期/时间,如果转换成功,则返回 true。所以没有引发异常。

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

    所有函数都在 SysUtils 中定义。

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

    【讨论】:

    • 我的问题不同,我不需要检查字符串是否是有效的DateTime,我需要查看字符串是否是有效的DateTime格式(例如:“dd.MM.yy HH .mm" 是有效的日期时间格式,而 "KK.LL.MM NN.RR" 不是。
    • 是的,您可以为此目的使用该功能。您可以调整格式设置。
    【解决方案2】:

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

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

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

    对这个问题做了一点澄清:

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

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

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

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

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

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

    即便如此,我还是坚持我最初的建议(稍作调整):而只是让他们预览他们使用 当前日期时间 预定日期时间输入的格式应该强调格式字符串中的“错误”。

    假设您有一个配置对话框,您打算让用户在其中定义此设置:

    • 添加一个 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 只是封装了一个不使用 FormatDateTime 的内置 Windows 控件,因此它的格式字符串也有不同的规则。

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

    【讨论】:

    • 确实,+1。不是有效占位符的所有内容都将保持原样。再加上有效占位符的列表,这将允许用户迭代地更改格式,直到他们满意为止。如果你充实你的答案(也许有一些代码示例),我希望它被接受。
    【解决方案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】:

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

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

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

      【讨论】:

      • 其实我需要在数据库中指定 TDateTimePicker 和 TDateTime 字段的 Format 属性。我希望用户能够更改这些格式。
      • 这几乎是一回事:如果您设置 TDateTimeField 的 DisplayFormat 属性,那么这将导致根据需要调用 FormatDateTime。我的另一个答案的要点是,几乎所有字符串都是有效,尽管并非所有字符串都是有用。但是...您对 TDateTimePicker 的提及确实给工作带来了麻烦...... TDateTimeField 和 TDateTimePicker 的格式字符串使用不同的约定,因此它们不可互换!
      【解决方案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;
      

      【讨论】:

        【解决方案6】:

        过程 TForm1.BitBtn1Click(Sender: TObject);
        变量
        mydate,mydate1:TDateTime;
        TestDate,TestDate1:string;
        开始
        测试日期:='13/15/2021';
        TestDate1:='03/05/2021';

        如果 IsValidDate(TestDate) 那么
        开始
        mydate:=strtodate(TestDate)
        showmessage(TestDate+'是一个有效的日期');
        结束
        其他
        showmessage(TestDate+' 不是有效日期!');

        如果 IsValidDate(TestDate1) 那么
        开始
        mydate:=strtodate(TestDat1e)
        showmessage(TestDate1+'是一个有效的日期');
        结束
        其他
        showmessage(TestDate1+' 不是有效日期!');

        结束;

        函数 IsValidDate(S:string):boolean;
        变量
        FS:TFormatSettings;
        DT:TDatetime;
        开始
        FS := TFormatSettings.Create('en-US');

        如果 TryStrToDate(S,DT,FS) 那么
        结果:=真
        其他
        结果:=假;

        结束;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-10
          • 1970-01-01
          • 1970-01-01
          • 2013-02-13
          • 2011-02-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多