代码之家  ›  专栏  ›  技术社区  ›  Lubos

StrToDate无法将从DateToStr获得的值转换为

  •  0
  • Lubos  · 技术社区  · 8 年前

    现在我们需要将其重新用作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.
    

    项目1。exe引发了异常类EConvertError,消息为“28”。9.2017“不是有效日期”。 这是不正确的,例外情况中提到的日期是有效的!它是刚刚通过DateToStr生成的。 这对我来说完全没有意义。 这可能是Windows 10中的错误吗?

    1 回复  |  直到 8 年前
        1
  •  5
  •   Sertac Akyuz    8 年前

    dd. M.yyyy 用于操作系统区域设置中的短日期格式。或 dd. M. yyyy

    原因 StrToDate 失败的原因是 ScanDate “sysutils.pas”中的函数失败并返回False。原因 斯堪的纳特

    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;
    

    对于日期格式,所需的缓冲区为3个字符,因为RTL只提供2个字符,API无法使用 ERROR_INSUFFICIENT_BUFFER

    如果您有奇数格式字符串的有效用例,请使用 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;
    

    但您不能分配返回 '. ' DateSeparator TFormatSettings ,因为它需要一个字符。你必须假装知道分隔符是一个 '.' 使用它,因为第二个字符是一个空间,在 斯堪的纳特 .