Autor Beitrag
Lake
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78


D6 prof., Delphi 10.2 Tokyo
BeitragVerfasst: Mi 29.05.13 12:57 
Hallo ich verstehe etwas nicht.

Wenn ich folgendes Statement (SQL-Server2008) absetze:

(das Feld GueltigVon ist vom Typ DateTime)
ausblenden SQL-Anweisung
1:
Select CAST(GueltigVon as Integeras Zahl, GueltigVon from [Tabelle];					

Erhalte ich folgendes Ergebnis:
|Zahl | GueltigVon |
+------+------------+
|29219 | 01.01.1980 |

Zur Prüfung des Wertes mache ich folgendes
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
var 
  dDatum : TDateTime;
  fWert  : Double
begin
  ...
  dDatum := EncodeDate(1980,1,1);
  fWert  := Double(dDatum )));
  ...
end;


Der Wert von fWert ist aber 29221 und nicht 29219.
Auch die Prüfung in Excel gibt für den 01.01.1980 29221 aus.

Warum ergeben sich hier Unterschiede und wie läßt sich das vermeiden?

_________________
Gruss Lake
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Mi 29.05.13 13:40 
Lass Dir doch einfach mal die 0 als Datum ausgeben, dabei ergibt das dann unter Delphi den 30.12.1899 und unter MSSQL den 01.01.1900. Das macht 2 Tage Unterschied, die Du berücksichtigen musst.
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 29.05.13 19:04 
user profile iconLake hat folgendes geschrieben Zum zitierten Posting springen:
Der Wert von fWert ist aber 29221 und nicht 29219.
Auch die Prüfung in Excel gibt für den 01.01.1980 29221 aus.

Warum ergeben sich hier Unterschiede und wie läßt sich das vermeiden?

Die einfachste Lösung wäre sicherlich, kein TDateTime bei Datenbanken zu verwenden. Man kann das Datum und die Uhrzeit auch in einzelnen Feldern speichern. Z. B.:

datJahr = 2013
datMonat = 5
datTag = 29

Oder als String: "20130529"

Bei einer Uhrzeit entsprechend.

Bei den Zeitangaben kocht doch jeder Hersteller sein eigenes Süppchen. Der Wert bei Excel hängt von den Excel-Optionen ab (1901- oder 1904-Format). Siehe hierzu: office.microsoft.com...calculations_and_for

Mein Festplattenreceiver arbeitet intern beim Erstellen der Film-Header sogar mit dem Modifizierten Julianischem Datum (Nullpunkt der Zeitskala = 17. November 1858).
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 29.05.13 20:11 
Hallo,
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Mein Festplattenreceiver arbeitet intern beim Erstellen der Film-Header sogar mit dem Modifizierten Julianischem Datum (Nullpunkt der Zeitskala = 17. November 1858).

und deshalb: Warum arbeitest Du nicht mit Deinen eigenen Datumszahlen. Das Julianische Datum ist wirklich nicht schlecht, da es denn ganzen Ärger mit den Schaltjahren umgeht.
Die Differenz zweier Julianischer Daten gibt stets den wahren Abstand von zwei Tagen an.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
function julianischesdatum(const jahr,mon,tag:integer):integer;
var y,m,k:longint;
    a,b:real;
begin
   k:=10000*jahr+100*mon+tag;
   b:=-63.5;
   y:=jahr+4712;
   m:=mon+1;
   if mon<=2 then
     begin
       dec(y);
       inc(m,12);
     end;
   if k>=15821015 then
     begin
       a:=int((y+88)/100);
       b:=b+38-a+int(0.25*a);
     end;
   result:=trunc(int(365.25*y)+int(30.6001*m)+tag+b);     //Julianisches Datum
//bzw.
   result:=round(int(365.25*y)+int(30.6001*m)+tag+b-2400000.5); //modifiziertes Julianisches Datum
end;


Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Mi 29.05.13 22:03 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Warum arbeitest Du nicht mit Deinen eigenen Datumszahlen. Das Julianische Datum ist wirklich nicht schlecht, da es denn ganzen Ärger mit den Schaltjahren umgeht.
Die Differenz zweier Julianischer Daten gibt stets den wahren Abstand von zwei Tagen an.
ausblenden Delphi-Quelltext
1:
result:=round(int(365.25*y)+int(30.6001*m)+tag+b-2400000.5); //modifiziertes Julianisches Datum					

Es gibt doch die Funktion
ausblenden Delphi-Quelltext
1:
function ModifiedJulianDateToDateTime(const AValue: Double): TDateTime;					

