Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi C++ DateTime in Delphi TDateTime umwandeln. (https://www.delphipraxis.net/132127-c-datetime-delphi-tdatetime-umwandeln.html)

Andreas L. 6. Apr 2009 18:28


C++ DateTime in Delphi TDateTime umwandeln.
 
Hi,
ich habe folgenden Wert aus einer Datei ausgelesen: 12879544607645573 Dieser Wert soll das Erstellungsdatum eines Eintrags der Datei darstellen. Ich vermute das es sich hier bei um einen DateTime-Wert handelt. Die Software mit der die Datei erstellt wurde, ist in C++ geschrieben. Ein Auszug aus dem MSDN:
Zitat:

Remarks

The DateTime value type represents dates and times with values ranging from 12:00:00 midnight, January 1, 0001 Anno Domini (Common Era) to 11:59:59 P.M., December 31, 9999 A.D. (C.E.)

Time values are measured in 100-nanosecond units called ticks, and a particular date is the number of ticks since 12:00 midnight, January 1, 1 A.D. (C.E.) in the GregorianCalendar calendar. For example, a ticks value of 31241376000000000L represents the date, Friday, January 01, 0100 12:00:00 midnight. A DateTime value is always expressed in the context of an explicit or default calendar.
http://msdn.microsoft.com/en-us/library/system.datetime(VS.71).aspx

TDateTime wird in der Delphi-Hilfe so beschrieben:
Zitat:

Der ganzzahlige Teil eines TDateTime-Wertes von Delphi entspricht der Anzahl der Tage seit dem 30.12.1899. Der fraktionale Teil des TDateTime-Wertes gibt die Tageszeit an.
Wie wandel ich das jetzt in einen TDateTime-Wert um?

Andreas L. 7. Apr 2009 14:18

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Mein bisheriger Ansatz:
  • 12879544607645573 mit 100 multiplizieren um Nanosekunden zu erhalten = 1287954460764557300
  • Nanosekunden in Sekunden umrechnen = 1287954460.7645574 (gerundet = 1287954461)
  • Ausrechnen wie viele Sekunden zwischen dem 01.01.0001 und dem 01.01.1970 vergangen sind = 62135596800
    Delphi-Quellcode:
    var
      d: tDateTime;
    begin
      d := EncodeDateTime(0001, 01, 01, 00, 00, 00, 0000);
      i := DateTimeToUnix(d); //ist hier negativ
    end;

Und wie gehts weiter?

Hmm.. ein Mathe-Genie war ich noch nie. Stecke irgendwie fest...

Chemiker 7. Apr 2009 19:05

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Hallo Andreas L.

12879544607645573 = Datum/Zeit. Welches Datum/Uhrzeit soll dieser Wert repräsentieren?

Hast Du die passenden Werte von Datum/Uhrzeit?

Bis bald Chemiker

Andreas L. 8. Apr 2009 11:16

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Chemiker
12879544607645573 = Datum/Zeit. Welches Datum/Uhrzeit soll dieser Wert repräsentieren?

Hast Du die passenden Werte von Datum/Uhrzeit?

Ja, es soll der Donnerstag, 19. Februar 2009 20:16:47 sein.

Andreas L. 15. Apr 2009 15:18

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
OK, ich hab jetzt weitere Infos. Es scheint sich um das von Webkit verwendet Datumsformat zu handeln:
Zitat:

WEBKIT time which is the number of microseconds since midnight UTC of 1 January 1601
Wie könnte ich das nun am besten umrechnen?

EDIT: Ich hab mir jetzt mal die UnixToDateTime-Routinen angesehen und ein bisschen gebastelt:

Delphi-Quellcode:
const
  WebKitTimeDelta                    = 256036; //Tage zwischen 31.12.1899 und 01.01.1601 (glaube der Wert ist falsch)
...
...

function DateTimeToWebKitTime(const AValue: TDateTime):Int64;
begin
  Result := Round((AValue - WebKitTimeDelta) * MSecsPerDay);
end;

function WebKitTimeToDateTime(const AValue: Int64):TDateTime;
begin
  Result := AValue / MSecsPerDay + WebKitTimeDelta;
end;
Funktioniert leider nicht:
Delphi-Quellcode:
  DateTimePicker3.DateTime := WebKitTimeToDateTime(StrToInt64(Edit2.Text));
Wert von Edit2: 12884278663641352
Debugger zeigt als Ergebnis von WebKitTimeToDateTime: 149379631,64
DateTimePicker3 verändert sich aber nicht

Andreas L. 16. Apr 2009 15:21

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Keiner eine Idee?

Reinhard Kern 16. Apr 2009 15:31

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Andreas L.
Keiner eine Idee?

Hi,

ohne garantiert korrekte Wertepaare, anhand derer man die Umwandlungssoftware prüfen könnte, lohnt sich das Nachdenken nicht wirklich.

Gruss Reinhard

Andreas L. 16. Apr 2009 18:12

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Reinhard Kern
Zitat:

Zitat von Andreas L.
Keiner eine Idee?

Hi,

ohne garantiert korrekte Wertepaare, anhand derer man die Umwandlungssoftware prüfen könnte, lohnt sich das Nachdenken nicht wirklich.

Gruss Reinhard

Ok, der Wert 12884375683494367 repräsentiert den 16. April 2009 19:14:45.

EDIT: Die Werte werden vom Google Chrome Browser in der Cookies-Datei im UserData-Verzeichnis abgespeichert. Ich hab auch schon den Chromium Code geladen, finde aber die entsprechende Stelle im Code nicht. Ist auch ziemlich umfangreich...

Reinhard Kern 16. Apr 2009 23:44

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Andreas L.
Zitat:

Zitat von Reinhard Kern
Zitat:

Zitat von Andreas L.
Keiner eine Idee?

Hi,

ohne garantiert korrekte Wertepaare, anhand derer man die Umwandlungssoftware prüfen könnte, lohnt sich das Nachdenken nicht wirklich.

Gruss Reinhard

Ok, der Wert 12884375683494367 repräsentiert den 16. April 2009 19:14:45.

EDIT: Die Werte werden vom Google Chrome Browser in der Cookies-Datei im UserData-Verzeichnis abgespeichert. Ich hab auch schon den Chromium Code geladen, finde aber die entsprechende Stelle im Code nicht. Ist auch ziemlich umfangreich...

Hi,

braucht man alles nicht:

gewünscht ist
CppTime * mul + add = DelphiTime

1 Tag hat 864000000000 ticks (100ns), also

(CppTime + 864000000000) * mul + add = DelphiTime + 1

-> das sind 2 Gleichungen mit 2 Unbekannten, daraus ergibt sich mul = 1/864000000000 und add = 25007,330053825741741

finally: DT := CT / 864000000000 + 25007,330053825741741

natürlich mit int64 und extended zu rechnen.

Gruss Reinhard

Reinhard Kern 17. Apr 2009 01:05

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Reinhard Kern
finally: DT := CT / 864000000000 + 25007,330053825741741

Hallo,

hat mich nicht befriedigt - ist zwar mathematisch schon das, was du wolltest, aber eigentlich sollte add ganzzahlig sein (Tage). Eine genauere Zahlenanalyse ergab, dass Webtime ab 1601 richtig ist und dass UTC rauskommt - du hast aber in deinen Zahlenpaaren zuerst MEZ und dann MESZ angegeben. Korrekt logisch abgeleitet muss es daher heissen:

DelphiTime := WebTime / 86400000000 {µs} - 109205 {Tage 1601 - 1899} + (MEZ - UTC | MESZ - UTC) {für GER}

Gruss Reinhard

Reinhard Kern 17. Apr 2009 01:16

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Andreas L.
Ein Auszug aus dem MSDN:
Zitat:

Remarks

The DateTime value type represents dates and times with values ranging from 12:00:00 midnight, January 1, 0001 Anno Domini (Common Era) to 11:59:59 P.M., December 31, 9999 A.D. (C.E.)

Time values are measured in 100-nanosecond units called ticks, and a particular date is the number of ticks since 12:00 midnight, January 1, 1 A.D. (C.E.) in the GregorianCalendar calendar. For example, a ticks value of 31241376000000000L represents the date, Friday, January 01, 0100 12:00:00 midnight. A DateTime value is always expressed in the context of an explicit or default calendar.

Hi,

diese Definition ist schon reichlich abstrus, besonders das Beispiel mit dem 1.Jan 100 - da sind nämlich 24 Schalttage eingerechnet, aber ich weiss aus sicherer Quelle, dass es im ersten Jahrhundert keine Schaltjahre gab; von anderen Problemen wie der Umstellung vom julianischen auf den gregorianischen Kalender ganz abgesehen. Da wird mehr Verwirrung gestiftet als was erklärt.

Gruss Reinhard

nicodex 17. Apr 2009 09:29

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Zitat:

Zitat von Andreas L.
Zitat:

Zitat von Chemiker
12879544607645573 = Datum/Zeit. Welches Datum/Uhrzeit soll dieser Wert repräsentieren?

Hast Du die passenden Werte von Datum/Uhrzeit?

Ja, es soll der Donnerstag, 19. Februar 2009 20:16:47 sein.

Nö, 19:16 (20:16 ist die lokale Zeit bei dir).

Zitat:

Zitat von Andreas L.
OK, ich hab jetzt weitere Infos. Es scheint sich um das von Webkit verwendet Datumsformat zu handeln:
Zitat:

WEBKIT time which is the number of microseconds since midnight UTC of 1 January 1601
Wie könnte ich das nun am besten umrechnen?

Windows verwendet ein ähnliches Zeitformat für TFileTime - nur in 100 Nanosekunden anstatt Mikrosekunden:
Delphi-Quellcode:
type
  TWebKitTime = UInt64;

function WebKitTimeToDateTime(const AWebKitTime: TWebKitTime;
  out ADateTime: TDateTime): Boolean;
var
  SystemTime: TSystemTime;
begin
  Result := FileTimeToSystemTime(TFileTime(AWebKitTime * 10), SystemTime);
  if Result then
  try
    ADateTime := SystemTimeToDateTime(SystemTime);
  except
    on E: EConvertError do
      Result := False;
  end;
end;

procedure TestWebKitTimeToDateTime();
var
  DateTime: TDateTime;
begin
  if WebKitTimeToDateTime(StrToInt64('12879544607645573'), DateTime) then
    ShowMessage(DateTimeToStr(DateTime));
end;
Für die Umrechnung in eine lokale Zeit könnte man FileTimeToLocalFileTime verwenden.

Wie auch immer, man sollte beachten, dass TDateTime nicht alle Werte eines TFileTime/TWebKitTime abbilden kann (vor dem 30.12.1899).

Andreas L. 17. Apr 2009 10:20

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Danke für die Antworten. :-D Werde das gleich testen :thumb:

Andreas L. 17. Apr 2009 11:22

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Ok, der Code funktioniert wunderbar. Jetzt muss ich nur noch einen DateTime in einen WebKit-Time Wert umwandeln. Ich hab dazu die Routine umgedreht:
Delphi-Quellcode:
function DateTimeToWebKitTime(const ADateTime: TDateTime;
  out AWebkitTime: TWebKitTime): Boolean;
var
  FileTime: TFileTime;
begin
  FileTime := DateTimeToFileTime(ADateTime);
  if Result then
  try
    AWebkitTime := TWebKitTime(FileTime) div 10;
  except
    on E: EConvertError do
      Result := False;
  end;
end;

function DateTimeToFileTime(Value: TDateTime):TFileTime;
var
  SystemTime: TSystemTime;
begin
  DateTimeToSystemTime(Value, SystemTime);
  SystemTimeToFileTime(systemtime, Result);
end;
Wenn ich jetzt 19.02.2009 19:02 umwandle erhalte ich -1456136888. Wo liegt der Fehler?

nicodex 17. Apr 2009 12:27

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Delphi-Quellcode:
type
  TWebKitTime = UInt64;

function WebKitTimeToDateTime(const AWebKitTime: TWebKitTime;
  out ADateTime: TDateTime): Boolean;
var
  SystemTime: TSystemTime;
begin
  Result := FileTimeToSystemTime(TFileTime(AWebKitTime * 10), SystemTime);
  if Result then
  try
    ADateTime := SystemTimeToDateTime(SystemTime);
  except
    on E: EConvertError do
      Result := False;
  end;
end;

function DateTimeToWebKitTime(const ADateTime: TDateTime): TWebKitTime;
var
  SystemTime: TSystemTime;
begin
  DateTimeToSystemTime(ADateTime, SystemTime);
  SystemTimeToFileTime(SystemTime, TFileTime(Result));
  Result := Result div 10;
end;

procedure TestWebKitTime();
const
  WebKitTimeText = '12879544607645573';
var
  DateTime: TDateTime;
begin
  if WebKitTimeToDateTime(StrToInt64(WebKitTimeText), DateTime) then
    ShowMessage(
      WebKitTimeText + #13#10 +
      FormatDateTime('yyyy-mm-dd hh:nn:ss,zzz', DateTime) + #13#10 +
      IntToStr(DateTimeToWebKitTime(DateTime)));
end;

Andreas L. 17. Apr 2009 12:43

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Ich bekomme als Ergebnis trotzdem -1456136888. Der Code meiner Test-App:
Delphi-Quellcode:
procedure TForm4.Button1Click(Sender: TObject);
var
  datetime: TDateTime;
begin
  WebKitTimetodatetime(StrToInt64(Edit1.Text), datetime);
  DateTimePicker1.DateTime := datetime; //in datettime umwandeln funktioniert
end;

procedure TForm4.Button2Click(Sender: TObject);
var
  datetime: TDateTime;
begin
  datetime := DateTimePicker1.DateTime;
  FormatDateTime('yyyy-mm-dd hh:nn:ss,zzz', DateTime);
  Edit1.Text := IntToStr(DateTimeToWebKitTime(DateTime));
end;
Was mache ich falsch?

nicodex 17. Apr 2009 13:01

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Keine Ahnung, bei mir geht folgendes unter Delphi 2009:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
resourcestring
  StrWebKitTimeConvertError = 'Failed to convert WebKitTime to DateTime.';
var
  DateTime: TDateTime;
begin
  if WebKitTimeToDateTime(StrToInt64(Edit1.Text), DateTime) then
    DateTimePicker1.DateTime := DateTime
  else
    raise EConvertError.Create(StrWebKitTimeConvertError);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  DateTime: TDateTime;
begin
  DateTime := DateTimePicker1.DateTime;
  ShowMessage(FormatDateTime('yyyy-mm-dd hh:nn:ss,zzz', DateTime));
  Edit1.Text := IntToStr(DateTimeToWebKitTime(DateTime));
end;
DateTimePicker1.Format ist 'yyyy-MM-dd HH:mm', dürfte aber keine Rolle spielen.

Andreas L. 17. Apr 2009 13:40

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Tatsächlich. Laut Delphi-Hilfe existiert zwar eine überladene Routine von IntTostr die Int64 konvertiert, diese wird aber anscheinend nicht verwendet. Ich caste jetzt einfach noch nach Int64 und es geht.

Delphi-Quellcode:
  Edit1.Text := IntToStr(Int64(DateTimeToWebKitTime(DateTime)));
Nochmal Danke für deine Hilfe :-D

nicodex 17. Apr 2009 13:42

Re: C++ DateTime in Delphi TDateTime umwandeln.
 
Ansonsten halt manuell:
Delphi-Quellcode:
function WebKitTimeToStr(AWebKitTime: TWebKitTime): string;
const
  MaxWebKitTimeStrLength = Length('18446744073709551615');
  DecimalToCharacter: array [0..9] of Char = '0123456789';
var
  Index: Integer;
begin
  SetLength(Result, MaxWebKitTimeStrLength);
  for Index := MaxWebKitTimeStrLength downto 1 do
  begin
    Result[Index] := DecimalToCharacter[AWebKitTime mod 10];
    AWebKitTime := AWebKitTime div 10;
    if AWebKitTime = 0 then
    begin
      Delete(Result, 1, Index - 1);
      Break;
    end;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:32 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz