我的问题简而言之:TDateTime A
(03.09.2014 13:40) - TDateTime B
(03.09.2014 13:40)= -1
我有两个想要比较的TDateTime值,首先我使用=
运算符来检查它们是否相同,但经过几次测试后我意识到这在我的情况下不起作用。令人困惑的是,它在大部分时间内效果很好,但有时却没有。
我从现有文件中获取LastWriteTime
属性中的一个值,而另一个值来自MySQL数据库。
以下是一些代码:
TDateTime a := FileList[loop].Lastwritetime.AsUTCDateTime; // TDateTime from MySQL
TDateTime b := GetLastwritetimeUtc(Sourcedirectory); // TDateTime from my local file
if (CompareDateTime(a, b) = 0) then
begin
// do some stuff.
end;
现在如前所述,这个简单的代码大部分时间都在工作,但是对于某些TDateTime
值,我得到一个否定结果,这意味着MySQL数据库中的TDateTime
值早于我的本地文件TDateTime
。
所以我开始调试:
double aTicks := a; // MySQL TDateTime
double bTicks := b; // Local file TDateTime
这为我提供了自1999年12月30日以来的日子和小数值时间。
示例值:
// a = 02.09.2014 11:42:01
// b = 02.09.2014 11:42:01
// aTicks = 41884,4875115741
// bTicks = 41884,4875153356
不相同的小数应该是毫秒或不是(从xxxx,4875开始)?
现在,如果我比较它们(例如CompareDateTime(a,b)
或a = b
)我不会得到0
/ true
(我不比较{{1} }}和aTicks
值)。
我是否必须按照自己的方式更改本地文件bTicks
(目前我正在使用WinAPI,TDateTime
没有提供正确的UTC时间)?
我认为这不是一个很难的问题,但我不知道如何解决这个问题。 ``GetLastWriteTimeUTC
是否隐藏了毫秒?在调试模式下,我看不到任何毫秒,我不知道如何从我的TDateTime
中获取此值(使用Delphi XE2)。
以下是有关我的项目的一些额外详情
我以这种方式获得TDateTime
值
TDateTime b
如果来自MySQL数据库的文件是"更新"我替换它并以这种方式从我的MySQL function GetLastwritetimeUtc(source: String): TDateTime;
var
fad: TWin32FileAttributeData;
SystemTime: TSystemTime;
lastwritetimeUtc: TDateTime;
begin
GetFileAttributesEx(PWideChar(source),GetFileExInfoStandard,@fad);
FileTimeToSystemTime(fad.ftLastWriteTime, SystemTime);
lastwritetimeUtc := SystemTimeToDateTime(SystemTime);
result := lastwritetimeUtc;
end;
属性设置LastWriteTime
:TDateTime a
(以及来自MySQL(a)的SetLastWriteTimeUTC(a)
值没有任何毫秒值) 。所以这个问题不应该再出现,但确实如此。
我的MySQL数据库上的TDateTime
值来自此
TDateTime
我希望这是足够的信息而不是太多。
致以最诚挚的问候,
的Niclas
更新
代码与#34;相同"作为我的主程序,正如我上面所说的错误的DateTime比较不会一直触发一些文件(在我的情况下是$ Default10.dsk)。
XSDateTime c := DateTimeToXSDateTime(GetLastwritetimeUtc(sourceDirectory));
// i send this via WCF service to the MySQL database and store it in a `TDateTime` column (which does not include milliseconds)
答案 0 :(得分:1)
如果您想比较两个TDateTime
值并与第二个值匹配,忽略毫秒差异,请使用SecondsBetween
单元中的DateUtils
:
program Project1;
uses
SysUtils, DateUtils;
var
dtOne, dtTwo: TDateTime;
begin
dtOne := 41884.4875115741;
dtTwo := 41884.4875153356;
if SecondsBetween(dtOne, dtTwo) = 0 then
WriteLn('Dates the same without MS')
else
WriteLn('Not the same dates.');
ReadLn;
end.
如果您需要与其他分辨率匹配,其他差异也有类似功能,例如DaysBetween
,MinutesBetween
和MilliSecondsBetween
。这是一个适用于各种分辨率(完全匹配,日,小时,分钟或秒)的效用函数:
type
TDiffResolution = (tdrExact, tdrDay, tdrHour, tdrMin, tdrSec);
function IsSameDateTime(dValOne, dValTwo: TDateTime;
const Resolution: TDiffResolution = tdrSec): Boolean;
begin
case Resolution of
tdrExact: Result := MillisecondsBetween(dValOne, dValTwo) = 0;
tdrDay: Result := IsSameDay(dValOne, dValTwo);
tdrHour: Result := HoursBetween(dValOne, dValTwo) = 0;
tdrMin: Result := MinutesBetween(dValOne, dValTwo) = 0;
tdrSec: Result := SecondsBetween(dValOne, dValTwo) = 0;
else
raise Exception.CreateFmt('Invalid resolution value (%d) provided.',
[Ord(Resolution)]);
end;
end;
样品使用:
dtOne := 41884.4875115741;
dtTwo := 41884.4875153356;
if IsSameDateTime(dtOne, dtTwo, tdrSec) then
WriteLn('Dates are the same.')
else
WriteLn('Dates are different.');
ReadLn;
答案 1 :(得分:0)
您也可以将TDateTime
转换为字符串并进行比较。通过这种方式,您可以制定更复杂的条件来设置时间格式。例如,您可以检查日期是否在同一小时内,忽略分钟和秒:
If FormatDateTime('yyyymmddhh', Date1) = FormatDateTime('yyyymmddhh', Date2) ...
另一种方法是解码它们并比较您感兴趣的部分,如:
DecodeDateTime (Date1, Y1, M1, D1, H1, N1, S1, mS1);
DecodeDateTime (Date2, Y2, M2, D2, H2, N2, S2, mS2);
If (Y1 = Y2) and (M1 = M2) and (D1 = D2) and (H1 = H2) then ...
答案 2 :(得分:0)
dt := Now;
dtWithoutMilliseconds := SecondsBetween(0,dt)*OneSecond;
//or
dtWithoutMilliseconds := dt-MillisecondOf(dt)*OneMillisecond;
//or
dtWithoutMilliseconds := Trunc(dt)+Trunc(Frac(dt)*SecsPerDay)/SecsPerDay;
//or simply
dtWithoutMilliseconds := Trunc(dt)+Trunc(Frac(dt)*3600)/3600;