【问题标题】:How to read both Date and Time from a TDateTimePicker如何从 TDateTimePicker 中读取日期和时间
【发布时间】:2017-03-23 09:34:50
【问题描述】:

我真的很困惑。我想要做的(似乎很简单)是在 TDateTimePicker 中显示日期+时间,并集成日历,并在其值更改后能够读取它。

我想使用 dd/MM/yyyy hh:mm 格式。

由于 TDateTimePicker 不是 TDateOrTimePicker,因此使用的是:

  • 种类:dtkDate(显示日历)
  • 格式:'dd/MM/yyyy hh:mm'

看起来不错,现在让我们读一下吧:

showmessage(DateTimeToStr(DateTimePicker1.Date)); 

仅正确显示日期。未考虑 hh:mm 部分的更改。我总是得到默认值。 然后我想:还有一个Time属性,也许我需要读取2次的值。

 showmessage(DateTimeToStr(DateTimePicker1.Time));
 showmessage(DateTimeToStr(DateTimePicker1.Date));

但我的输出(和问题)与以前完全相同。所以现在,让我们尝试将这个 Kind 属性更改为 dtkTime,然后读取时间,然后将其切换回 dtkDate,然后读取日期。

但是不,它仍然不起作用。将 Kind 属性从 dtkDate 切换到 dtkTime 会擦除我在 hh:mm 部分的输入。


我知道我实际上应该使用 2 个 TDateTimePickers :一个用于日期,一个用于时间。

所以我的问题是:

  • 有没有一种简单的方法可以解决我的简单且非常常见的问题(a 真正的 DateTimePicker)?

还有一道德尔福设计题:

  • 为什么会有一个基本没用的Format属性 误导?拥有 TimeFormat、DateFormat 和正确的格式 验证过程并不难。

请注意,我发布这个问题主要是为了避免初学者做同样冗长的调试过程和挫败感。

【问题讨论】:

  • 嗯,阅读文档可以节省您一些时间:TDateTimePicker 显示一个用于输入日期或时间的列表框。注意。进一步:因为 TDateTimePicker 是 Windows 控件的包装,所以这些格式不能通过更改 SysUtils 单元中的格式变量来更改。但是,您可以使用 Windows API 调用 DateTime_SetFormat 以编程方式指定这些设置。
  • @TomBrunberg 是的,我应该在“尝试使其工作”之前看到这一点。我无法从 IDE 访问文档这一事实并没有帮助。
  • @EtsitpabNioliv 我手头没有 Delphi 来检查实现。但文档表明:(1)DateTime 按原样返回基础字段。 (2)Date使用Get...方法;一个从基础领域剥离时间的机会。 (3) Time 同样能够去除基础字段值的日期部分。
  • 一个设计良好的组件/类不应该要求你阅读文档上帝帮助我们!!
  • @CraigYoung:DateTime 属性仅按原样返回基础TDateTime 成员。 Date 属性返回TDateTime 类型转换为TDate (它并没有真正剥离任何东西),Time 属性返回TDateTime 类型转换为TTime (这也没有真的剥离任何东西)。他们应该改用DateOf()TimeOf() 函数(或等效数学)。这在过去导致我的应用程序出现错误,我不得不手动使用DateOf()/TimeOf() 来解决。

标签: delphi datetime datetimepicker datetime-format delphi-xe7


【解决方案1】:

我想做的(看起来很简单)是在 TDateTimePicker 中显示日期+时间,并集成日历,并在其值更改后能够读取它。

我想使用 dd/MM/yyyy hh:mm 格式

对不起,你不能。 TDateTimePicker 旨在仅与日期或时间一起使用,但不能同时与两者一起使用。

如果将Kind 属性设置为dtkDate,则可以指定自定义日期格式,但忽略任何时间格式,并且未定义使用Time 属性。

如果您将Kind 属性设置为dtkTime,您可以指定自定义TIME 格式但忽略任何DATE 格式,并且未定义使用Date 属性。

读取Date 属性时,只有值的DATE 部分有效。在一个完美的世界中,TIME 部分总是为零,但我有时看到它包含垃圾。但是,您可以使用 DateUtils.DateOf() 函数轻松忽略这一点:

