![]() |
Konvertierung UnixTimeStamp nacht TDateTime und zurück
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 ![]() Die Umrechnung eines TDatetime-Wertes zu einem Unixtimestamp funktioniert auch schon:
Delphi-Quellcode:
Leider will die Umkehrfunktion (also von Unixtimestamp nach TDatetime) nicht so wirklich funktionieren.
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;
Delphi-Quellcode:
Ein Unterschied von 1 sek (+/-) wär ok, da ein Unixtimestamp keine Millisekunden berücksichtigt. Leider bekomme ich aber Unterschieder von teilweise mehreren Tagen.
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; Kann mir da jemand auf die Sprünge helfen ? Anmerkung: Das ganze sollte sowohl mit positiven als auch negativen Werten klarkommen. |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
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
![]()
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; |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
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; |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
@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 |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
Zitat:
|
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
@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") |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
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; |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
Zitat:
|
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
Ja, das 1899-Problem habe ich nun auch erkannt. Das sollte schon mal besser sein:
Delphi-Quellcode:
Für DateTimeToUnix habe ich noch keine kompakte Lösung.
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; |
AW: Konvertierung UnixTimeStamp nacht TDateTime und zurück
Naja...DateTimeToUnix tut ja so:
Delphi-Quellcode:
auch bei Daten vor 31.12.1899.
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; 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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz