如何从 TDateTimePicker 读取日期和时间

How to read both Date and Time from a TDateTimePicker

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

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

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

看起来不错,现在让我们阅读它:

showmessage(DateTimeToStr(DateTimePicker1.Date)); 

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

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

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

但是不行,还是不行。将种类 属性 从 dtkDate 切换到 dtkTime 会删除我在 hh:mm 部分的输入。


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

所以我的问题是:

还有一道Delphi设计题:

请注意,我post这个问题主要是为了避免初学者做同样冗长的调试过程而受挫。

What I want to do (seems pretty simple) is to display a date + time in a TDateTimePicker, with the calendar integrated, and be able to read it after its value has changed.

I'd like to use the dd/MM/yyyy hh:mm format

抱歉,你不能。 TDateTimePicker 设计为仅适用于日期或时间,但不能同时适用于两者。

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

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

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

Value := DateOf(DateTimePicker1.Date);

与值的 Time 属性 和 DATE 部分相同。您可以使用 DateUtils.TimeOf() 函数忽略任何潜在的垃圾:

Value := TimeOf(DateTimePicker1.Time);

Is there an easy way to solve my simple and very common problem (a real DateTimePicker) ?

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

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

如果要显示一个TDateTime,则反其道而行之:

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

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

Why is there a Format property that is basically useless and misleading ?

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

Having a TimeFormat, DateFormat, and proper format validation process isn't that hard.

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

这些天我遇到了同样令人沮丧的问题。但在我的例子中,我只需要从 TDateTimePicker 字段中获取完整的日期和时间(不需要以编程方式设置它,但这不会很困难)。所以我所做的是创建我自己的 TDateTimePicker 并创建一个新的 public 属性 来获取字段 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,它的工作方式与您想要的一样。

我有完全相同的问题。 感谢 Andre,Andre 解决方案就像一个魅力)。

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

解决方案:为避免这种情况,只需在您使用 TDateTimePicker 组件的表单中声明以下 class: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;

您可以 link 将同一表单上所有 TDateTimePicker 组件的所有 OnChange 事件转换为正常的 OnChange 事件...瞧!

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