忽略TDateTime中的毫秒数(减去相同的TDateTime值不为0)

时间:2014-09-03 12:35:58

标签: mysql delphi compare milliseconds tdatetime

我的问题简而言之: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; 属性设置LastWriteTimeTDateTime 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)

3 个答案:

答案 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.

如果您需要与其他分辨率匹配,其他差异也有类似功能,例如DaysBetweenMinutesBetweenMilliSecondsBetween。这是一个适用于各种分辨率(完全匹配,日,小时,分钟或秒)的效用函数:

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;