моя проблема вкратце: TDateTime A
(09.03.2014 13:40) - TDateTime B
(09.03.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
я получаю отрицательный результат, который должен означать, что мое значение TDateTime
из базы данных MySQL раньше, чем значение 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
(используя Delphi 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
из моего атрибута MySQL TDateTime a
следующим образом: SetLastWriteTimeUTC(a)
(а мои значения TDateTime
из MySQL (a) не имеют значения в миллисекундах). Таким образом, проблема не должна возникать снова, но она возникает.
Значение 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;
TDateTime
из моего MySQL и моих локальных файлов. Но несколько файлов (всегда одно и то же в одном случае) несопоставимы, тогда ситуация описана выше. Я удалил эти файлы и воссоздал их с данными из моей базы данных MySQL, но это все еще происходит. РЕДАКТИРОВАТЬ: я думаю, что знаю, как воссоздать его, и предоставлю вам те же файлы и т. д., пожалуйста, подождите несколько минут или больше. - person TryToSolveItSimple   schedule 03.09.2014TDirectory.SetLastWriteTimeUtc
наTFile.SetLastWriteTimeUtc
и удалите;
перед else, компилятор скажет, где. Используйте любые два файла. Проблема заключается в сравнении с плавающей запятой. - person Sertac Akyuz   schedule 03.09.2014TDateTime
. Есть ли более умный способ, чемDecodeDateTime
иEncodeDateTime
DateTime
? Или я должен использовать плавающую точку и сравнить ее с математическим блоком? - person TryToSolveItSimple   schedule 03.09.2014