Delphi:如何确定和清空TDatetime值

21

似乎没有办法将NULL(即“未分配的值”)赋给TDateTime变量。

我能想到的唯一方法是使用类似以下的方式:

function isNull(aDate : TDateTime) : boolean;
const NullDate = 0.0;
var aNullDate : TDatetime;
    ms : Int64;
begin
  aNullDate := NullDate;
  ms := MilliSecondsBetween(aDate,aNullDate);
  result := (ms = Int64(0));
end;

有没有人知道更好的解决方案,避免日期数值与0重叠?

负的TDateTime数值是否危险?(作为先前目的的可靠资源)


如果您打算按照我想的那样使用此函数,那么NullDate应该是一个全局常量,对吧? - Andreas Rejbrand
我在比较一个被赋值为0的TDateTime变量和常量值0时遇到了问题。即使是这样简单的if语句也无法检查条件:var v_datetime: TDatetime; v_datetime := 0; if (v_datetime = 0) then actionToTake - xsubira
3
那是由于浮点数模糊造成的。请使用 Math.IsZero - Andreas Rejbrand
0 是一个有效的日期,负数日期也是可以的。0 表示 1899 年 12 月 30 日午夜。负数则表示在此之前的日期。 - Nick Hodges
5个回答

20

正如Andreas所写,TDateTime类型实际上是一个double,因此不是“可空”的。我使用

const
  c_UnassignedDate = -693594;

对于空的日期值,因为它表示一个不可能存在的日期 00/00/0000。但例如DevExpress使用

NullDate = -700000;
InvalidDate = NullDate + 1;

因此似乎不存在统一的标准值,您应选择适合您需求的值。


2
不存在都为0(零)的日期。在数据库中,如果日期未被分配,则应使用NULL,而不是某个神奇的日期。 - ain
1
是的,抱歉。我只看了那个日期的年份部分... 如果某个日期时间列的值将为“NULL”,而我必须严格将此值存储到“TDateTime”字段中,我可能会使用您的“c_UnassignedDate”常量值。 [+1] - TLama
你如何确定-693594代表日期0/0/0000? - Rob Kennedy
1
@RobпјҡжҲ‘зҢңжҳҜеӣ дёә-693591д»ЈиЎЁзҡ„жҳҜ0000-01-03пјҢ-693592д»ЈиЎЁзҡ„жҳҜ0000-01-02пјҢиҖҢ-693593еҲҷд»ЈиЎЁзҡ„жҳҜ0000-01-01пјҢиҮіе°‘ж №жҚ®DateTimeToStrеҮҪж•°жҳҜиҝҷж ·зҡ„гҖӮ - Andreas Rejbrand
@RobKennedy 只需执行 ShowMessage(FormatDateTime('dd.mm.yyyy',-693594));,它会弹出带有 00.00.0000 的对话框。 - ain
@ain:与每个较小的值一样。我的分析表明,-693594是具有此属性的最大负整数。 - Andreas Rejbrand

11
首先,您需要定义“空的TDateTime值”的含义。 TDateTime值是一个双精度浮点数,其中日期编码在整数部分,时间编码在小数部分。因此,最接近“null日期”的东西可能是0
因此,只需测试ADate <> 0以测试日期是否为“null”。
但要注意:如果声明一个TDateTime局部变量,则在给它赋值之前它不一定为=0。它可以是任何值。当然,对于类型为integerdoubleboolean等的变量也适用。
此外,我认为值为0TDateTime编码了日期1899-12-30。
最后,负的TDateTime值是完全正常的。例如,-5000对应于1886-04-22
我不太明白您代码的意图。如果您想将0用作“未分配”值(如果您对接近1899-12-30的日期感兴趣,则这很糟糕),为什么不简单地这样做?
function IsUnassigned(ADate: TDateTime): boolean;
begin
  result := ADate = 0;
end;

或者,可能(但不完全等效!)

function IsUnassigned(ADate: TDateTime): boolean;
begin
  result := IsZero(Date);
end;
在他的回答中,ain提供了几个更加合理的“未指定日期”值选择。

负时间日期最终变得毫无意义,当日历破裂时。 - David Heffernan
@David:说得好。因此,“未分配”值实际上有很多合理的选择。 - Andreas Rejbrand
1
在这里使用NaN作为显式值不是很有用吗?然后您可以使用IsNaN来测试条件。 - Brian Frost

4
在库Spring Framework for Delphi(http://www.spring4d.org)的单元Spring.Persistence.Core.Session.pas中,方法TSession.ExecuteScalar<T>在结果为NULL时使用了Default(T);的值。您的函数可能看起来像这样。
function IsNull(ADate: TDateTime): Boolean;
begin
  Result := ADate = Default(TDateTime);
end;

1
使用PDateTime代替TDateTime,并将其发送为nil值。如果没有指向该值的指针,则结果没有值。
要检查值,请使用Assigned ptr:
MyDatePointer := nil;
if ( Assigned(MyDatePointer)) then ...

1
对于0和-1之间的值是未定义的,这意味着-0.5的是一个未定义的值,并且作为NaN的替代品,可用于表示空日期。DateTimeToString将以与+0.5相同的方式显示-0.5;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接