简而言之: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这为我提供了自30.12.1899以来的日子和十进制值的时间。
示例值:
// 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 (我做而不是,比较aTicks和bTicks值)。
我是否必须改变获取本地文件TDateTime的方式(在我使用WinAPI时,GetLastWriteTimeUTC没有提供正确的UTC时间)?
我认为这不是一个很难的问题,但我不知道如何解决这个问题。 TDateTime是否存储隐藏的毫秒?在调试模式中,我看不到任何毫秒,也不知道如何从我的TDateTime (使用XE2)中获取这个值。
这里是关于我的项目的一些额外的细节
我是这样得到TDateTime b值的
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;如果来自MySQL数据库的文件是“较新的”,我将替换它并通过LastWriteTime TDateTime a属性设置它:SetLastWriteTimeUTC(a) (以及来自MySQL (a)的TDateTime值没有任何毫秒值)。所以这个问题不应该再发生了,但它确实发生了。
我的TDateTime数据库上的MySQL值来自于
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)我希望这是足够的信息,而不是太多。
诚挚的问候,
尼可拉斯
更新:
代码与我的主程序“相同”,正如我上面所说,错误的DateTime比较并不总是在某些文件上触发(在我的例子中是$Default10.dsk)。
uses
SysUtils,
Soap.SoapHttpTrans,
DateUtils,
Windows,
System.IOUtils,
Soap.XSBuiltIns;
var
fad: TWin32FileAttributeData;
SystemTime: TSystemTime;
lastwritetimeUtcA: TDateTime;
lastwritetimeUtcB: TDateTime;
sourceFileA: string;
sourceFileB: string;
lastwritetimeXS: TXSDateTime;
begin
while True do
begin
sourceFileA := 'Path to a file on your computer no matter which';
sourceFileB := 'Path to another file on your computer no matter which';
//GetLastWriteTime from local file
GetFileAttributesEx(PWideChar(sourceFileA),GetFileExInfoStandard,@fad);
FileTimeToSystemTime(fad.ftLastWriteTime, SystemTime);
lastwritetimeUtcA := SystemTimeToDateTime(SystemTime);
//Set the localfile lastwritetime to the theoretical mySQL file
// in my main program there does not exist a mySQL file (only a value of TDateTime in the TDateTime column of my database where i store the lastwritetime from the local files
TFile.SetLastWriteTimeUtc(sourceFileB, lastwritetimeUtcA);
//Get the LastWriteTime from theoretical mySQL file
// in my main program i get the lastwritetime value from the MySQL database via WCF that is the reason for the convertion of XSDateTime.AsUTCDateTime and DateTimeToXSDateTime
GetFileAttributesEx(PWideChar(sourceFileB),GetFileExInfoStandard,@fad);
FileTimeToSystemTime(fad.ftLastWriteTime, SystemTime);
lastwritetimeUtcB := SystemTimeToDateTime(SystemTime);
//Convert lastwritetime to XSDatetime - how i do it in my program
lastwritetimeXS := DateTimeToXSDateTime(lastwritetimeUtcB);
{Convert it back to DateTime}
lastwritetimeUtcB := lastwritetimeXS.AsUTCDateTime;
//Compare them
if lastwritetimeUtcA = lastwritetimeUtcB then
Writeln('Same time')
else
writeln('Not same time');
Sleep(500);
end;
end;发布于 2014-09-03 15:28:13
如果要比较两个TDateTime值并与第二个值匹配,忽略毫秒的差异,请使用来自DateUtils单元的SecondsBetween:
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; 发布于 2014-09-04 07:43:19
您还可以通过将TDateTime转换为string并比较它们来播放。这样,您就可以使许多复杂的条件购买设置时间格式。例如,您可以检查日期是否在同一小时内,忽略了分钟和秒:
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 ...发布于 2019-02-12 23:51:18
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;https://stackoverflow.com/questions/25644507
复制相似问题