Der Fragesteller stellte eine Abweichung von 2 Tagen fest. Wenn mal die Datenbank auf die einer anderen Firma umgestellt wird, hat er die Differenz vielleicht nicht mehr, sie bleibt gleich oder ändert sich. Da kommt sicherlich Freude auf, wenn dann die Anwendung und ggf. die Daten angepasst werden müssen. Eine Datumsangabe z. B. in der Form 20130529 ist eindeutig, eine fortlaufende Zahl wie beim TDateTime aber nicht. Selbst Delphi hatte damals beim Versionssprung von Delphi 1 nach Delphi 2 (wenn ich mich bei den Versionsnummern jetzt nicht irre) den Bezugszeitpunkt bei TDateTime geändert. Exportiert man die Daten nach Excel, ist es von den Einstellung bei den Optionen abhängig, wie dort die Werte interpretiert werden.

Mit EncodeDate usw. kann man das innerhalb der Anwendung ggf. für die weitere Verarbeitung der Anwendung umrechnen.

Ich sehe jedenfalls überwiegend Vorteile, wenn man das Datum praktisch im Klartext in der Datenbank ablegt.
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1448

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Mi 29.05.13 22:40 
Hallo,
user profile iconGerd Kayser hat folgendes geschrieben Zum zitierten Posting springen:
Es gibt doch die Funktion
ausblenden Delphi-Quelltext
1:
function ModifiedJulianDateToDateTime(const AValue: Double): TDateTime;					

Bei meinem alten Delphi 5 gibt es das noch nicht.
Es freut mich aber, dass diese Funktion bei moderneren "Delphis" aufgenommen wurde.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Do 30.05.13 09:48 
Man könnte aber auch die komplette Berechnung clientseitig durchführen, da ist dann das Offset unerheblich, und die DB-Struktur muss nicht geändert werden.
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Do 30.05.13 11:01 
Nur kurz, ich muss gleich los. Aber bevor hier noch mehr so tolle Ideen kommen wie "Datum als 3 Felder speichern" :roll:

Man rechnet nicht mit der internen Darstellung von Datumswerten. Nie. Dafür bietet jede Umgebung entsprechende Wrapper an, die dann auch Schaltjahre, Sommerzeit, Schaltsekunden, UTC/GMT und sonstige Absurditäten beachten. Die Anzahl der Stunden zwischen 2 Zeitpunkten ist zum Beispiel ziemlich oft nicht einfach die Anzahl der Tage mal 24...

Entweder also die Berechnung in der DB machen oder aber als TDateTime-Spalte abholen und dann mit dem Field rechnen, dann wird die Umsetzung vom Binding übernommen (meistens über den Umweg einer String-Repräsentation).

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Do 30.05.13 11:17 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Entweder also die Berechnung in der DB machen oder aber als TDateTime-Spalte abholen und dann mit dem Field rechnen, dann wird die Umsetzung vom Binding übernommen (meistens über den Umweg einer String-Repräsentation).

Sag ich doch ;)

Für diesen Beitrag haben gedankt: Martok
Lake Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 78


D6 prof., Delphi 10.2 Tokyo
BeitragVerfasst: Do 30.05.13 19:53 
Vielen Dank für die Posts.

In zukünftigen Projekten werde ich da Datum als String ablegen.

Für die alten Projekte deren Daten nun auf dem SQL-Server liegen werde ich nach einer Möglichkeit suchen dies Problem zu umgehen.

Danke an Alle

_________________
Gruss Lake
Gerd Kayser
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 632
Erhaltene Danke: 121

Win 7 32-bit
Delphi 2006/XE
BeitragVerfasst: Do 30.05.13 21:40 
user profile iconLake hat folgendes geschrieben Zum zitierten Posting springen:
In zukünftigen Projekten werde ich da Datum als String ablegen.

Bei einem Datum als String besteht immer die Gefahr, dass Daten falsch eingegeben werden können. Stichwort wäre z. B. das amerikanische und das deutsche Format (Monat und Tag vertauscht). Dazu noch die Trennzeichen (Punkt, Schrägstrich, Bindestrich). Eine Aufteilung des Datums in year, month, day (jeweils als Zahl abgespeichert) hat Vorteile, auch wenn manche hier das ignorieren wollen. Es kommt immer darauf an, wie die Daten am Günstigsten vorliegen sollen. Beim Löschen eines gesamten Jahres braucht man nur das Jahr anzugeben. Sogar einen Monat eines bestimmten Jahres kann man so gezielt und einfach löschen.

Wenn man mal in Google nach "datenbanken datetime probleme" sucht, wird man von der Masse der Ergebnisse förmlich erschlagen.
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Fr 31.05.13 08:37 
Ich erkenne den Sinn, ein Datenformat in ein anderes zu quetschen, irgendwie nicht, obwohl ich so etwas immer wieder sehe :gruebel: