Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: VarToDateTime mit englischem Datum

  Alt 15. Jan 2012, 12:57
  1. Also die Werte bekommt man von Microsoft (die haben ja auch Windows gebaut, also wissen die das auch am besten )
  2. Wenn du dir mal Delphi-Referenz durchsuchenTFormatSettings im Quelltext (oder auch Online-Hilfe) anschaust, stellst du fest, da gibt es auch einen Constructor. Mal schauen, was der so zu bieten hat ... oha, da gibt es ja sogar 3 Varianten Delphi-Referenz durchsuchenTFormatSettings.Create und eine besagt, dass auch dieses möglich ist TFormatSettings.Create( 'en-US' );
Aha, geht ja schon mal ganz einfach.

Jetzt mal zu Delphi-Referenz durchsuchenVarToDateTime und Delphi-Referenz durchsuchenStrToDateTime
Die Online-Hilfe lässt einen hier ein wenig im Regen stehen, so dass man hier auf den Quelltext angewiesen ist.

StrToDateTime ist eine Pascal-Funktion, die z.B. erhebliche Schwierigkeiten hat, wenn man als Trennzeichen ein Leerzeichen nimmt.
Diese Funktion wird innerhalb von StrToDateTime aufgerufen und entfernt alle Leerzeichen, bis das Trennzeichen gefunden wird
Delphi-Quellcode:
function ScanChar(const S: string; var Pos: Integer; Ch: Char): Boolean;
begin
  Result := False;
  ScanBlanks(S, Pos);
  if (Pos <= Length(S)) and (S[Pos] = Ch) then
  begin
    Inc(Pos);
    Result := True;
  end;
end;
VarToDateTime ist da etwas anders aufgebaut und ruft - nach einigem Hin- und Hergewurschtel - folgendes auf
Delphi-Quellcode:
  VarDateFromStr: function(const strIn: WideString; LCID: DWORD; dwFlags: Longint;
    out dateOut: TDateTime): HRESULT; stdcall;
Es sieht komisch aus, liegt aber daran, dass hier eine Variable definiert wird, die eine DLL-Funktion aufruft. Die DLL wird per LateBinding eingebunden.

Schlussendlich wird also eine Windows-Funktion für die Konvertierung bemüht.

Interessant ist der Parameter LCID: DWORD . Diese Funktion kann also auch je nach LCID entsprechend reagieren ... warum macht die das also nicht?

Der Grund liegt hier, da irgendwann innerhalb von VarToDateTime einmal diese Funktion aufgerufen wird:
Delphi-Quellcode:
function VarToDateAsString(const V: TVarData): TDateTime;
var
  S: WideString;
  D: Double;
  LResult: HResult;
begin
  _VarToWStr(S, V);
  LResult := VarDateFromStr(S, VAR_LOCALE_USER_DEFAULT, 0, Result);
  case LResult of
    VAR_OK:; // in this case the OS function has put the value into result
    VAR_TYPEMISMATCH:
      if not TryStrToDate(S, Result) then
        if TryStrToFloat(S, D) then
          Result := D
        else
          VarResultCheck(VAR_TYPEMISMATCH, V.VType, varDate);
  else
    VarResultCheck(LResult, V.VType, varDate);
  end;
end;
Es gibt auch - soweit ich das überschauen kann - keine überladene Funktion, wo man die gewünschte LCID übergeben kann.

Die Lösung besteht darin, z.B. direkt die Funktion aufzurufen:
Delphi-Quellcode:
function APIStrToDateTime( const S : WideString; LCID : Cardinal ) : TDateTime;
var
  LResult : HResult;
begin
  if VarDateFromStr( S, LCID, 0, Result ) <> VAR_OK
  then
    raise EConvertError.CreateFmt( '"%s" ist kein gültiges Datum', [S] );
end;

procedure TForm1.Button1Click( Sender : TObject );
begin
  ShowMessage( DateToStr( APIStrToDateTime( '15 Dec 2012', 1033 ) ) );
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat