Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi mit Zeiten Rechnen (https://www.delphipraxis.net/67377-mit-zeiten-rechnen.html)

RX3 13. Apr 2006 23:50


mit Zeiten Rechnen
 
Hallo ich möchte mit Zeiten rechnen und bräuchte bisl Hilfe,

Ich habe eine Zahl (Minutenanzahl), die in eine Zeitangabe umgerechnet werden soll
bsp. 135,5 min = 2:15:30 (2h15min30s)
diese Minutenanzahl wird durch 2 Editfelder berechnet. (Time2)

Nach dieser Berechnung wird in ein drittes Editfeld eine weitere Zeitangabe (Format hh:mm:ss) eingegeben. (Time1)
Von dieser Zeitangabe sollen die vorherigen Minuten abgezogen werden (Time3 = Time1-Time2)

Kann mir da irgendjemand weiterhelfen?
Irgendwie krieg ich das mit den Encode/DecodeTime-Funktionen nich ganz hin.

Folgenden Code habe ich bisher

Delphi-Quellcode:
  a := StrToInt64(Edit1.Text);      //a = Ressis vorhanden
  b := StrToInt64(Edit2.Text);      //b = Ressiproduktion pro h
  h := Trunc(a/b);                //h = Stundenanzahl seit Verlassen der Flotte
  m := Round(h/60);               //m = Minutenanzahl seit Verlassen der Flotte
  s := Round(m/60);
  ss:= Round(S/100);

  TimeSeparator := ':';
  ShortTimeFormat := 'hh:mm:ss';
  Time1 := StrToTime(Edit3.Text);  //Time1 = Spionagezeitpunkt
  TryEncodeTime(h,m,s,ss,Time2);   //Time2 = berechnete Flugzeit aus Ressiproduktion
  Time3 := Time1-Time2;

  DecodeTime(Time3,h3,m3,s3,ss3);
  Label1.Caption := IntToStr(h3) + ':' + IntToStr(m3) + ':' + IntToStr(s3);
(bitte keine professionellen Code-Vorschläge, sondern einfachen simplen Code, damit ich es auch selber verstehe *gg*)

ichbins 14. Apr 2006 00:31

Re: mit Zeiten Rechnen
 
Erstmal ist die Anzahl der Minuten nicht die Anzahl der Stunden durch 60 sondern die Anzahl der Stunden mal 60 ;) (genauso bei sekunden etc.)

Dann sieht es bei dir so aus dass du sagst: 2 Stunden, 120 Minuten und 7200 Sekunden, wobei du ja eher meinst: 2 Stunden, 0 Minuten und 0 Sekunden ;)


Also berechne erstmal die Anzahl der hundertstel Sekunden aus der Stundenzahl:

Delphi-Quellcode:
var
  ss,s,m,h,rest:integer;
begin
  rest:=round(ZEITWERT IN STUNDEN * 360000); //den zeitwert in Stunden solltest du mit strtofloat bestimmen (Kommazahlen möglich)
  ss:=rest mod 100 //Die Anzahl der Hundertstelsekunden entspricht dem Teilungsrest des Zeitwerts (rest) durch hundert.
  rest:=rest div 100 //Jetzt durch hundert teilen, da die Hundertstelsekunden erledigt sind.
  //das selbe mit sec/min/h machen:
 
  s:=rest mod 60;
  rest:=rest div 60;

  min:=rest mod 60;
  rest:=rest div 60;
 
  h:=rest; //der übrige Wert in REST ist die Stundenanzahl
end;

Hawkeye219 14. Apr 2006 00:53

Re: mit Zeiten Rechnen
 
Hallo,

Du kannst die Sache noch weiter vereinfachen, wenn Du die Routine IncMilliSecond aus der Unit DateUtils verwendest.
Damit kann man eine Anzahl Millisekunden zu einem TDateTime-Wert addieren:

Delphi-Quellcode:
a := StrToInt64(Edit1.Text);    // a = Ressis vorhanden
b := StrToInt64(Edit2.Text);    // b = Ressiproduktion pro h
Time1 := StrToTime(Edit3.Text); // Time1 = Spionagezeitpunkt

// Stundenanzahl seit Verlassen der Flotte berechnen
h := Trunc(a / b);                
// Flugzeit vom Spionagezeitpunkt subtrahieren
Zeit := IncMilliSecond(Time1, -h * 360000);
Zur Ausgabe des Ergebnisses könntest Du die Funktion FormatDateTime aus der Unit SysUtils verwenden:

Delphi-Quellcode:
Label1.Caption := FormatDateTime('hh:nn:ss', Zeit);
Gruß Hawkeye

negaH 14. Apr 2006 01:00

Re: mit Zeiten Rechnen
 
