Discussion:
EncodeTime - Problem
(zu alt für eine Antwort)
Stefan Koschke
2007-02-19 07:57:38 UTC
Permalink
Hallo zusammen,

ich habe ein "Verständnisproblem" bei der Zeitberechnung;

Ich möchte auf einen gegebenen Zeitpunkt 123 Minuten aufaddieren
Dabei könnte ich
result := result + (123 / 1440) rechnen.
Nun aber meine Frage : es gibt ja systembedingt bei Double-Werten geringste
Abweichungen, so daß ich "befürchte" daß der daraus resultierende Zeitpunkt
(123 / 1440) eben vielleicht ein paar ms darüber oder darunter liegt oder
ist diese Befürchtung unbegründet?
Ich würde lieber
DecodeDate(result,h,n,s,ms) und danach
EncodeDate(h,n+123,s,ms) machen, was aber zu Laufzeitfehler führt.
Visual Basic ist da toleranter, da ist so etwas erlaubt und das Ergebnis ist
korrekt!

Wie verfahrt Ihr bei solchen Anforderungen?

Danke
Ciao
Stefan
Alfred Gemsa
2007-02-19 08:45:41 UTC
Permalink
Post by Stefan Koschke
Hallo zusammen,
ich habe ein "Verständnisproblem" bei der Zeitberechnung;
Ich möchte auf einen gegebenen Zeitpunkt 123 Minuten aufaddieren
Dabei könnte ich
result := result + (123 / 1440) rechnen.
Nun aber meine Frage : es gibt ja systembedingt bei Double-Werten geringste
Abweichungen, so daß ich "befürchte" daß der daraus resultierende Zeitpunkt
(123 / 1440) eben vielleicht ein paar ms darüber oder darunter liegt oder
ist diese Befürchtung unbegründet?
Ich würde lieber
DecodeDate(result,h,n,s,ms) und danach
EncodeDate(h,n+123,s,ms) machen, was aber zu Laufzeitfehler führt.
Visual Basic ist da toleranter, da ist so etwas erlaubt und das Ergebnis ist
korrekt!
Wie verfahrt Ihr bei solchen Anforderungen?
Die Unit DateUtils ist riesig, da gibt's auch

IncMinutes(const AValue: TDateTime; const ANumberOfMinutes: Int64 = 1)

EncodeDate kannst Du schon nehmen, nur Minuten um 123 zu inkremnetieren
geht halt nicht:

EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen.

Alfred
Alfred Gemsa
2007-02-19 08:47:50 UTC
Permalink
Post by Alfred Gemsa
IncMinutes(const AValue: TDateTime; const ANumberOfMinutes: Int64 = 1)
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen.
Sorry, zwei Fehler:

IncMinute() ohne s und EncodeTime statt EncodeDate
Stefan Koschke
2007-02-19 09:08:57 UTC
Permalink
Hallo Alfred,
Post by Alfred Gemsa
Post by Alfred Gemsa
IncMinutes(const AValue: TDateTime; const ANumberOfMinutes: Int64 = 1)
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen.
IncMinute() ohne s und EncodeTime statt EncodeDate
von welcher Delphi-Version sprichst Du?
Ich habe in meinem D5 Enterprise weder eine Unit Dateutils noch einen
Hinweis in der OH auf IncMinute :-(

In der Unit Sysutils gibt es lediglich eine Funktion IncMonth()...
Dein Tip
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen, vielen
Dank für den Tip, da hätte ich auch selbst drauf kommen können ;-)

