更改Sysem.Variants.VarToWideStr的区域设置格式

我的应用程序上的第三方组件(FastReports)广泛使用System.Variants.VarToWideStr函数,该函数很好,但它忽略了我需要该应用程序使用的区域设置。

示例:

FormatSettings.ShortDateFormat := 'dd/mm/yyyy';
ShowMessage(VarToWideStr(Date));
FormatSettings.ShortDateFormat := 'yyyy/mm/dd';
ShowMessage(VarToWideStr(Date));

此代码始终返回相同的字符串,而忽略了我指示要使用的应用程序的区域设置。

您知道另一种更改应用程序(具体是VarToWideStr)将要使用的区域设置的方法吗。

libailiang 回答:更改Sysem.Variants.VarToWideStr的区域设置格式

我认为您对Variants单元和FastReport的糟糕设计感到困惑。 VarToWideStr调用VarToWideStrDef,这会先调用隐式_VarToWStr,然后再调用DateToWStrViaOS,最后再从单元VarBStrFromDate调用System.VarUtils

实际上VarBStrFromDate是对函数的引用,其实现取决于编译器。在Windows 32/64上,这只是对oleaut32.dllVarBstrFromDate的引用。非Windows编译器会退回到通过使用全局格式设置和'C' format specifier格式化值的DateTimeToStr(单参数不变)来转换值。

没有办法解决这个问题,因为所有这些例程都过于依赖全局状态。幸运的是,您可以将VarBStrFromDate指向您自己的实现。在单元BackupVarBStrFromDate的功能System.VarUtils中可以看到非Windows平台默认实现的启发。然后您可以执行以下操作:

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,29,10,30,50,700)));

获得结果:

  

2019-11-29
  2019-11-29 10:30:50

您需要注意,这会改变整个应用程序中依赖于VarBstrFromDate的所有例程的行为。

VarToStr也是如此。另请参见here,作者建议在转换为字符串之前先从变量中提取日期值。

本文链接:https://www.f2er.com/3009139.html

大家都在问