Und noch einfacher

Delphi-Quellcode:
Label1.Caption := FormatDateTime('hh:nn:ss', 135.5 / 60 / 24);
Denn 135.5 Minuten / 60 Minuten / 24 Stunden sind die Bruchteile eines Tages, und ein TDateTime ist nichts anderes als

TDateTime = Anzahl Tage komma Bruchteile eines Tages

Ein Wert von 0.5 in einem TDateTime ist also exakt 12 Uhr, 0.75 = 3/4tel eines Tages also 18 Uhr.

Du musst also keinerlei Umwege über Stringformatierungen, Datum/Zeit-de-/enkodierungen gehen.

Du kannst also ganz einfach mit Zeiten rechnen:

12 Uhr + 15 Minuten ist

TDateTime( (12 / 24) + (15 / 60 / 24) )

Gruß Hagen

Hawkeye219 14. Apr 2006 01:06

Re: mit Zeiten Rechnen
 
@Hagen: Alles lesen :wink:
Er möchte keinen konstanten Wert darstellen, sondern einen berechneten...

Gruß Hawkeye

3_of_8 14. Apr 2006 01:19

Re: mit Zeiten Rechnen
 
Außerdem, müsste es nicht heißen: 'hh:mm:ss'?

negaH 14. Apr 2006 02:00

Re: mit Zeiten Rechnen
 
Zitat:

@Hagen: Alles lesen
Er möchte keinen konstanten Wert darstellen, sondern einen berechneten...
Und wo ist das problem ?
Diese Frage taucht alle par Tage in der DP auf und immer wieder sehe ich Vorschlage die viel zu kompliziert darauf antworten. Aber am schlimmsten empfinde ich eben den Punkt das die vielen Antworten deutlich zeigen das man nicht verstanden hat was ein TDateTime ist, wie darin das Datum/Uhrzeit oder eben einfach Zeiten kodiert sind und wie man damit rechnet.

Die viele Datum/Zeit Funktion in der RTL sind ja schön und gut aber fast 90% dieser Funktionen sind überflüssig und verkomplizieren das Verständnis.

Worauf ich also mit obigen Posting hinaus wollte ist nicht die fertige Lösung sondern das Verständnis zur fertigen Lösung.

Delphi-Quellcode:
Label1.Caption := FormatDateTime('hh:nn:ss', StrToFloat(Edit1.Text) / 60 / 24);
So besser !? oder so ?

Delphi-Quellcode:
Label1.Caption := FormatDateTime('hh:nn:ss', MinutenWert / 60 / 24);
Zitat:

Außerdem, müsste es nicht heißen: 'hh:mm:ss'?
Nein müsste es nicht. mm gibt den Monat an und da mm schon damit vergeben ist ist laut Delphi Hilfe nn die Stunde.

Und nur kurz was man in Delphi 6 unit Dateutils.pas findet:

Delphi-Quellcode:
function MilliSecondOfTheYear(const AValue: TDateTime): Int64;
begin
  Result := MilliSecondOf(AValue) + SecondOfTheYear(AValue) + 1000;
end;

function MilliSecondOfTheMonth(const AValue: TDateTime): LongWord;
begin
  Result := MilliSecondOf(AValue) + SecondOfTheMonth(AValue) + 1000;
end;

function MilliSecondOfTheWeek(const AValue: TDateTime): LongWord;
begin
  Result := MilliSecondOf(AValue) + SecondOfTheWeek(AValue) + 1000;
end;
Viele schöne Datum/Zeit Funktionen, viel zu viele und dann noch offensichtlich falsch.
Funktionen wie Estern() fehlen aber.

Gruß Hagen

Amateurprofi 14. Apr 2006 02:20

Re: mit Zeiten Rechnen
 
Zitat:

Zitat von negaH
Nein müsste es nicht. mm gibt den Monat an und da mm schon damit vergeben ist ist laut Delphi Hilfe nn die Stunde.

@Hagen : nn ist die Minute, nicht Stunde

negaH 14. Apr 2006 02:22

Re: mit Zeiten Rechnen
 
Stimmt ;)

Gruß Hagen

marabu 14. Apr 2006 09:00

Re: mit Zeiten Rechnen
 
Guten Morgen.

Um beim Rechnen mit Zeitwerten nicht unnötig durch die zwangsläufigen Rundungsfehler der Fließkommaarithmetik überrascht zu werden, rechne ich stets mit Ganzzahlwerten (Sekunden), konvertiere diese aber für die Anzeige und die Benutzereingabe von und zu TDateTime (Fließkommawert) und schließlich String, wobei die von Hagen erwähnte Unit DateUtils gute Dienste leistet. Zum Thema Rundungsfehler beim Rechnen mit Zeiten ist vielleicht auch das Lesen in diesem thread interessant: klick.

