AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi Konvertierung UnixTimeStamp nacht TDateTime und zurück
Thema durchsuchen
Ansicht
Themen-Optionen

Konvertierung UnixTimeStamp nacht TDateTime und zurück

Ein Thema von Ghostwalker · begonnen am 5. Jun 2018 · letzter Beitrag vom 7. Jun 2018
Antwort Antwort
Seite 1 von 3  1 23      
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#1

Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 04:58
Moinmoin,

im Rahmen eines Projektes brauch ich die Umrechnung von TDatetime-Werten nach UnixTimeStamp und zurück. Das ganze aber manuell ohne Dateutils. Da die Funktionen aus der Codelib Hier, nicht so wirklich funktionieren (erstens wird von der Deutschen Zeitzone ausgegangen, 2 wird der Zeitteil nicht wirklich korrekt berechnet), hab ich mich dazu entschlossen, das ganze selbst um zusetzen.

Die Umrechnung eines TDatetime-Wertes zu einem Unixtimestamp funktioniert auch schon:
Delphi-Quellcode:
const
  cSecPerDay = 86400;
  cMSecPerDay = 86400000;
  cDelphiEpoche = -2209161600; //30.12.1899 als UTS

function DateTimeToUnixtimestamp(const value:TDateTime):Int64;
var
  TimePart : extended;
  Zeit : int64;
  datum: int64;

begin
  zeit := Trunc(Abs(Frac(value))*cSecPerDay); //Zeitanteil in Sekunden
  timepart := frac(Abs(Frac(value))*cMSecPerDay); //Millisekunden
  datum := trunc(int(value)*cSecPerDay); //Anzahl der Tage mit Bezug Delphi-Epoche in Sekunden
  result := cDelphiEpoche+(datum+zeit);
  if (timepart > 0.5) then //Korrektur bei 500+ Millisekunden
    inc(result);
end;
Leider will die Umkehrfunktion (also von Unixtimestamp nach TDatetime) nicht so wirklich funktionieren.

Delphi-Quellcode:
function UnixTimeStampToDateTime(const value:int64):TDateTime;
var
  datum : int64;
  base,rest : int64;
  zeit,timepart : Extended;

  base := cDelphiEpoche - value;
  datum := base DIV cSecPerDay;
  rest := base MOD cSecPerDay;
  timepart := cMSecPerDay/ABS(rest);
  zeit := cSecPerDay/Abs(rest);
  if (Frac(abs(Timepart))>0.5) then
    zeit := cSecPerDay/(base - (datum*cSecPerday))+1;
  result := datum+zeit;
end;
Ein Unterschied von 1 sek (+/-) wär ok, da ein Unixtimestamp keine Millisekunden berücksichtigt. Leider bekomme ich aber Unterschieder von teilweise mehreren Tagen.

Kann mir da jemand auf die Sprünge helfen ?


Anmerkung: Das ganze sollte sowohl mit positiven als auch negativen Werten klarkommen.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#2

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 07:53
Die Zeitzone würde ich gesondert behandeln. D.h. ich würde den Datetimewert vor der Konvertierung in UTC umrechnen und dann in die Unixtimestamp umrechnen. Im umgekehrten Fall würde ich den berechneten Datetimewert wieder in lokale Zeit umrechnen, falls das erforderlich sein sollte. Hier mein Vorschlag für die Umrechnung von UTC-Datetimewerte in die Unixtimestamp und zurück (nur grob mit einigen Testdaten von https://www.freeformatter.com/epoch-...converter.html getestet):

Delphi-Quellcode:
uses
  System.SysUtils;
(*
{ Days between TDateTime basis (12/31/1899) and Unix time_t basis (1/1/1970) }

  UnixDateDelta = 25569;
*)


function UnixTimeToDatetime(UnixTime: Int64): TDatetime;
begin
  Result := UnixTime/SecsPerDay + UnixDateDelta;
end;

function DatetimeToUnixTime(Datetime: TDatetime): Int64;
var
  t: TDatetime;
begin
  t := Datetime - UnixDateDelta;
  if t>=0
  then
    Result := trunc(t*SecsPerDay + 0.5)
  else
    Result := trunc(t*SecsPerDay - 0.5);
end;
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 08:29
Warum nicht die Funktionen aus DateUtils.pas verwenden?

Delphi-Quellcode:
uses nichts;

const
  UnixDateDelta = 25569;
  SecsPerDay = 86400;


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;
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 08:47
@samso

Nah drann.

Bei den (Test)-Daten hauts nicht hin:

So, 23.08.1733 18:33:44
-60759,7734259259
-7458672376

Bei DateTimeToUnix fehlen 2 Sekunden. Bei UnixToDateTime mehr als ein Tag.

@KodeZwerk
Das ganze soll möglichst unabhängig von anderen (auch Delphi-Eigenen) Units laufen.

btw leided deine Variante unter dem gleichen Problem wie Samso's
Uwe
e=mc² or energy = milk * coffee²

Geändert von Ghostwalker ( 5. Jun 2018 um 08:52 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 08:48
Wieviel mehr kann man denn unabhängig sein? Nja egal, bin raus.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 09:15
@KodeZwerg
Da ich die Starter verwende hab ich keine .pas zu den Delphiegenen Units

Lustig ist nur, das die von dir gepostet variante bei oben genannten Datum das gleiche fehlerhafte
Ergebnis liefert.

Die orginal Funktion dagegen haut hin.

So wie es aussieht hackt es bei Daten vor dem 30.12.1899 00:00:00 (also der "Delphi-Epoche")
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 09:20
Wenn man sich die SysUtils.pas anschaut, vielleicht ist das von Bedeutung für Dein Problem.
Delphi-Quellcode:
{ Days between 1/1/0001 and 12/31/1899 }

  DateDelta = 693594;

{ Days between TDateTime basis (12/31/1899) and Unix time_t basis (1/1/1970) }

  UnixDateDelta = 25569;
Gruß vom KodeZwerg

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

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 09:22
Da ich die Starter verwende hab ich keine .pas zu den Delphiegenen Units
Was ich oben schrieb war/ist Original Code von DateUtils.pas aus Delphi 2009.
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat
samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#9

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 09:27
Ja, das 1899-Problem habe ich nun auch erkannt. Das sollte schon mal besser sein:
Delphi-Quellcode:
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;
Für DateTimeToUnix habe ich noch keine kompakte Lösung.
  Mit Zitat antworten Zitat
Ghostwalker

Registriert seit: 16. Jun 2003
Ort: Schönwald
1.299 Beiträge
 
Delphi 10.3 Rio
 
#10

AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück

  Alt 5. Jun 2018, 09:57
Naja...DateTimeToUnix tut ja so:

Delphi-Quellcode:
var
  Zeit : int64;
  datum: int64;

begin
  zeit := Trunc((Abs(Frac(value))*cSecPerDay)+0.5); //Zeitanteil in Sekunden
  datum := trunc(int(value)*cSecPerDay); //Anzahl der Tage mit Bezug Delphi-Epoche in Sekunden
  result.fvalue := cDelphiEpocheUT+(datum+zeit);
end;
auch bei Daten vor 31.12.1899.

Nur die UnixTimeStamp nach TDateTime leidet hier unter dem 1899'er problem.

Ich probier grad, ob ich mit der Info von KodeZwerk hinsichtlich DateDelta was rauskrieg.
Uwe
e=mc² or energy = milk * coffee²
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:26 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