Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Erledigt - DateUtils.RecodeTime und 0 Sekunden (https://www.delphipraxis.net/193692-erledigt-dateutils-recodetime-und-0-sekunden.html)

Glados 29. Aug 2017 21:23


Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Ich verwende aktuell RecodeTime, um die Uhrzeit einer DateTime-Variable anzupassen.
Bei der Übergabe von 86399 (23:59:59) geht komischerweise eine Sekunde verloren und daraus wird 25:59:58.
Woran kann das liegen?

Delphi-Quellcode:
function SecondsToDateTime(wSeconds: Int64): TDateTime;
var
 aHours, aMinutes, aSeconds, aDivisor: Int64;
begin
 aDivisor := 60;
 aSeconds := wSeconds mod aDivisor;
 aMinutes := (wSeconds div aDivisor) mod aDivisor;
 aHours := (wSeconds div aDivisor) div aDivisor;
 aHours := aHours mod 24;

 Result := EncodeTime(aHours, aMinutes, aSeconds, 000);
end;

function UnixToDateTime(Timestamp: Integer): TDateTime;
begin
 Result := (Timestamp / 86400) + 25569;
end;

unction DateTimeToUnix(DateTime: TDateTime): Integer;
begin
 Result := Trunc((DateTime - 25569) * 86400); // Lösung gefunden: hier round statt trunc
end;

function ChangeTime(DateTime: TDateTime; const NewTime: Integer): Integer;
var
 aNewTime: TDateTime;
begin
 if (NewTime >= 86400) or (NewTime <= 0) then // Sicherheitshalber denn sonst gäbe es gar keine Zeitangabe!
  aNewTime := StrToTime('00:00:00')
 else
  aNewTime := SecondsToDateTime(NewTime);

 // bis hier hin ist es noch 23:59:59

 DateTime := RecodeTime(DateTime, System.DateUtils.HourOf(aNewTime), System.DateUtils.MinuteOf(aNewTime), System.DateUtils.SecondOf(aNewTime), 000);
 Result := DateTimeToUnix(DateTime);

 ShowMessage(DateTimeToStr(UnixToDateTime(Result)) + sLineBreak + NewTime.ToString); // Resultat 23:59:58
end;
Ok das 58 zu 59-Problem ist gelöst. Round statt Trunc in meiner eigenen Funktion war die Lösung.
Aber ein letztes Problem besteht noch.
Wie stellt man mit DateTimeToStr() ein Datum mit einer Uhrzeit von 00:00:00 dar?

Gerade entdeckt, dass DateTimeToStr() keine Zeit darstellt, wenn es 00:00:00 ist.

Erledigt!

himitsu 29. Aug 2017 23:13

AW: Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Bei mir stimmt es und ist am Ende immernoch :59 .

Wurde in deinem Programm am Round-Mode rumgepfuscht?

TDateTime (Double) ist noch ein paar Jährchen genau genug, um auf mindestens 1 Millisekunde genau zu sein.
Also Rundungsfehler aufgrund der Datengröße kann es nicht sein.
Bleibt also nur noch ein anderer Rundungsmodus oder eine kaputte FPU. :stupid:


PS: Ab dem 19. Januar 2038 um 03:14:08 wird deine Funktion wieder kaputt sein, wenn der Integer zu klein für den Unix-Timestamp ist. :angle:


[edit]
Ahh, also doch ein Rundungsproblemchen, nur wo anders. :lol:

und
Delphi-Referenz durchsuchenFormatDateTime

Glados 29. Aug 2017 23:24

AW: Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Zitat:

Bei mir stimmt es und ist am Ende immernoch :59 .
Ahh, also doch ein Rundungsproblemchen, nur wo anders.
Mit Trunc oder Round?
Genau. Trunc durch Round tauschen und alles ist gut.

Zitat:

PS: Ab dem 19. Januar 2038 um 03:14:08 wird deine Funktion wieder kaputt sein, wenn der Integer zu klein für den Unix-Timestamp ist.
Na dann werde ich schon jetzt alle Integer-Timestamps durch irgendwas anderes ersetzen. Int64, hilft das?
Ansonsten baue ich alles nach ISO 8601 YYYYMMDDHHMMSS) um.
( Ich habe hierzu ein neues Thema eröffnet: http://www.delphipraxis.net/193693-d...ml#post1379906 )

Zitat:

FormatDateTime
Was FormatDateTime angeht: es werden keine Uhrzeiten 00:00:00 dargestellt. Findet sich auch einiges bei Google drüber.
Habe das jetzt anders gfelößt.
Aber wie kommt man auf die beknackte Idee 00:00:00 nicht darstellen zu müssen?

Uwe Raabe 30. Aug 2017 07:41

AW: Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Zitat:

Zitat von Glados (Beitrag 1379905)
Zitat:

FormatDateTime
Was FormatDateTime angeht: es werden keine Uhrzeiten 00:00:00 dargestellt. Findet sich auch einiges bei Google drüber.
Habe das jetzt anders gfelößt.
Aber wie kommt man auf die beknackte Idee 00:00:00 nicht darstellen zu müssen?

Das gilt doch aber nur, wenn du als Format einen Leerstring oder
Delphi-Quellcode:
'c'
mitgibst. Versuch mal
Delphi-Quellcode:
'ddddd t'
als Format-String.

Sherlock 30. Aug 2017 07:55

AW: Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Klar geht das mit FormatDateTime, gerade unter Tokyo.1 getestet.

Delphi-Quellcode:
procedure TForm10.Button1Click(Sender: TObject);
var
  mytime: TDateTime;
begin
  mytime := Trunc(Now);
  Label1.Caption := FormatDateTime('ddddd tt', mytime, TFormatSettings.Create);
end;
Das liefert im Label dann "30.08.2017 00:00:00"

Ansonsten ist das Verhalten von DateTimeToString "as designed".

Sherlock

sko1 30. Aug 2017 09:22

AW: Erledigt - DateUtils.RecodeTime und 0 Sekunden
 
Zitat:

Gerade entdeckt, dass DateTimeToStr() keine Zeit darstellt, wenn es 00:00:00 ist.
Dann nimm FormatDateTime und Du hast, egal wie die Uhrzeit ist, immer die gleiche Formatierung!

Ciao
Stefan


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:08 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