Freundliche Grüße vom marabu

Hawkeye219 14. Apr 2006 14:08

Re: mit Zeiten Rechnen
 
@Hagen:
Wenn Du meinen Beitrag noch mal aufmerksam liest, wirst Du feststellen, daß er keine Umwege über Kodierung/Dekodierung enthält. Ich habe gerade diese Aufrufe aus dem Ursprungs-Posting durch ein direktes Rechnen mit TDateTime (gekaspselt in IncMilliSecond) ersetzt. Mein erster Gedanke beim Verfassen des Beitrags war es auch, für die eigentliche Berechnung einen Einzeiler zu schreiben. Diese Zeile

Zitat:

Zitat von RX3
(bitte keine professionellen Code-Vorschläge, sondern einfachen simplen Code, damit ich es auch selber verstehe *gg*)

hat mich aber davon abgehalten. Möglicherweise findet RX3 ja über das Nachschlagen der Funktion IncMilliSecond in der Online-Hilfe den Einstieg in die Verwendung von TDateTime.

Die von Dir beschriebenen Fehler sind, wie Du sicher weißt, spätestens seit Version 6.02 korrigiert. Ob die Unit nun fehlerfrei ist, vermag ich nicht zu sagen. Ich vermeide ebenfalls den übermäßgen Gebrauch der dort angebotenen Funktionen. Ich stimme Dir aber durchaus zu, daß viele Routinen eigentlich überflüssig sind und durch einfache Umrechnungen ersetzt werden können. Eine gedankenlose Verwendung führt aufgrund der möglichen Rundungsfehler zu Problemen, die mit dem von marabu erwähnten Verfahren weitestgehend vermieden werden können.


Eine Korrektur noch zu meinem ersten Beitrag:

Der Aufruf der Trunc-Funktion sollte entfernt werden, die Variable h muß dann natürlich als Real vereinbart werden. Diesen Fehler aus dem Ursprungs-Posting hatte ich nicht korrigiert. Mit Trunc erhält man lediglich die (ganzzahlige) Anzahl Stunden, wodurch die nachfolgende Umrechnung in Millisekunden überflüssig wäre.

Gruß Hawkeye

negaH 14. Apr 2006 14:25

Re: mit Zeiten Rechnen
 
@Marabu:

exakt diese Arbeitsweise benutze ich auch, nur meinstens reichen Minuten und das ist für Datenbanken dann bischen Resourcen schonender.

@Rundungsfehler:

Diese treten immer auf wenn man TDateTime benutzen möchte, das lässt sich höchsten minimieren aber nicht beseitigen. Allerdings stellt sich die Frage wie groß diese Fehler eigentlich sind. In den meisten Fällen sind nämlich nicht diese minimale Rundungsfehler eine Urache eines Problemes sondern schlicht die falsche Art zu runden oder das Ignorieren der Möglichkeit einer Kummulierung von Rundungsfehlern durch den Programmierer.
Um so wichtiger wird es nun das der Programmierer verstanden hat wie TDateTime intern funktioniert, sprich nicht die Lösung eine Problems sondern der Weg zur Lösung eines Problems.

Das in Delphi 6.02 die Fehler beseitigt wurden weis ich und verlange ich auch ! Besonders wenn es um solche Schußlichkeits-Fehler handelt wie oben gepostet. Um so wichtiger wieder der Punkt des Verständisses wie TDateTime arbeitet. Ich für meinen Teil habe, wie jedesmal bei einer neuen Delphi Version, meine übliche Runde durch die RTL Sourcen gedreht um mir ein Urteil über die Qualität der Arbeit der Bolandianer bilden zu können. Obige 3 Fehler sind mir sofort aufgefallen und müssen daher nicht die einzigsten sein. Mein Hinweis auf diese Fehler war also eher ein Fingerzeig das eine überfrachtete Unit wie DateUtils.pas die im Grunde nicht viel essentiell Wichtiges enthält mit höherer Wahrscheinlichkeit Fehler enhält als ein kurzer, prägnanter, auf ein Ziel zugeschnittener Zweizeiler. Auch hier wieder -> ein solcher Zweizeiler ist nur möglich wenn man weis wie TDateTime funktioiniert.


Ergo: nichts persönlich nehmen sondern einfach als Wissensgewinn betrachten.

@Hawkeye:

Zitat:

@Hagen: Alles lesen
Er möchte keinen konstanten Wert darstellen, sondern einen berechneten...
Diese Aussage störte mich. Du impliziertst

1.) ich lese die Beiträge nicht vollständig oder verstehe sie nicht
2.) Du wiederum bist nicht in der Lage eine allgemein gehaltene Erklärung zum Problem zu abstrahieren und dann an die Erfordernisse des speziellen Problems anzupassen.

