Lub*_*bos 0 windows delphi delphi-10.1-berlin
我有一个旧的申请.它具有存储在其数据中的本地化格式的日期.此字符串仅用于显示,因此可以将其置于本地化表单中.现在我们需要将它重用为TDateTime.这似乎很简单:因为我们从DateToStr获取了字符串,我们将使用StrToDate将其转换回来.所以我写了一个小的控制台程序来验证它:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
var
S:String;
D: TDateTime;
begin
S := DateToStr(Now);
Writeln(S);
D := StrToDate(S); //! throws an EConvertError
Readln;
end.
Run Code Online (Sandbox Code Playgroud)
它抛出一个EConvertError:Project Project1.exe引发异常类EConvertError,消息为''28.9. 2017'不是有效日期'.这是不正确的,异常提到的日期是有效的!它刚刚通过DateToStr生成.这对我来说完全没有意义.这可能是Windows 10中的错误吗?
如果我dd. M.yyyy在操作系统的区域设置中输入短日期格式,我可以复制您的问题.或者dd. M. yyyy要在问题中引用确切的错误消息,请注意格式字符串中的空格.
StrToDate失败的原因是ScanDate"sysutils.pas" 中的函数失败并返回False.ScanDate失败的原因是默认格式设置记录中的日期分隔符不正确.
RTL使用以下代码检索日期分隔符,其中LOCALE_SDATE为LocaleType参数传递,并为参数传递"/" Default.
...
var
Buffer: array[0..1] of Char;
begin
if GetLocaleInfo(Locale, LocaleType, Buffer, 2) > 0 then
Result := Buffer[0] else
Result := Default;
Run Code Online (Sandbox Code Playgroud)
在您的日期格式的情况下,所需的缓冲区是3个字符,因为RTL仅提供API失败的2个字符,ERROR_INSUFFICIENT_BUFFER而上述函数(与失败原因无关)返回默认日期分隔符"/".所以这是Delphi RTL中的一个错误.
如果您的奇数格式字符串具有有效用例,请使用StrToDate接收格式设置参数的重载.如果没有,只需在区域设置中更正日期字符串即可.
遗憾的是,您无法为第一种替代方案应用通用解决方案.也就是说,你可以检索正确的日期分隔符,例如,像这样:
function GetDateSeparator: string;
var
NumChars: Integer;
begin
NumChars := GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, nil, 0);
Win32Check(NumChars <> 0);
SetLength(Result, NumChars);
Win32Check(GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, PChar(Result), NumChars) <> 0);
SetLength(Result, Length(Result) - 1);
end;
Run Code Online (Sandbox Code Playgroud)
但你不能指定返回'. '到DateSeparator的TFormatSettings,因为它需要一个字符.你必须假装你知道分隔符是a '.'并使用它,这只能起作用,因为第二个char是一个被剥离的空间ScanDate.