Value := DateOf(DateTimePicker1.Date);

Time 属性和值的 DATE 部分也是如此。您可以使用DateUtils.TimeOf() 函数来忽略任何潜在的垃圾:

Value := TimeOf(DateTimePicker1.Time);

有没有一种简单的方法可以解决我的简单且非常常见的问题(一个真正的 DateTimePicker)?

使用TDateTimePicker 的唯一真正解决方案是使用两个独立的TDateTimePicker 控件,一个用于日期,另一个用于时间。您可以在需要时将这两个值组合在一起:

Value := DateOf(DateTimePicker1.Date) + TimeOf(DateTimePicker2.Time)

如果你想显示TDateTime,则相反:

DateTimePicker1.Date := DateOf(Value);
DateTimePicker2.Time := TimeOf(Value);

否则,请找到支持您需要的第 3 方选择器(或自己编写)。

为什么会有一个基本无用且具有误导性的 Format 属性?

这不是无用和误导。它非常有用,但仅限于当前 Kind 设置的范围内。

拥有 TimeFormat、DateFormat 和正确的格式验证过程并不难。

TDateTimePicker 只是 Win32 Date and Time Picker control 的一个薄包装器,它没有这样的功能。当然,他们可以编写自定义逻辑,以允许在保留不同设置的情况下在 Kind 值之间切换,但这并不是 DTP 控件的真正用途。您将Kind 设置一次,Format 设置一次,然后根据需要处理输入和输出。没有来回切换。仅仅因为您可以动态切换Kind 并不意味着您应该。如果您认为编写这样的自定义逻辑很容易,欢迎您在自己的代码中进行。

【讨论】:

    【解决方案2】:

    我也有同样的问题。 多亏了安德烈,安德烈的解决方案就像一个魅力)。

    ISSUE : 我们需要创建一个新单元,创建一个新组件并将该组件注册到另一个包,以便能够在设计时设置表单。

    解决方案:为避免这种情况,只需在使用 TDateTimePicker 组件的表单中声明以下类:THackDateTimePicker

    ...
    type
      // this class is just to access protected Caption property
      THackDateTimePicker = class(TDateTimePicker);
    
      TSymbolInfoForm = class(TForm)
      ...
    end;
    

    然后像这样实现 OnChange 事件:

    procedure TSymbolInfoForm.dtpChange(Sender: TObject);
    begin
       TDatetimePicker(Sender).Datetime := StrToDateTime(THackDateTimePicker(Sender).Caption);
    end;
    

    您可以将同一表单上所有 TDateTimePicker 组件的所有 OnChange 事件链接到理智的 OnChange 事件......瞧!

    【讨论】:

      【解决方案3】:

      这些天我遇到了同样令人沮丧的问题。但在我的情况下,我只需要从 TDateTimePicker 字段中获取完整的日期和时间(不需要以编程方式设置它,但这不会很困难)。所以我所做的是创建我自己的 TDateTimePicker 并创建一个新的公共属性,该属性获取字段 Caption 并设置为 DateTime(Caption 受 documentation 的保护)。这是我的代码:

      unit uZDateTimePicker;
      
      interface
      
      uses
       Vcl.ComCtrls, SysUtils;
      
      type
        TZDateTimePicker = class(TDateTimePicker)
        private
          procedure SetDateAndTime;
      
        protected
          procedure Change; override;
      
        end;
      
      implementation
      
      { TZDateTimePicker }
      
      procedure TZDateTimePicker.Change;
      begin
        SetDateAndTime
      end;
      
      procedure TZDateTimePicker.SetDateAndTime;
      begin
        DateTime := StrToDateTime(Caption);
        inherited;
      end;
      
      
      end.
      

      就这么简单。

      另外,如果您使用 DevExpress 组件,您将使用 TcxDateEdit,它可以按您的意愿工作。

      【讨论】:

        【解决方案4】:

        以上答案都正确,可以从 datetimepicker.DateTime 属性中获取日期时间,也可以通过设置“格式”属性来显示日期和时间 dd/MM/yyyy hh:mm

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-11-03
          • 1970-01-01
          • 2019-07-30
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多