Delphi 捐赠日的变体误报
(背景)我有一个程序,它使用参数化查询在一天中的某个时间搜索数据库。所需的功能意味着我在一天结束时进行一些搜索,因此我有如下代码Delphi 捐赠日的变体误报,delphi,variant,Delphi,Variant,(背景)我有一个程序,它使用参数化查询在一天中的某个时间搜索数据库。所需的功能意味着我在一天结束时进行一些搜索,因此我有如下代码 Query.Parameters[3].Value := TimeOf(EnfOfTheDay(ToTime)); 由于时间为“31/12/1899”,因此此操作失败并出现格式错误。以下控制台程序可证明这一点,该程序在系统控制台上输出“31/12/1899”(或区域设置中的等效值) 这很容易解决,但我的问题是这是否是一个应该向Embarcadero报告的错误。我可以
Query.Parameters[3].Value := TimeOf(EnfOfTheDay(ToTime));
由于时间为“31/12/1899”,因此此操作失败并出现格式错误。以下控制台程序可证明这一点,该程序在系统控制台上输出“31/12/1899”(或区域设置中的等效值)
这很容易解决,但我的问题是这是否是一个应该向Embarcadero报告的错误。我可以看到,当TDateTime类型中的纯时间值存储到一个变量中,然后强制转换为文本时,就会出现问题。在一天中的早些时候,会产生类似“23:59”的细线
如果我将时间变量更改为TTime,则生成的字符串是数字分数(即变量尚未设置为datetime值),但我不明白为什么等于23:59:59(这是EndOfTheDay生成的)的特定分数被解释为1899日期。我天生就怀疑任何能产生1899个展期日期的东西,因为Microsoft产品的特殊问题可能意味着这是故意的。变量表示将设置为
varDate
,这在内部是一个TDateTime
变量。因此,信息仍然保存在变体中
WriteLn(Output, FormatDateTime('hh:nn:ss',V));
输出
23:59:59
可在最终调用以下函数的变量例程中找到错误:
function DateToWStrViaOS(const AValue: TDateTime): WideString;
begin
VarResultCheck(VarBStrFromDate(AValue, VAR_LOCALE_USER_DEFAULT, 0, Result),
varDate, varOleStr);
end;
VarBStrFromDate
是对操作系统的调用,它以某种方式将值舍入到1
,因此日期为“31/12/1899”
结论:如果您仍然希望在数据库中使用变体,请不要使用变体库提供的
TDateTime
的内置变体到文本转换
更新:
EndOfTheDay
将返回午夜前1毫秒的时间。转换为文本时的变体分辨率似乎基于秒(windows设计)。将时间设置为1,然后用时间:=inc毫秒(时间,-501)
进行减法将返回正确的值。(或Time:=IncSecond(Time,-1)
,如果您愿意。)如果您将示例改写为
begin
Time := Now; //TimeOf(EndOfTheDay(EncodeDate(2017,1,26)));
Time := EndOfTheDay(Time);
V := Time;
WriteLn(Output, V);
Time := TimeOf(Time);
V := Time;
WriteLn(Output, V);
ReadLn;
end.
在时间变量上放置一个手表,并在调试器中单步执行,很明显,是调用TimeOf
导致了无效结果。原因如我写这篇文章时出现的LU RD的答案所示,但后来被删除了(如果它再次出现,我会记下来),即TimeOf
将日期时间值的整数部分设置为零,默认情况下表示为“31/12/1899”。但依我看,这并不是问题的原因:问题在于将TimeOf
上的结果分配给一个变量,并将其留给RTL生成其表示
回到最初提示q的问题,如果db的SQL实现支持,那么解决这个问题的更好方法可能是使用一个构造/函数,该构造/函数只处理时间组件,不管它的日期/时间是如何存储的
顺便说一句,我认为你的q标题是错误的,问题不是“endoftheday的变量错误陈述”。您可以通过使用.Asxxxx函数来设置参数值,而不是使用.values来避免变量。您实际上应该避免使用TimeOf函数,而只使用FormatDateTime函数,因此实际答案是操作系统API VarBStrFromDate正在执行此操作错误的转换,这绝对不是Delphi的问题。请参阅我的更新,windows在转换为文本时会舍入到最接近的秒数。
begin
Time := Now; //TimeOf(EndOfTheDay(EncodeDate(2017,1,26)));
Time := EndOfTheDay(Time);
V := Time;
WriteLn(Output, V);
Time := TimeOf(Time);
V := Time;
WriteLn(Output, V);
ReadLn;
end.