Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.685 Beiträge
 
Delphi 11 Alexandria
 
#18

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 19:42
Wie man hier sehen kann, funktionieren 3 Methoden. screenshot-05_06.png
Tokyo per Units, D2009 per Code, Samso per Code.
Die GW Methode aus Post #1 bei Rückverwandlung klappt etwas nicht.

Der Fehler mit D2009 Rückverwandlung entstand weil UnixTimeA verwendet wurde und nicht sein zugewiesener UnixTimeB.
Nun A B C D vorhanden

Delphi-Quellcode:
program UT2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.DateUtils;

const
  _DateDelta = 693594;
  _UnixDateDelta = 25569;
  _HoursPerDay = 24;
  _MinsPerHour = 60;
  _SecsPerMin = 60;
  _MSecsPerSec = 1000;
  _MinsPerDay = _HoursPerDay * _MinsPerHour;
  _SecsPerDay = _MinsPerDay * _SecsPerMin;
  _SecsPerHour = _SecsPerMin * _MinsPerHour;
  _MSecsPerDay = _SecsPerDay * _MSecsPerSec;
  _DelphiEpoche = -2209161600; //30.12.1899 als UTS

function _DateTimeToUnix(const AValue: TDateTime): Int64;
begin
  Result := Round((AValue - _UnixDateDelta) * _SecsPerDay);
end;

function _UnixToDateTime(const AValue: Int64): TDateTime;
begin
  Result := AValue / _SecsPerDay + _UnixDateDelta;
end;

function _UnixTimeToDatetime(UnixTime: Int64): TDatetime;
var
  t: Double;
begin
  t := UnixTime / _SecsPerDay + _UnixDateDelta;
  if t > 0
  then
    Result := t
  else
    Result := trunc(t) - frac(t) - 2;
end;

function _DateTimeToUnixTime(Datetime: TDatetime): Int64;
var
  t: TDatetime;
begin
  if Datetime < 0
  then
    t := trunc(Datetime) - frac(Datetime) - _UnixDateDelta
  else
    t := Datetime - _UnixDateDelta;
  if t>0
  then
    Result := trunc(t * _SecsPerDay + 0.5)
  else
    Result := trunc(t * _SecsPerDay - 0.5);
end;

function _DateTimeToUnixtimestamp(const value:TDateTime):Int64;
var
  TimePart : extended;
  Zeit : int64;
  datum: int64;
begin
  zeit := Trunc(Abs(Frac(value)) * _SecsPerDay); //Zeitanteil in Sekunden
  timepart := frac(Abs(Frac(value)) * _MSecsPerDay); //Millisekunden
  datum := trunc(int(value) * _SecsPerDay); //Anzahl der Tage mit Bezug Delphi-Epoche in Sekunden
  result := _DelphiEpoche + (datum+zeit);
  if (timepart > 0.5) then //Korrektur bei 500+ Millisekunden
    inc(result);
end;

function _UnixTimeStampToDateTime(const value:int64):TDateTime;
var
  datum : int64;
  base,rest : int64;
  zeit,timepart : Extended;
begin
  base := _DelphiEpoche - value;
  datum := base DIV _SecsPerDay;
  rest := base MOD _SecsPerDay;
  timepart := _MSecsPerDay/ABS(rest);
  zeit := _SecsPerDay/Abs(rest);
  if (Frac(abs(Timepart))>0.5) then
    zeit := _SecsPerDay/(base - (datum*_SecsPerday))+1;
  result := datum+zeit;
end;

procedure Main;
var
  DateTimeStr: string;
  MyDateTime: TDateTime;
  UnixTimeA, UnixTimeB, UnixTimeC, UnixTimeD : Int64;
begin
  DateTimeStr := '23.08.1733 18:33:44';
  Writeln('Testdatum: ', DateTimeStr);

  MyDateTime := StrToDateTime(DateTimeStr);
  Writeln('Umwandung in TDateTime: ', Double(MyDateTime).ToString);

  UnixTimeA := System.DateUtils.DateTimeToUnix(MyDateTime);
  Writeln('DateTimeToUnix (Tokyo): ', UnixTimeA.ToString);
  UnixTimeB := _DateTimeToUnix(MyDateTime);
  Writeln('DateTimeToUnix (D2009): ', UnixTimeB.ToString);
  UnixTimeC := _DateTimeToUnixTime(MyDateTime);
  Writeln('DateTimeToUnix (Samso): ', UnixTimeC.ToString);
  UnixTimeD := _DateTimeToUnixtimestamp(MyDateTime);
  Writeln('DateTimeToUnix (GWalg): ', UnixTimeD.ToString);

  Writeln('Rückwandlung von UnixTime in TDateTime und in String');

  Writeln('UnixToDateTime (Tokyo): ', FormatDateTime('DD.MM.YYYY HH:MM:SS', System.DateUtils.UnixToDateTime(UnixTimeA)));
  Writeln('UnixToDateTime (D2009): ', FormatDateTime('DD.MM.YYYY HH:MM:SS', _UnixToDateTime(UnixTimeB)));
  Writeln('UnixToDateTime (Samso): ', FormatDateTime('DD.MM.YYYY HH:MM:SS', _UnixTimeToDateTime(UnixTimeC)));
  Writeln('UnixToDateTime (GWalg): ', FormatDateTime('DD.MM.YYYY HH:MM:SS', _UnixTimeStampToDateTime(UnixTimeD)));

end;

begin
  try
    Main;
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
edit
Fazit: Für volle Unit Unabhängigkeit und sehr hohe Kompatibilität Benutze Samsos Umsetzung.
D2009 nur von und mit D2009 Code, dann klappt der auch ganz gut.
Gruß vom KodeZwerg

Geändert von KodeZwerg ( 5. Jun 2018 um 20:24 Uhr)
  Mit Zitat antworten Zitat