VarToDateAsString 返回意外结果



Delphi 有这个函数:

function VarToDateAsString(const V: TVarData): TDateTime;
....
LResult := VarDateFromStr(S, VAR_LOCALE_USER_DEFAULT, 0, Result);

对今天的日期执行此操作:

   VarDateFromStr('07;12;18', VAR_LOCALE_USER_DEFAULT, 0, Result);

那么结果将是相等的

Result = '07;18;12'

是否有任何修复可能?

代码示例

procedure TForm1.Button1Click(Sender: TObject);
var
  LDateTimeVar: Variant;
  LDateTime: TDateTime;
begin
  // Current date separator in OS settings is ';'
  LDateTimeVar := '07;12;18';
  LDateTime := VarToDateTime(LDateTimeVar);
  // Expected LDateTime = '07;12;18', 
  // but will be LDateTime = '07;18;12'  
  ShowMessage(DateToStr(LDateTime));
end;

VarToDateAsString调用'oleaut32's VarDateFromStr来执行转换,如果你有年份在中间,转换就会失败。

variants.VarToDateAsString

function VarToDateAsString(const V: TVarData): TDateTime;
var
  ...
begin
  _VarToWStr(S, V);
  LResult := VarDateFromStr(S, VAR_LOCALE_USER_DEFAULT, 0, Result);
  ...

在第二行放置一个断点,您将看到 Result 参数将反转日期和年份。您可以通过调用 activex.VarDateFromStr 自行进行测试。

您可以绕过variants.VarToDateAsString调用VarDateFromStr并实现自己的函数,但不要考虑使用sysutils中的东西,因为它也不支持中间格式的年份。 sysutils.TryStrToDateTime调用ScanDate而又调用GetDateOrder。以下是整个函数:

function GetDateOrder(const DateFormat: string): TDateOrder;
var
  I: Integer;
begin
  Result := doMDY;
  I := 1;
  while I <= Length(DateFormat) do
  begin
    case Chr(Ord(DateFormat[I]) and $DF) of
      'E': Result := doYMD;
      'Y': Result := doYMD;
      'M': Result := doMDY;
      'D': Result := doDMY;
    else
      Inc(I);
      Continue;
    end;
    Exit;
  end;
end;

如您所见,中间没有年份的结果排序。


看起来你必须自己解析字符串:

uses
  varutils;
function MyVarDateFromStr(const strIn: WideString; LCID: DWORD; dwFlags: Longint;
  out dateOut: TDateTime): HRESULT; stdcall;
begin
  // write your parser here and return a valid 'dateOut'
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  LDateTimeVar: Variant;
  LDateTime: TDateTime;
begin
  varutils.VarDateFromStr := MyVarDateFromStr;   // replace the broken function
  // Current date separator in OS settings is ';'
  LDateTimeVar := '07;12;18';
  LDateTime := VarToDateTime(LDateTimeVar);
  // Expected LDateTime = '07;12;18',
  // but will be LDateTime = '07;18;12'
  ShowMessage(DateToStr(LDateTime));
end;

最新更新