Mar*_*lot 2 delphi date-formatting delphi-10.1-berlin
我的应用程序上的第三方组件(FastReports)广泛使用System.Variants.VarToWideStr函数,该函数很好,但它忽略了我需要该应用程序使用的区域设置。
例:
FormatSettings.ShortDateFormat := 'dd/mm/yyyy';
ShowMessage(VarToWideStr(Date));
FormatSettings.ShortDateFormat := 'yyyy/mm/dd';
ShowMessage(VarToWideStr(Date));
Run Code Online (Sandbox Code Playgroud)
此代码始终返回相同的字符串,而忽略了我指示要使用的应用程序的区域设置。
您是否知道另一种更改应用程序(具体是VarToWideStr)将要使用的区域设置的方法?
我认为您对Variants单元和FastReport的糟糕设计感到困惑。VarToWideStr呼叫VarToWideStrDef它调用隐含_VarToWStr,然后DateToWStrViaOS,最后VarBStrFromDate从单元System.VarUtils。
实际上VarBStrFromDate是对函数的引用,其实现取决于编译器。在Windows 32/64上,这只是从中对VarBstrFromDate的引用oleaut32.dll。非Windows编译器回退到通过DateTimeToStr(单参数不变)使用全局格式设置和'C'格式说明符来格式化值的方式转换值。
没有办法解决这个问题,因为所有这些例程都过于依赖全局状态。幸运的是,您可以指向VarBStrFromDate自己的实现。您可以从BackupVarBStrFromDateunit 功能中看到的非Windows平台默认实现的启发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)));
Run Code Online (Sandbox Code Playgroud)
得到结果:
2019-11-29
2019-11-29 10:30:50
您需要注意,这会更改VarBstrFromDate整个应用程序中依赖的所有例程的行为。
同样的道理VarToStr。另请参阅此处,作者建议在转换为字符串之前从变量中提取日期值。