Ich möchte mich weis Gott nicht daran aufziehen, da ich garnicht weis wie deine Gefühlslage im Moment des Schreibens dieser Zeilen war oder wie Du dich im allgmeinen sprachlich ausdrückst. Es lohnt also nicht sich damit aufzuhalten. Wichtig ist mir nur das der Fragesteller die dahinterstehende Problematik verstehen lernt und gleichzeitig einen Aha-Effekt hat mit dem Gedanken "wusste ich noch garnicht, gut zu wissen, so einfach ist das im Grunde". Aus diesem Blickwinkel wirst du wohl nachvollziehen können das ich erstmal jede überflüssig verkomplizierte Lösung verteufeln muß ;) (weiche von mir du schlechte Lösung, sonst verpasse ich dir eine Ladung geweihter Programmierer Erfahrung :) )

Gruß Hagen

RX3 14. Apr 2006 17:08

Re: mit Zeiten Rechnen
 
Zitat:

Zitat von Hawkeye219
Möglicherweise findet RX3 ja über das Nachschlagen der Funktion IncMilliSecond in der Online-Hilfe den Einstieg in die Verwendung von TDateTime.

Ich probiere grundsätzlich alles erstmal selber, ich denke mal nur so werde ich die Komplexität von Delphi irgendwann mal von alleine durchschauen und verstehen *hoff*
Jedenfalls blättere ich so lange in der Hilfe bis ich was habe womit ich arbeiten kann und probiere dann erstmal ein bischen rum. Erst wenn ich dann absolut nicht mehr weiterkomme, melde ich mich hier im Forum... ;-)
Sonst lern ich das ja nie *g*


Dieser Vorschlag vom Nega erscheint mir am plausibelsten:
Delphi-Quellcode:
Label1.Caption := FormatDateTime('hh:nn:ss', StrToFloat(Edit1.Text) / 60 / 24);
aber dennoch habe ich immernoch nicht das was ich brauche! :-(



ich will das ganze hier nochmal ein wenig genauer erläutern:
1. a = vorhandene Ressourcen (Edit1.Text) bsp: 500000
2. b = Produktion/h (Edit2.Text) bsp: 10000
3. a/b = h = wie lange bereits produziert wurde (in stunden) bsp: 50h
4. dieses h will ich in minuten umwandeln, also h*60. bsp: 50h = 3000min
5. dieser minutenwert (3000min) muss in ein Zeitformat umgewandelt werden, also 50:00:00 (hh:mm:ss)

6. Spionagezeitpunkt in Editfeld eingeben. bsp: 14:01:35 (hh:mm:ss)
7. von diesem Spionagezeitpunkt die 50:00:00 subtrahieren, also 14:01:35 - 50:00:00 = -2d 12:01:35 (vor 2 Tagen)
--> damit habe ich den Startzeitpunkt der Produktion! Den brauche ich!

sieht kompliziert aus, aber für ein paar Profis müsste das doch Peanuts sein ... :roll: :?:

marabu 14. Apr 2006 17:46

Re: mit Zeiten Rechnen
 
Hallo RX3,

du willst einen Zeitraum von einem Zeitpunkt subtrahieren - das Ergebnis ist dann wieder ein Zeitpunkt. In deiner Musterrechnung gibst du aber ein Ergebnis an, welches weder das eine noch das andere ist, sondern eine Mischung aus beidem. Ist das wirklich dein Wunsch?

Ich habe dir die Routine aus dem von mir verlinkten thread einmal so abgeändert, dass sie dir diese Mischgröße ausgibt:

Delphi-Quellcode:
uses
  Math,
  DateUtils;

function DateTimeToStr3(dt: TDateTime; daySep: string): string;
var
  d: Integer;
begin
  d := Floor(dt); // Abstand in Tagen
  dt := dt - d; // Uhrzeit am Zieltag
  Result := Format('%d%s%s', [d, daySep, TimeToStr(dt)]); // Zeichenkette bilden
end;

procedure TDemoForm.TestButtonClick(Sender: TObject);
var
  dt: TDateTime;
  iSec, iDelta: Integer;
begin
  iDelta := 50 * 3600; // Stunden in Sekunden umrechnen
  dt := StrToTime('14:01:35'); // Uhrzeit im internen Format
  iSec := SecondOfTheDay(dt); // auch in Sekunden umrechnen
  iSec := iSec - iDelta; // Differenz bilden
  dt := iSec / SecsPerDay; // wieder in internes Format umwandeln
  ShowMessage(DateTimeToStr3(dt, 'd ')); // Kontrollausgabe
end;
Grüße vom marabu


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:25 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 by Thomas Breitkreuz