我认为您被 Variants 单元和 FastReport 的糟糕设计搞砸了。VarToWideStr
calls VarToWideStrDef
这会调用隐式的_VarToWStr
, then DateToWStrViaOS
最后VarBStrFromDate
来自单位System.VarUtils
.
In fact VarBStrFromDate
是对函数的引用,其实现取决于编译器。在 Windows 32/64 上,这只是对VarBstrFromDate https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-varbstrfromdate from oleaut32.dll
。非 Windows 编译器回退到通过以下方式转换值DateTimeToStr
(单参数不变)使用全局格式设置和'C' 格式说明符 http://docwiki.embarcadero.com/Libraries/Rio/en/System.SysUtils.DateTimeToString格式化该值。
没有什么好的办法可以解决这个问题,因为所有这些例程都过于依赖全局状态。幸运的是(?)你可以指出VarBStrFromDate
到你自己的实现。您可以从函数中看到的非 Windows 平台的默认实现中获得启发BackupVarBStrFromDate
单位的System.VarUtils
。然后你可以做这样的事情:
uses
System.SysUtils, System.Variants, System.VarUtils, System.DateUtils;
function MyVarBstrFromDate(dateIn: TDateTime; LCID: Integer; dwFlags: Integer;
out bstrOut: WideString): HRESULT; stdcall;
begin
if LCID = VAR_LOCALE_USER_DEFAULT then
begin
bstrOut := DateTimeToStr(dateIn);
Result := VAR_OK;
end
else
Result := VAR_NOTIMPL;
end;
{ ... }
System.VarUtils.VarBstrFromDate := MyVarBstrFromDate;
FormatSettings.ShortDateFormat := 'yyyy-mm-dd';
FormatSettings.LongTimeFormat := 'hh:nn:ss';
Writeln(VarToWideStr(EncodeDate(2019, 11, 29)));
Writeln(VarToWideStr(EncodeDateTime(2019, 11, 29, 10, 30, 50, 700)));
得到结果:
2019-11-29
2019-11-29 10:30:50
您需要意识到这会改变所有依赖于VarBstrFromDate
贯穿整个应用程序。
同样适用于VarToStr
。也可以看看here https://support.embarcadero.com/article/35913,作者建议在转换为字符串之前从变体中提取日期值。