Ciao
Stefan
Alfred Gemsa
2007-02-19 09:19:32 UTC
Permalink
Post by Stefan Koschke
von welcher Delphi-Version sprichst Du?
Ich habe in meinem D5 Enterprise weder eine Unit Dateutils noch einen
Hinweis in der OH auf IncMinute :-(
Ab D6 erst :-(
Stefan Koschke
2007-02-19 09:21:10 UTC
Permalink
Hallo Alfred,
Post by Alfred Gemsa
Post by Stefan Koschke
von welcher Delphi-Version sprichst Du?
Ich habe in meinem D5 Enterprise weder eine Unit Dateutils noch einen
Hinweis in der OH auf IncMinute :-(
Ab D6 erst :-(
hatte ich fast vermutet ;-) aber Dein Ansatz ist schon in Ordnung, es
handlisch auf Stunden / Minuten aufzuteilen, ggf, sogar auf Tage
erweitert...

Ciao
Stefan
Kurt-Heinrich Ermel
2007-02-19 09:59:44 UTC
Permalink
Hi,
Post by Stefan Koschke
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen,
führt bei Überschreiten eines Tages bzw. einer Stunde aber auch zu
einer Exception.

Falls die Tagesgrenze keine Rolle spielt:

h_neu := (h + (123 div 60) + (n + (123 mod 60)) div 60) mod 24;
n_neu := (n + (123 Mod 60)) mod 60;

hth,
Kurt
Stefan Koschke
2007-02-19 10:17:30 UTC
Permalink
Hallo Kurt,
Post by Kurt-Heinrich Ermel
Hi,
Post by Stefan Koschke
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen,
führt bei Überschreiten eines Tages bzw. einer Stunde aber auch zu
einer Exception.
h_neu := (h + (123 div 60) + (n + (123 mod 60)) div 60) mod 24;
n_neu := (n + (123 Mod 60)) mod 60;
stimmt!
Aber meine eigentliche Frage hat bisher niemand beantwortet (oder
beantworten können) :
Muß man mit "Ungenauigkeiten" rechnen, wenn man auf ein TDateTime einen
Double addiert, so z.B.

result := result + (123/1440) //123 Minuten dazu oder
result := result + (1435/86400) //1435 Sekunden dazu ?

Ciao
Stefan
Andreas Koch
2007-02-19 10:52:25 UTC
Permalink
Post by Stefan Koschke
Aber meine eigentliche Frage hat bisher niemand beantwortet (oder
Muß man mit "Ungenauigkeiten" rechnen, wenn man auf ein TDateTime einen
Double addiert, so z.B.
In der Praxis kannst du davon ausgehen daß Flieskommazahlen immer
ungenau sind. Und da TDateTime und Double beide welche sind ...
Stefan Koschke
2007-02-19 12:16:37 UTC
Permalink
Hallo Andreas,
Post by Andreas Koch
Post by Stefan Koschke
Aber meine eigentliche Frage hat bisher niemand beantwortet (oder
Muß man mit "Ungenauigkeiten" rechnen, wenn man auf ein TDateTime einen
Double addiert, so z.B.
In der Praxis kannst du davon ausgehen daß Flieskommazahlen immer
ungenau sind. Und da TDateTime und Double beide welche sind ...
leider :-(
Nun habe ich mal probiert, viele Sekunden selbst mit den dafür vorgesehenen
Funktionen zu addieren und bekomme, wenn ich das mal extrem über 100 Tage
mache

procedure TForm1.Button1Click(Sender: TObject);
var
zp : Tdatetime;
i : integer;
begin
zp := encodedate(2007,2,19);
for i := 1 to 100*86400 do
zp := zp + encodetime(0,0,1,0);
label1.caption := datetimetostr(zp);
end;

eine Abweichung von 2 sec :-((((
Muß ich denn wirklich mein gesamtes Programm vom Typ TDatetime auf integer
umstellen (Zeitstempel generell als Sekunden seit Zeitpunkt x) oder gibt es
doch einen Weg um diese "Ungenauigkeiten zu eliminieren?

Ciao
Stefan
Kroni
2007-02-19 12:27:36 UTC
Permalink
Post by Stefan Koschke
Post by Andreas Koch
ungenau sind. Und da TDateTime und Double beide welche sind ...
leider :-(
Das kommt darauf an was du eigentlich programmierst.

Was ist eigentlich dein Ziel?

K.R.
Stefan Koschke
2007-02-19 16:09:22 UTC
Permalink
Hallo Kroni,
Post by Kroni
Post by Stefan Koschke
Post by Andreas Koch
ungenau sind. Und da TDateTime und Double beide welche sind ...
leider :-(
Das kommt darauf an was du eigentlich programmierst.
Was ist eigentlich dein Ziel?
ich habe aus Gerätedaten Zeitstempel, die auf ein festes Raster (1min bis
24h) je nach Anwendung "gerundet" werden müssen.
Das heißt es gibt ein festes Raster (1 min, 15 min, 1h... bis 24h) und
dahinein müssen Auslesedaten.
Sind diese nicht am Periodenende entstanden sondern mittendrin, ist der
Registerzeitstempel eben dazwischen und durch "runden" auf die komplette
Periode muß die Arrayposition ermittelt werden, auf die der Wert zu
schreiben ist.
Deshalb addiere ich eine bestimmte Zahl Sekunden oder Minuten auf einen
vorhandenen TDatetime.
Bisher hatte ich mir über die Auswirkungen oder ggf. entstehende Fehler
keine Gedanken gemacht, aber jetzt hat's eben mal Probleme gegeben und ich
bin dabei, das Ganze "wasserdicht" zu machen...

Ciao
Stefan
Jens-Erich Lange
2007-02-19 16:46:06 UTC
Permalink
Post by Stefan Koschke
eine Abweichung von 2 sec :-((((
Muß ich denn wirklich mein gesamtes Programm vom Typ TDatetime auf integer
umstellen (Zeitstempel generell als Sekunden seit Zeitpunkt x) oder gibt es
doch einen Weg um diese "Ungenauigkeiten zu eliminieren?
Ich verwende seit jeher diese Methode. Auf jedem OS, mit jeder
Sprache und ich finde es gibt nichts Besseres. Das jeweilige
Wandeln in den ab und zu benötigten TDateTime ist dann ein Klacks.

Ok, Du musst die Grenzen kennen. D.h. bei den heute noch üblichen
32 Bit Integern deckt Du eben nur einen Zeitraum von einigen Jahr-
zehnten ab. Wer seine Routinen zu gegebener Zeit auf 64 Bit auf-
bohrt, hat dann erst mal wieder etwas Ruhe :-)

Darf ich Dir gleich mal meine Delphi 5 Unit "SysTime.pas" zeigen?
Diese enthält auch die Berechnungsmöglichkeit für alle beweglichen
Feiertage.

Gruß, Jens

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

unit SysTime;

interface

type
str31 = string[31];
IsoFormat = (IsoShort, IsoLong);

const
SecsPerDay = 86400;

Wochentage: array[0..6] of str31 = ('Sonntag', 'Montag', 'Dienstag',
'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag');
Monate: array[1..12] of str31 = ('Januar', 'Februar', 'März', 'April', 'Mai',
'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember');

WeekDays: array[0..6] of str31 = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri',
'Sat');
Months: array[1..12] of str31 = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');

type
DTRec = record
Year: word;
Month: word;
Day: word;
Hour: word;
Minute: word;
Second: word;
WeekDay: word;
end;


procedure GetDateTime(var DTR: DTRec);
procedure NormalizeDate(var DTR: DTRec);
procedure Date2Secs(Date: DTRec; var Secs: longint);
procedure Secs2Date(Secs: longint; var Date: DTRec);

procedure PackDate(Date: DTRec; var Time: integer);
procedure PackSecs(Secs: longint; var Time: integer);
procedure UnpackDate(Time: integer; var Date: DTRec);
procedure UnpackSecs(Time: integer; var Secs: longint);

function ShortYear(Year: integer): byte;
function LongYear(Year: integer): integer;
function DayOfYear(Date: DTRec): integer;
function QuarterOfYear(Date: DTRec): integer;
function WeekOfYear(Date: DTRec; WeekDay: byte): integer;
function DTS(Date: DTRec; D, T: byte; Gap: string): string;
{ Format D Format T }
{ ------------------------------------------------------}
{ 1: 1980-01-01 01:02:03 }
{ 2: 1980-01 01:02 }
{ 3: 1980 01 }
{ 4: 198001 0102 }
{ 5: 19800101 010203 }
{ 6: 01-01 01:02:03 am }
{ 7: 0101 01:02 am }
{ 8: 01.01.1980 01.02.03 }
{ 9: 01.01.80 01.02 }
{10: 1. Januar 1980 1 Uhr 02 }
{11: Dienstag, 1. Januar 1980 1 Uhr 02 und 03 Sekunden }
{ }
{ Wenn D=0 und T=0 kann Gap folgende Formate enthalten }
{ ------------------------------------------------------}
{ %YYYY Jahreszahl vierstellig }
{ %YY Jahreszahl zweistellig }
{ %MMM Monatsname 3-stellig (englische Bezeichnung ) }
{ %MM Monate zweistellig }
{ %M Monate ein- oder zweistellig }
{ %DD Tage zweistellig }
{ %D Tage ein- oder zweistellig }
{ %Q Quartal }
{ %WW Kalenderwoche zweistellig }
{ %W Kalenderwoche ein- oder zweistellig }
{ %CCC Tag des Jahres dreistellig }
{ %C Tag des Jahres ein- bis dreistellig }
{ %NNN Wochentag 3-stellig (englische Bezeichnung ) }
{ }
{ %hh Stunden zweistellig }
{ %h Stunden ein- oder zweistellig }
{ %HH Stunden (12 h-Format) zweistellig }
{ %H Stunden (12 h-Format) ein- oder zweistellig }
{ %mm Minuten zweistellig }
{ %m Minuten ein- oder zweistellig }
{ %ss Sekunden zweistellig }
{ %s Sekunden ein- oder zweistellig }

function CurrDTS(D, T: byte; Gap: string): string;
function GetSecs: longint;
function GetSecsUTC: longint;

function Utc2Local(Secs: longint): longint;
function Local2Utc(Secs: longint): longint;

function GetHoliday(Year, Holiday: integer): longint;

function Secs2Time(Secs: longint): TDateTime;
function Time2Secs(Time: TDateTime): longint;

function Date2Iso(Date: DTRec; Format: IsoFormat): string;
function Secs2Iso(Secs: longint; Format: IsoFormat): string;
function Iso2Date(S: string): DTRec;
function Iso2Secs(S: string): longint;

implementation

uses
Windows, SysUtils;

const
DaysPerYear = 365.24267;
DaysPerMonth = 30.60001;

var
DlstYear: integer;
DlstStart: longint;
DlstEnd: longint;



function Zin(Value: string): longint;
var i: integer;
begin
if (Value = '') then Value := '0';
val(Value, Result, i);
end;


function Zout(Zahl: longint; VK: byte): ShortString;
var temp: ShortString;
begin
str(zahl: VK, temp);
Result := temp;
end;



function ZoutZero(Zahl: longint; VK: byte): ShortString;
var
i: byte;
temp: ShortString;
begin
str(zahl: VK, temp);
for i := 1 to length(temp) do if temp[i] = ' ' then temp[i] := '0';
Result := temp;
end;




{------------------------------------------------------------}



procedure GetDateTime(var DTR: DTRec);
var
DT: TDateTime;
MSec: word;
begin
DT := Now;
with DTR do
begin
DecodeDate(DT, Year, Month, Day);
DecodeTime(DT, Hour, Minute, Second, MSec);
WeekDay := DayOfWeek(DT) - 1;
end;
end;



procedure NormalizeDate(var DTR: DTRec);
var Secs: longint;
begin
Date2Secs(DTR, Secs);
Secs2Date(Secs, DTR);
end;



procedure Date2Secs(Date: DTRec; var Secs: longint);
var Tage: longint;
begin
with Date do
begin
Year := (LongYear(Year) mod 1900) + 1900;
if (Month < 3) then
begin
inc(Month, 12);
dec(Year);
end;
Tage := (Year div 4) - (Year div 100) + (Year div 400);
Tage := Tage + trunc(DaysPerMonth * (Month + 1)) + Day;
Secs := (longint(Year) * 365) + Tage - 723243;
Secs := (Secs * SecsPerDay) + (longint(Hour) * 3600) + (Minute * 60) +
Second;
end;
end;



procedure Secs2Date(Secs: longint; var Date: DTRec);
var
Tage: longint;
Zeit: longint;
begin
with Date do
begin
Zeit := (Secs mod SecsPerDay);
Secs := (Secs div SecsPerDay) + 723121;

WeekDay := (Secs + 2) mod 7;
Year := trunc(Secs / DaysPerYear);
Tage := (Year div 4) - (Year div 100) + (Year div 400);

Secs := (Secs - ((longint(Year) * 365) + Tage - 122));
Month := pred(trunc(Secs / DaysPerMonth));
Day := Secs - trunc(DaysPerMonth * succ(Month));
if (Month > 12) then
begin
dec(Month, 12);
inc(Year);
end;
if (Day = 29) and (Month = 2) and ((Year mod 4) > 0) then
begin
Day := 1;
Month := 3;
end;
Hour := Zeit div 3600;
Minute := (Zeit - (longint(Hour) * 3600)) div 60;
Second := Zeit - (longint(Hour) * 3600) - (Minute * 60);
end;
end;



procedure PackDate(Date: DTRec; var Time: integer);
var DT: TDateTime;
begin
NormalizeDate(Date);
DT := EncodeDate(Date.Year, Date.Month, Date.Day);
DT := DT + EncodeTime(Date.Hour, Date.Minute, Date.Second, 0);
Time := DateTimeToFileDate(DT);
end;



procedure PackSecs(Secs: longint; var Time: integer);
var Date: DTRec;
begin
Secs2Date(Secs, Date);
PackDate(Date, Time);
end;



procedure UnpackDate(Time: integer; var Date: DTRec);
var
DT: TDateTime;
MSec: word;
begin
DT := FileDateToDateTime(Time);
with Date do
begin
DecodeDate(DT, Year, Month, Day);
DecodeTime(DT, Hour, Minute, Second, MSec);
end;
NormalizeDate(Date);
end;



procedure UnpackSecs(Time: integer; var Secs: longint);
var Date: DTRec;
begin
UnpackDate(Time, Date);
Date2Secs(Date, Secs);
end;



function ShortYear(Year: integer): byte;
begin
Result := Year mod 100;
end;



function LongYear(Year: integer): integer;
begin
Year := ShortYear(Year);
if (Year < 80)
then inc(Year, 2000)
else inc(Year, 1900);
Result := Year;
end;



function DayOfYear(Date: DTRec): integer;
var S1, S2: longint;
begin
Date.Hour := 0;
Date.Minute := 0;
Date.Second := 0;
Date2Secs(Date, S1);
Date.Day := 1;
Date.Month := 1;
Date2Secs(Date, S2);
Result := ((S1 - S2) div SecsPerDay) + 1;
end;


function QuarterOfYear(Date: DTRec): integer;
begin
Result := ((Date.Month - 1) div 3) + 1;
end;


function FirstWeek(Year, WeekDay: word): longint;
var Date: DTRec;
begin
fillchar(Date, SizeOf(Date), #0);
Date.Day := 0;
Date.Month := 1;
Date.Year := Year;
Date2Secs(Date, Result);
repeat
Result := Result + SecsPerDay;
Secs2Date(Result, Date);
until (Date.WeekDay = WeekDay);
if (Date.Day > 4) then dec(Result, 7 * SecsPerDay);
end;


function WeekOfYear(Date: DTRec; WeekDay: byte): integer;
var S1, S2: longint;
begin
Date.Hour := 0;
Date.Minute := 0;
Date.Second := 0;
Date2Secs(Date, S1);
S2 := FirstWeek(Date.Year, WeekDay);
if (S1 < S2)
then Result := 0
else Result := ((abs(S1 - S2) div SecsPerDay) div 7) + 1;
end;



function DTS(Date: DTRec; D, T: byte; Gap: string): string;
var S1, S2: string;

function Replace(Mark: string; Code: string): integer;
begin
Result := pos(Mark, Gap);
if (Result > 0) then
begin
delete(Gap, Result, length(Mark));
insert(Code, Gap, Result);
end
end;

procedure LoopReplace(Mark: string; Code: string);
var i: integer;
begin
repeat
i := Replace(Mark, Code);
until (i = 0);
end;

procedure GapFormat;
begin
LoopReplace('%YYYY', ZoutZero(LongYear(Date.Year), 4));
LoopReplace('%YY', ZoutZero(ShortYear(Date.Year), 2));
LoopReplace('%MMM', Months[Date.Month]);
LoopReplace('%MM', ZoutZero(Date.Month, 2));
LoopReplace('%M', ZoutZero(Date.Month, 1));
LoopReplace('%DD', ZoutZero(Date.Day, 2));
LoopReplace('%D', ZoutZero(Date.Day, 1));
LoopReplace('%Q', ZoutZero(QuarterOfYear(Date), 1));
LoopReplace('%WW', ZoutZero(WeekOfYear(Date, 1), 2));
LoopReplace('%W', ZoutZero(WeekOfYear(Date, 1), 1));
LoopReplace('%CCC', ZoutZero(DayOfYear(Date), 3));
LoopReplace('%C', ZoutZero(DayOfYear(Date), 1));
LoopReplace('%NNN', WeekDays[Date.WeekDay]);
LoopReplace('%hh', ZoutZero(Date.Hour, 2));
LoopReplace('%h', ZoutZero(Date.Hour, 1));
LoopReplace('%HH', ZoutZero(Date.Hour mod 12, 2));
LoopReplace('%H', ZoutZero(Date.Hour mod 12, 1));
LoopReplace('%mm', ZoutZero(Date.Minute, 2));
LoopReplace('%m', ZoutZero(Date.Minute, 1));
LoopReplace('%ss', ZoutZero(Date.Second, 2));
LoopReplace('%s', ZoutZero(Date.Second, 1));
end;

begin
NormalizeDate(Date);
with Date do
begin
case D of
1: S1 := ZoutZero(LongYear(Year), 4) + '-' + ZoutZero(Month, 2) + '-' +
ZoutZero(Day, 2);
2: S1 := ZoutZero(LongYear(Year), 4) + '-' + ZoutZero(Month, 2);
3: S1 := ZoutZero(LongYear(Year), 4);
4: S1 := ZoutZero(LongYear(Year), 4) + ZoutZero(Month, 2);
5: S1 := ZoutZero(LongYear(Year), 4) + ZoutZero(Month, 2) + ZoutZero(Day,
2);
6: S1 := ZoutZero(Month, 2) + '-' + ZoutZero(Day, 2);
7: S1 := ZoutZero(Month, 2) + ZoutZero(Day, 2);
8: S1 := ZoutZero(Day, 2) + '.' + ZoutZero(Month, 2) + '.' +
ZoutZero(LongYear(Year), 4);
9: S1 := ZoutZero(Day, 2) + '.' + ZoutZero(Month, 2) + '.' +
ZoutZero(ShortYear(Year), 2);
10: S1 := Zout(Day, 1) + '. ' + Monate[Month] + ' ' +
ZoutZero(LongYear(Year), 4);
11: S1 := Wochentage[WeekDay] + ', ' + Zout(Day, 1) + '. ' + Monate[Month]
+ ' ' + ZoutZero(LongYear(Year), 4);
end;

case T of
1: S2 := ZoutZero(Hour, 2) + ':' + ZoutZero(Minute, 2) + ':' +
ZoutZero(Second, 2);
2: S2 := ZoutZero(Hour, 2) + ':' + ZoutZero(Minute, 2);
3: S2 := ZoutZero(Hour, 2);
4: S2 := ZoutZero(Hour, 2) + ZoutZero(Minute, 2);
5: S2 := ZoutZero(Hour, 2) + ZoutZero(Minute, 2) + ZoutZero(Second, 2);
6:
begin
S2 := ZoutZero(Hour mod 12, 2) + ':' + ZoutZero(Minute, 2) + ':' +
ZoutZero(Second, 2);
if (Hour < 12) then S2 := S2 + ' am' else S2 := S2 + ' pm';
end;
7:
begin
S2 := ZoutZero(Hour mod 12, 2) + ':' + ZoutZero(Minute, 2);
if (Hour < 12) then S2 := S2 + ' am' else S2 := S2 + ' pm';
end;
8: S2 := ZoutZero(Hour, 2) + '.' + ZoutZero(Minute, 2) + '.' +
ZoutZero(Second, 2);
9: S2 := ZoutZero(Hour, 2) + '.' + ZoutZero(Minute, 2);
10: S2 := Zout(Hour, 1) + ' Uhr ' + ZoutZero(Minute, 2);
11: S2 := Zout(Hour, 1) + ' Uhr ' + ZoutZero(Minute, 2) + ' und ' +
ZoutZero(Second, 2) + ' Sekunden';
end;
end;
if (D = 0) and (T = 0) then
begin
GapFormat;
Result := Gap;
end
else if (D <> 0) and (T = 0) then Result := S1
else if (D = 0) and (T <> 0) then Result := S2
else Result := S1 + Gap + S2;
end;



function CurrDTS(D, T: byte; Gap: string): string;
var DTR: DTRec;
begin
GetDateTime(DTR);
Result := DTS(DTR, D, T, Gap);
end;

{
function GetSecs: longint;
var
DTR: DTRec;
Secs: longint;
begin
GetDateTime(DTR);
Date2Secs(DTR, Secs);
Result := Secs;
end;
}


function GetSecs: longint;
begin
Result := Trunc((Now - 29221) * SecsPerDay);
end;


function GetSecsUTC: longint;
var
Date: TDateTime;
Time: TSystemTime;
begin
GetSystemTime(Time);
Date := SystemTimeToDateTime(Time);
Result := Trunc((Date - 29221) * SecsPerDay);
end;


function NextSunday(Day, Month, Year: integer): longint;
var Date: DTRec;
begin
fillchar(Date, SizeOf(Date), #0);
Date.Day := Day;
Date.Month := Month;
Date.Year := Year;
Date2Secs(Date, Result);
repeat
Result := Result + SecsPerDay;
Secs2Date(Result, Date);
until (Date.WeekDay = 0);
end;


function Utc2Local(Secs: longint): longint;
var Date: DTRec;
begin
Secs2Date(Secs, Date);
if (Date.Year <> DlstYear) then
begin
DlstYear := Date.Year;
DlstStart := NextSunday(24, 3, DlstYear);
DlstEnd := NextSunday(24, 10, DlstYear);
end;
if (Secs >= DlstStart) and (Secs <= DlstEnd)
then Result := Secs + 7200
else Result := Secs + 3600;
end;


function Local2Utc(Secs: longint): longint;
var Date: DTRec;
begin
Secs2Date(Secs, Date);
if (Date.Year <> DlstYear) then
begin
DlstYear := Date.Year;
DlstStart := NextSunday(24, 3, DlstYear);
DlstEnd := NextSunday(24, 10, DlstYear);
end;
if (Secs >= DlstStart) and (Secs <= DlstEnd)
then Result := Secs - 7200
else Result := Secs - 3600;
end;


function EasterSunday(Year: integer): longint;
var Date: DTRec;
begin
fillchar(Date, SizeOf(Date), #0);
case (Year mod 19) of
0: Date.Day := 14;
1: Date.Day := 3;
2: Date.Day := 23;
3: Date.Day := 11;
4: Date.Day := 31;
5: Date.Day := 18;
6: Date.Day := 8;
7: Date.Day := 28;
8: Date.Day := 16;
9: Date.Day := 5;
10: Date.Day := 25;
11: Date.Day := 13;
12: Date.Day := 2;
13: Date.Day := 22;
14: Date.Day := 10;
15: Date.Day := 30;
16: Date.Day := 17;
17: Date.Day := 7;
18: Date.Day := 27;
end;
if (Date.Day > 20) then Date.Month := 3 else Date.Month := 4;
Date.Year := Year;
Date2Secs(Date, Result);
repeat
Result := Result + SecsPerDay;
Secs2Date(Result, Date);
until (Date.WeekDay = 0);
end;


function GetHoliday(Year, Holiday: integer): longint;
begin
Result := 0;
case Holiday of
0: Result := EasterSunday(Year); { Ostersonntag }
1: begin { Muttertag }
Result := NextSunday(7, 5, Year);
if (Result = EasterSunday(Year) + (49 * SecsPerDay)) then Result :=
Result + (7 * SecsPerDay);
end;
2: Result := NextSunday(29, 9, Year); { Erntedankfest }
3: Result := NextSunday(19, 11, Year); { Totensonntag }
4: Result := NextSunday(24, 12, Year) - (7 * SecsPerDay); { 4. Advent }
end;
end;


function Secs2Time(Secs: longint): TDateTime;
begin
Result := (Secs / SecsPerDay) + 29221;
end;


function Time2Secs(Time: TDateTime): longint;
begin
Result := Trunc((Time - 29221) * SecsPerDay);
end;


function Date2Iso(Date: DTRec; Format: IsoFormat): string;
begin
if (Format = IsoShort) then Result := DTS(Date, 5, 5, 'T') else Result :=
DTS(Date, 1, 1, ' ');
end;


function Secs2Iso(Secs: longint; Format: IsoFormat): string;
var Date: DTRec;
begin
Secs2Date(Secs, Date);
Result := Date2Iso(Date, Format);
end;


function Iso2Date(S: string): DTRec;
var i: integer;
begin
fillchar(Result, SizeOf(Result), #0);

if (length(S) = 15) and (pos('T', S) = 9) then
begin
Result.Year := Zin(copy(S, 1, 4));
Result.Month := Zin(copy(S, 5, 2));
Result.Day := Zin(copy(S, 7, 2));
Result.Hour := Zin(copy(S, 10, 2));
Result.Minute := Zin(copy(S, 12, 2));
Result.Second := Zin(copy(S, 14, 2));
end
else begin
i := pos('-', S);
if (i > 0) then
begin
Result.Year := Zin(copy(S, 1, i - 1));
if (Result.Year < 100) then inc(Result.Year, 2000);
delete(S, 1, i);

i := pos('-', S);
Result.Month := Zin(copy(S, 1, i - 1));
delete(S, 1, i);

i := pos(' ', S);
Result.Day := Zin(copy(S, 1, i - 1));
delete(S, 1, i);

i := pos(':', S);
Result.Hour := Zin(copy(S, 1, i - 1));
delete(S, 1, i);

i := pos(':', S);
Result.Minute := Zin(copy(S, 1, i - 1));
delete(S, 1, i);

Result.Second := Zin(S);
end;
end;
NormalizeDate(Result);
end;


function Iso2Secs(S: string): longint;
var Date: DTRec;
begin
Date := Iso2Date(S);
Date2Secs(Date, Result);
end;


initialization
DlstYear := -1;

end.
Stefan Koschke
2007-02-20 07:35:12 UTC
Permalink
Hallo Jens,
Post by Jens-Erich Lange
Post by Stefan Koschke
eine Abweichung von 2 sec :-((((
Muß ich denn wirklich mein gesamtes Programm vom Typ TDatetime auf
integer umstellen (Zeitstempel generell als Sekunden seit Zeitpunkt x)
oder gibt es doch einen Weg um diese "Ungenauigkeiten zu eliminieren?
Ich verwende seit jeher diese Methode. Auf jedem OS, mit jeder
Sprache und ich finde es gibt nichts Besseres. Das jeweilige
Wandeln in den ab und zu benötigten TDateTime ist dann ein Klacks.
Ok, Du musst die Grenzen kennen. D.h. bei den heute noch üblichen
32 Bit Integern deckt Du eben nur einen Zeitraum von einigen Jahr-
zehnten ab. Wer seine Routinen zu gegebener Zeit auf 64 Bit auf-
bohrt, hat dann erst mal wieder etwas Ruhe :-)
Darf ich Dir gleich mal meine Delphi 5 Unit "SysTime.pas" zeigen?
Diese enthält auch die Berechnungsmöglichkeit für alle beweglichen
Feiertage.
...schnipp

danke, die werde ich mir mal genauer unter die Lupe nehmen!

Ciao
Stefan
Hans-Peter Diettrich
2007-02-19 13:52:20 UTC
Permalink
Post by Stefan Koschke
Aber meine eigentliche Frage hat bisher niemand beantwortet (oder
Muß man mit "Ungenauigkeiten" rechnen, wenn man auf ein TDateTime einen
Double addiert, so z.B.
result := result + (123/1440) //123 Minuten dazu oder
result := result + (1435/86400) //1435 Sekunden dazu ?
Ungenauigkeiten lassen sich prinzipiell nicht vermeiden, das hast Du
völlig richtig erkannt. Sie dürften allerdings bei Zeiten ohne Datum bei
+-10^-18 Tagen liegen - Du müßtest nur Datum und Zeit getrennt speichern.

Als exakte Alternative käme nur eine Darstellung
mit ganzen Zahlen in Frage, und dazu müßte man alle Funktionen von Hand
implementieren.

DoDi
Marian Aldenhövel
2007-02-19 17:07:49 UTC
Permalink
Hallo,
Post by Alfred Gemsa
EncodeDate(h+(123 DIV 60),n+(123 MOD 60),s,ms) sollte aber gehen.
Nein. EncodeTime besteht auf "legalen" Angaben. Also ginge Deine Version
zum Beispiel kurz vor Mitternacht bitter in die Hose.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Kroni
2007-02-19 11:43:14 UTC
Permalink
Post by Stefan Koschke
(123 / 1440) eben vielleicht ein paar ms darüber oder darunter liegt oder
ist diese Befürchtung unbegründet?
Die numerische Ungenauigkeit liegt sicher nicht im *ein bar ms* Bereich
sondern wesentlich weiter *Hinten*.

K.R.
Marian Aldenhövel
2007-02-19 17:18:59 UTC
Permalink
Hi,
Post by Kroni
Die numerische Ungenauigkeit liegt sicher nicht im *ein bar ms* Bereich
sondern wesentlich weiter *Hinten*.
Eine ms als Datetime ausgedrückt ist 1/24/60/60/1000 = 1,16e-8. Werte für
"heute" haben 5 Stellen vor dem Komma. Mit anderen Worten: Du hast recht.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Christian Gudrian
2007-02-20 07:30:27 UTC
Permalink
Post by Marian Aldenhövel
Eine ms als Datetime ausgedrückt ist 1/24/60/60/1000 = 1,16e-8. Werte für
"heute" haben 5 Stellen vor dem Komma. Mit anderen Worten: Du hast recht.
Das macht schon 13 signifikante Stellen. Double kann 15. "Wesentlich"
davon entfernt ist man dann doch eher nicht mehr, oder?

Christian
Marian Aldenhövel
2007-02-20 15:17:14 UTC
Permalink
Hi,
"Wesentlich" davon entfernt ist man dann doch eher nicht mehr, oder?
"Wesentlich" > "ein paar ms". Aber das ist nicht sehr wissenschaftlich :-).

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Marian Aldenhövel
2007-02-19 17:12:10 UTC
Permalink
Hallo,
Post by Stefan Koschke
Nun aber meine Frage : es gibt ja systembedingt bei Double-Werten geringste
Abweichungen, so daß ich "befürchte" daß der daraus resultierende Zeitpunkt
(123 / 1440) eben vielleicht ein paar ms darüber oder darunter liegt oder
ist diese Befürchtung unbegründet?
Die Befürchtung ist berechtigt. Aber sie sollte Dich nicht davon abhalten so
zu rechnen. Zum einen ist schon Dein "gegebener Zeitpunkt" davon
betroffen und zum anderen rechnen natürlich alle fertigen Implementationen
auch nur mit Wasser, äh. IEEE-Doubles.
Post by Stefan Koschke
ist diese Befürchtung unbegründet?
Berechtigt ja. Begründet? Was würde denn wenn Dein Programm den Zielzeitpunkt
um, sagen wir mal, 200ms falsch berechnen würde? In der Regel nix. Jedenfalls
so lange Du nicht auf Gleichheit vergleichst...
Post by Stefan Koschke
Wie verfahrt Ihr bei solchen Anforderungen?
Ich lasse mir keine Anforderungen vorgeben, bei denen eine DateTime-Angabe auf
Millisekunden genau sein soll.

Willst Du exakt rechnen, dann brauchst Du einen "record H,M,S:integer end;"
Und eigene Routinen.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Stefan Koschke
2007-02-20 07:34:06 UTC
Permalink
Hallo Marian,
Post by Marian Aldenhövel
Hallo,
...
Post by Marian Aldenhövel
Berechtigt ja. Begründet? Was würde denn wenn Dein Programm den Zielzeitpunkt
um, sagen wir mal, 200ms falsch berechnen würde? In der Regel nix. Jedenfalls
so lange Du nicht auf Gleichheit vergleichst...
Gleichheit prüfe ich so nicht, aber aufgefallen sind mir die Probleme, als
ich Sekundendifferenzen berechnet habe und
obwohl Zeit 1 = 9:15 und Zeit 2 = 9:30 (per DateTimeToStr() angesehen) kam
als Differenz 899 sec raus :-(
Das war der eigentliche Anstoß mir das alles mal genauer anzusehen.
Post by Marian Aldenhövel
Willst Du exakt rechnen, dann brauchst Du einen "record H,M,S:integer end;"
Und eigene Routinen.
Ich befürchte, daß ich das brauche ;-)

Ciao
Stefan
Christian Gudrian
2007-02-20 07:38:38 UTC
Permalink
Post by Stefan Koschke
Gleichheit prüfe ich so nicht, aber aufgefallen sind mir die Probleme, als
ich Sekundendifferenzen berechnet habe und
obwohl Zeit 1 = 9:15 und Zeit 2 = 9:30 (per DateTimeToStr() angesehen) kam
als Differenz 899 sec raus :-(
Das macht auf mich den Eindruck einer falschen Integer-Rundung. Wie
sieht die Differenz als Fließkomma-Wert aus?
Post by Stefan Koschke
Ich befürchte, daß ich das brauche ;-)
Sekundengenaue Berechnungen sollten mit TDateTime überhaupt kein Problem
darstellen. Man muss halt nur aufpassen, dass man zum richtigen
Zeitpunkt auf richtige Weise rundet.

Gruß,

Christian
Marian Aldenhövel
2007-02-20 15:19:04 UTC
Permalink
Hi,
Post by Stefan Koschke
obwohl Zeit 1 = 9:15 und Zeit 2 = 9:30 (per DateTimeToStr() angesehen) kam
als Differenz 899 sec raus :-(
Das kann ja zum Beispiel auch daran liegen, daß Du Sekundenanteile hattest,
Die Dir das DateTimeToStr() mit hh:nn als Format nicht verrät. Oder daran, daß
Du falsch rundest.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Stefan Koschke
2007-02-21 08:04:44 UTC
Permalink
Hallo Marian,
Post by Marian Aldenhövel
Hi,
Post by Stefan Koschke
obwohl Zeit 1 = 9:15 und Zeit 2 = 9:30 (per DateTimeToStr() angesehen)
kam als Differenz 899 sec raus :-(
Das kann ja zum Beispiel auch daran liegen, daß Du Sekundenanteile hattest,
Die Dir das DateTimeToStr() mit hh:nn als Format nicht verrät. Oder daran, daß
Du falsch rundest.
nein, dummerweise nicht, weil die Zeitpunkte im Programm generiert werden,
und zwar alle per EncodeDate() EncodeTime() und da gibt es definitiv keie
Sekundenbruchteile (der ms-Parameter ist immer 0).
Grund wird wohl, wie schon festgestellt wurde, die Ungenauigkeiten des
Double sein was sich bei mir eben negativ auswirkt.
Ich bin wirklich schon am Überlegen, komplett umzubauen (record mit
y,m,d,h,n,s : integer) und alles drumrum selbst zu basteln.
Leider wird das recht aufwändig :-(

Ciao
Stefan
Marian Aldenhövel
2007-02-21 10:21:22 UTC
Permalink
Hi,
Post by Stefan Koschke
Post by Stefan Koschke
obwohl Zeit 1 = 9:15 und Zeit 2 = 9:30 (per DateTimeToStr() angesehen)
kam als Differenz 899 sec raus :-(
const SecondsPerDay=24*60*60;
var T1,T2:TDateTime;
Seconds:double;
begin
T1:=Date()+EncodeTime(9,15,0,0);
T2:=Date()+EncodeTime(9,30,0,0);

Seconds:=(T2-T1)*SecondsPerDay;
ShowMessage(FloatToStr(Seconds));
end;

Verhält sich vollständig brav. Eben getestet mit D7.

Sicher ist das Ergebnis ungleich 900, aber es liegt nah genug. Hackst Du
mit Trunc() die Nachkommastellen von Seconds einfach ab, so kannst Du Dich
natürlich viel weiter von der richtigen Antwort entfernen als die Rechnung
ergeben hat.

In meinem Beispiel kommt heute etwas raus, das etwas über 900 liegt, da
wäre auch mit trunc() alles gut. Aber niemand garantiert Dir, daß morgen
Seconds nicht knapp unter 900 liegt, sagen wir 899.9999999976 oder so.
Trunce() hier, und Du hast den Fehler mal eben um einen Faktor von einer
Milliarde vergrößert.

Also an der richtigen Stelle behutsam runden. Aber das wurde hier ja schon
erwähnt.
Post by Stefan Koschke
Grund wird wohl, wie schon festgestellt wurde, die Ungenauigkeiten des
Double sein was sich bei mir eben negativ auswirkt.
Ich bezweifle das immer noch.
Post by Stefan Koschke
Ich bin wirklich schon am Überlegen, komplett umzubauen (record mit
y,m,d,h,n,s : integer) und alles drumrum selbst zu basteln.
Leider wird das recht aufwändig :-(
Und nicht notwendigerweise korrekter :-). Rechnen mit Zeiten ist schwer.

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Stefan Koschke
2007-02-21 12:15:58 UTC
Permalink
Hallo Marian,
Post by Marian Aldenhövel
Hi,
..
Post by Marian Aldenhövel
const SecondsPerDay=24*60*60;
var T1,T2:TDateTime;
Seconds:double;
begin
T1:=Date()+EncodeTime(9,15,0,0);
T2:=Date()+EncodeTime(9,30,0,0);
Seconds:=(T2-T1)*SecondsPerDay;
ShowMessage(FloatToStr(Seconds));
end;
Verhält sich vollständig brav. Eben getestet mit D7.
Sicher ist das Ergebnis ungleich 900, aber es liegt nah genug. Hackst Du
mit Trunc() die Nachkommastellen von Seconds einfach ab, so kannst Du Dich
natürlich viel weiter von der richtigen Antwort entfernen als die Rechnung
ergeben hat.
In meinem Beispiel kommt heute etwas raus, das etwas über 900 liegt, da
wäre auch mit trunc() alles gut. Aber niemand garantiert Dir, daß morgen
Seconds nicht knapp unter 900 liegt, sagen wir 899.9999999976 oder so.
Seconds:=(T2-T1)*SecondsPerDay;
und als Ergebnis dann 899.9999999976 oder so,
Du hast genau meinen Rechenansatz für die Sekundendifferenz benutzt und es
kam eben (sonst wäre ich ja nie drüber gestolpert) die erwähnten
899,99999... heraus
Mein Problem wurde offensichtlich, als ich die Sekundendifferenz (wie oben
berechnet) MOD 900 des festgelegten Rasters beurteilt habe (wenn nicht im
Raster dann soll das nächste Raster aufgesucht werden).
Ich könnte nun generell Round() verwenden aber so ganz sicher bin ich mir
überhaupt nicht mehr :-)
Post by Marian Aldenhövel
Rechnen mit Zeiten ist schwer.
wie Recht Du hast ;-)
Und in diesen Zeiten noch mehr ;-)))

Ciao
Stefan
Matthias Hanft
2007-02-21 12:55:38 UTC
Permalink
Post by Stefan Koschke
Ich könnte nun generell Round() verwenden aber so ganz sicher bin ich mir
überhaupt nicht mehr :-)
Bei den "Seconds" halte ich "Round" für ungefährlich. Du darfst "Round"
in Deiner Anwendung nur nie auf einen "TDateTime"-Wert anwenden :-)

Gruß Matthias.
Hans-Peter Diettrich
2007-02-21 15:13:36 UTC
Permalink
Post by Stefan Koschke
Du hast genau meinen Rechenansatz für die Sekundendifferenz benutzt und es
kam eben (sonst wäre ich ja nie drüber gestolpert) die erwähnten
899,99999... heraus
Na also, das ist doch in Ordnung?

Wenn *Du* diese Zahl auf 899,0 "rundest", dann sitzt das Problem eher
*vor* dem Bildschirm ;-)

DoDi
Stefan Koschke
2007-02-21 15:48:49 UTC
Permalink
Hallo Dodi,
Post by Hans-Peter Diettrich
Post by Stefan Koschke
Du hast genau meinen Rechenansatz für die Sekundendifferenz benutzt und
es kam eben (sonst wäre ich ja nie drüber gestolpert) die erwähnten
899,99999... heraus
Na also, das ist doch in Ordnung?
Wenn *Du* diese Zahl auf 899,0 "rundest", dann sitzt das Problem eher *vor*
dem Bildschirm ;-)
Du hast nicht ganz richtig gelesen, ich war immer davon ausgegangen, daß ich
korrekte gerade Sekunden bekomme weil ich per EncodeTime(x,y,z,0) glatte
Zeitstempel erzeuge.
Und dann habe ich nie gerundet, sondern unter der falschen Voraussetzung
verglichen :
if (sekunden mod 900) <> 0 und da schlägt eben der fehlerteufel zu ;-)

Ciao
Stefan
Mario Rothacher
2007-02-21 15:53:36 UTC
Permalink
Post by Stefan Koschke
Du hast nicht ganz richtig gelesen, ich war immer davon ausgegangen, daß ich
korrekte gerade Sekunden bekomme weil ich per EncodeTime(x,y,z,0) glatte
Zeitstempel erzeuge.
Und dann habe ich nie gerundet, sondern unter der falschen Voraussetzung
if (sekunden mod 900) <> 0 und da schlägt eben der fehlerteufel zu ;-)
Wenn man schon EncodeTime benutzt, warum dann nicht auch DecodeTime?
Dort sind alle Rückgabetypen schön als Word-Typen ohne Vorzeichen und
Komma...

cu
Mario
Marian Aldenhövel
2007-02-21 18:15:20 UTC
Permalink
Hi,
Post by Mario Rothacher
Wenn man schon EncodeTime benutzt, warum dann nicht auch DecodeTime?
Weil es keinen Aufruf von DecodeTime gibt, der eine ZeitDAUER als "900s"
zurückgaben kann?

Ciao, MM
--
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
Mario Rothacher
2007-02-22 09:41:39 UTC
Permalink
Post by Marian Aldenhövel
Hi,
Post by Mario Rothacher
Wenn man schon EncodeTime benutzt, warum dann nicht auch DecodeTime?
Weil es keinen Aufruf von DecodeTime gibt, der eine ZeitDAUER als "900s"
zurückgaben kann?
Aber Sekunden+Minuten*60+Stunden*3600... ergibt immer noch eine schöne
Ganzzahl ;-)

cu
Mario

Matthias Hanft
2007-02-21 16:45:33 UTC
Permalink
Post by Stefan Koschke
Du hast nicht ganz richtig gelesen, ich war immer davon ausgegangen, daß ich
korrekte gerade Sekunden bekomme weil ich per EncodeTime(x,y,z,0) glatte
Zeitstempel erzeuge.
Du mußt Dich von der Vorstellung lösen, daß Zeit jemals glatt sein
könnte :-) (hatte das nicht auch Herr Einstein schon irgendwann mal
bewiesen?! :-) )

Im Ernst, das Datum-/Zeit-Zeug ist intern einfach eine Gleitkomma-
zahl (wie z.B. 12354,2394072352563534) mit allen Konsequenzen. Das
muß man immer im Hinterkopf behalten!

Gruß Matthias.
Hans-Peter Diettrich
2007-02-21 22:53:19 UTC
Permalink
Post by Stefan Koschke
Post by Hans-Peter Diettrich
Wenn *Du* diese Zahl auf 899,0 "rundest", dann sitzt das Problem
eher *vor* dem Bildschirm ;-)
Du hast nicht ganz richtig gelesen, ich war immer davon ausgegangen,
daß ich korrekte gerade Sekunden bekomme weil ich per
EncodeTime(x,y,z,0) glatte Zeitstempel erzeuge.
Das liest sich in Deinem ersten Posting aber ganz anders:
Nun aber meine Frage : es gibt ja systembedingt bei Double-Werten
geringste Abweichungen, so daß ich "befürchte" daß der daraus
resultierende Zeitpunkt (123 / 1440) eben vielleicht ein paar ms
darüber oder darunter liegt oder ist diese Befürchtung unbegründet?
<<
Post by Stefan Koschke
Und dann habe ich nie gerundet, sondern unter der falschen
Voraussetzung verglichen : if (sekunden mod 900) <> 0 und da schlägt
eben der fehlerteufel zu ;-)
Vergleichen auf gleich/ungleich ist bei Gleitkommazahlen (Double) eben
tödlich, das hätte eigentlich von Anfang an klar sein sollen.

Aber solange es Dir nur um ganze Sekunden oder Millisekunden geht, mußt
Du ja nur die Differenzen richtig in Integer umwandeln, und dann
vergleichen.

DoDi
Loading...