Delphi XE2 FormatDateTime 传递 -693594

标签 delphi delphi-xe2 delphi-2006 formatdatetime

我们这里遇到了一些问题。我们已经从 Delphi 2006 升级到 Delphi XE2,并且正在转换我们的代码。

问题是,我们通过应用程序和数据库记录使用值 -693594 来表示无日期(零日期)。在 Delphi 2006 中,FormatDateTime 函数会将其正确格式化为 00/00/0000(给定日期格式为 dd/mm/yyyy)。

然而,在 Delphi XE2 中,他们在 System.SysUtils 的 DateTImeToTimeStamp 函数中添加了对 ValidateTimeStampDate 的调用,这会引发错误“无效浮点运算”。传递任何大于 -693594 的值(例如 -693593)都可以正常工作。

还有其他人遇到过这个问题和/或有人知道解决方法吗?

最佳答案

如果您真的迫切希望修补回以前的行为,您可以使用如下内容:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
  OldProtect: DWORD;
begin
  if VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then
  begin
    Move(NewCode, Address^, Size);
    FlushInstructionCache(GetCurrentProcess, Address, Size);
    VirtualProtect(Address, Size, OldProtect, @OldProtect);
  end;
end;

type
  PInstruction = ^TInstruction;
  TInstruction = packed record
    Opcode: Byte;
    Offset: Integer;
  end;

procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
  NewCode: TInstruction;
begin
  NewCode.Opcode := $E9;//jump relative
  NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
  PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;

function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
const
  FMSecsPerDay: Single = MSecsPerDay;
  IMSecsPerDay: Integer = MSecsPerDay;
var
  LTemp, LTemp2: Int64;
begin
  LTemp := Round(DateTime * FMSecsPerDay);
  LTemp2 := (LTemp div IMSecsPerDay);
  Result.Date := DateDelta + LTemp2;
  Result.Time := Abs(LTemp) mod IMSecsPerDay;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(FormatDateTime('dd/mm/yyyy', -693594));
end;

initialization
  RedirectProcedure(@System.SysUtils.DateTimeToTimeStamp, @DateTimeToTimeStamp);

end.

这适用于 32 位代码。如果新旧函数都驻留在同一个可执行模块中,它也适用于 64 位代码。否则跳转距离可能会超出32位整数的范围。如果您的 RTL 驻留在运行时包中,它也将不起作用。这两个限制都可以轻松解决。

此代码的作用是将所有对 SysUtils.DateTimeToTimeStamp 的调用重新路由到本单元中实现的版本。本单元中的代码只是 XE2 源代码中的 PUREPASCAL 版本。

满足您评论中概述的需求的唯一其他方法是修改并重新编译 SysUtils 单元本身,但我个人避免这种解决方案。

enter image description here

关于Delphi XE2 FormatDateTime 传递 -693594,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9255337/

相关文章:

delphi - 用Delphi实现读取文件时的超时

delphi - 解决网络快捷方式

delphi - 如何使用 Windows 登录凭据对用户进行身份验证?

delphi - Delphi 中 TDataSetProvider 所需的信息

delphi - 在delphi中使用两个exe文件时相对和绝对路径之间的冲突

macos - 我可以使用 Delphi XE2 (v16) 轻松编译适用于 Mac OS X 的现有 Delphi 应用程序吗?

sql-server - 使用 TQuery.Locate() 函数查找其他匹配项

multithreading - 退出时应用程序在 SysUtils -> DoneMonitorSupport 中挂起

multithreading - Delphi - TDictionary 线程安全吗

delphi - FireMonkey (Delphi XE2) 中的错误光标