delphi - 更改 Sysem.Variants.VarToWideStr 的区域设置格式
问题描述
我的应用程序上的第三方组件 (FastReports) 广泛使用 System.Variants.VarToWideStr 函数,这很好,只是它忽略了我需要该应用程序使用的区域设置。
例子:
FormatSettings.ShortDateFormat := 'dd/mm/yyyy';
ShowMessage(VarToWideStr(Date));
FormatSettings.ShortDateFormat := 'yyyy/mm/dd';
ShowMessage(VarToWideStr(Date));
此代码始终返回相同的字符串,忽略我指示要使用的应用程序的区域设置。
您是否知道另一种更改应用程序(具体是 VarToWideStr)将要使用的区域设置的方法?
解决方案
我认为您被变体单元和 FastReport 的糟糕设计搞砸了。VarToWideStr
调用VarToWideStrDef
隐式_VarToWStr
,然后DateToWStrViaOS
最后VarBStrFromDate
从 unit调用System.VarUtils
。
实际上VarBStrFromDate
是对函数的引用,它的实现依赖于编译器。在 Windows 32/64 上,这只是对VarBstrFromDate的引用oleaut32.dll
。非 Windows 编译器回退到通过DateTimeToStr
(单参数不变量)转换值,它使用全局格式设置和“C”格式说明符来格式化值。
没有好的方法可以解决这个问题,因为所有这些例程都过多地依赖于全局状态。幸运的是(??)你可以指向VarBStrFromDate
你自己的实现。BackupVarBStrFromDate
您可以从unit函数中看到的非 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)));
得到结果:
2019-11-29
2019-11-29 10:30:50
您需要注意,这会改变依赖于VarBstrFromDate
整个应用程序的所有例程的行为。
也是如此VarToStr
。另请参阅此处,作者建议在转换为字符串之前从变量中提取日期值。
推荐阅读
- python-3.x - 如何交换包含列表且大小不同的 2 个熊猫数据框中的行?
- python - Python:get() 不适用于 tkinter python
- swift - 在 TableView 中禁用标题上的删除/编辑?
- delphi - 如何更改 IdMappedPortTCP1 发送到 MappedPort 的 ip
- javascript - 选择一个
- 使用 getElementsByClassName 方法的元素
- c# - 如何计算一种方法的使用次数?
- java - 我无法将图像直接保存到应用程序目录的文件夹中
- web - IIS 上的部署问题
- javascript - 为什么反应路由器网址更改但组件未加载到我的嵌套路由器应用程序中
- blogger - 如何在博客帖子中创建带有图像的帖子列表