Zeit über Mitternacht

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Zeit über Mitternacht

Beitrag von AUGE_OHR »

ich bin mir nicht sicher ob das richtig ist ... wie teste ich solche Sachen die über Mitternacht gehen :?:

Code: Alles auswählen

   AADD(::aTimeSec, { SECONDS(), DATE() } )

   FOR i := 2 TO nLen
      nDays  := 0
      nStart := ::aTimeSec[i-1][1]
      nStop  := ::aTimeSec[i]  [1]
      // vergeleiche Datum  
      IF ::aTimeSec[i-1][2] <> ::aTimeSec[i][2]
         nDays := ::aTimeSec[i][2] - ::aTimeSec[i-1][2]
         // nur wenn nStop < nStart ?
         IF nStop < nStart
            nStop += (60*60*24)
            IF nDays = 1
               nDays := 0
            ELSE
               // nDays -= 1
            ENDIF
         ENDIF
      ENDIF
      nSum  += nStop - nStart
      nCount++
   NEXT
   nFull := (nSum / nCount) * 100
   nTime := nFull - nSum
   // Anzeige
   IF nDays < 1
      ::cTimeText := Sec2HMS(nTime)
   ELSE
      ::cTimeText := LTRIM(STR(nDays)) + " " + Sec2HMS(nTime)
   ENDIF
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Zeit über Mitternacht

Beitrag von Tom »

Das kommt mir richtig vor, aber Du läufst natürlich in Probleme, wenn die zweite Zeit trotz Mitternachtüberschreitung größer als die erste ist (Mo, 22.30 Uhr bis Di, 23.00 Uhr). Deshalb addiere ich für solche Fälle/Untersuchungen Sekundenwerte auf das mit 100.000 multiplizierte Val(DtoS())-Datum (20180823000001 wäre die erste Sekunde heute gewesen).
Herzlich,
Tom
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Zeit über Mitternacht

Beitrag von AUGE_OHR »

hi,

Danke für die Antwort. Schade das Xbase++ kein Function dafür hat :(
Das Problem ist das ich noch nicht weiss wie ich es testen soll :idea:
gruss by OHR
Jimmy
Benutzeravatar
HaPe
1000 working lines a day
1000 working lines a day
Beiträge: 995
Registriert: So, 15. Nov 2015 17:44
Wohnort: 71665 Vaihingen-Enz
Hat sich bedankt: 17 Mal
Danksagung erhalten: 15 Mal

Re: Zeit über Mitternacht

Beitrag von HaPe »

Hallo Jimmy !

Abhängig von der Lösung: funktioniert das auch korrekt wenn die Uhr-Zeit weiterhin 2 Mal im Jahr auf Sommerzeit und wieder zurückgestellt wird?
--
Hans-Peter
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Zeit über Mitternacht

Beitrag von AUGE_OHR »

so nun habe ich es anders gelöst : FILETIME64 aus ot4xb

Code: Alles auswählen

LOCAL OldTime  := FileTime64():NEW()
LOCAL NewTime  := FileTime64():NEW()
LOCAL nOneDay  := 60*60*24
LOCAL nSec
...
   AADD(::aTimeSec, { DATE(), TIME() } )
...
   FOR i := 2 TO nLen
      nDays  := 0
      // hier nur einfach die beiden Termine setzten
      OldTime:SetDateTime( ::aTimeSec[i-1][1] , ::aTimeSec[i-1][2] )
      NewTime:SetDateTime( ::aTimeSec[i  ][1] , ::aTimeSec[i  ][2] )
      // er gibt Sekunden > nOneDay zurück
      nSec := ft64_ElapSeconds(OldTime,NewTime)
      nSum += nSec
      IF nSec > nOneDay
         nDays := INT(nSec/nOneDay)
         nSec  -= nDays*nOneDay
      ENDIF

      nCount++
   NEXT
damit kann man auch vielen Tagen einfache Zeit-Rechnungen machen
HaPe hat geschrieben: Do, 23. Aug 2018 20:56Abhängig von der Lösung: funktioniert das auch korrekt wenn die Uhr-Zeit weiterhin 2 Mal im Jahr auf Sommerzeit und wieder zurückgestellt wird?
gute Frage ... :roll:

Code: Alles auswählen

FUNCTION IsDayLightSaving(dDate)
LOCAL nYear := YEAR(dDate)
LOCAL i
LOCAL iMax
LOCAL dStart
LOCAL dTest
LOCAL lRet := .F.
LOCAL T1 := DATE()
LOCAL T2 := DATE()

   dStart := STOD(STRZERO(nYear,4)+"0401")
   FOR i := 1 TO 7
      dTest := dStart -i
      IF DOW(dTest) = 1
         T1 := dTest
         EXIT
      ENDIF
   NEXT

   dStart := STOD(STRZERO(nYear,4)+"1101")
   FOR i := 1 TO 7
      dTest := dStart -i
      IF DOW(dTest) = 1
         T2 := dTest
         EXIT
      ENDIF
   NEXT

   IF dDate >= T1 .AND. dDate <= T2
      lRet := .T.
   ELSE
      lRet := .F.
   ENDIF

RETURN lRet
müsste er dazu nicht auch die Timezone haben ?
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Zeit über Mitternacht

Beitrag von AUGE_OHR »

wenn ich das richtig sehe geht die Sommerzeit dieses Jahr vom 25.03.2018 - 28.10.2018.

Code: Alles auswählen

#include "OT4XB.CH"

PROCEDURE MAIN()
LOCAL st1  := FileTime64():NEW()
LOCAL st2  := FileTime64():NEW()
LOCAL st3
LOCAL nOneDay := 60*60*24
LOCAL nDays := 0

   CLS
   st1:SetDateTime( CTOD("27.10.2018") , "23:59:00" )
   // Ende Sommerzeit 
   st2:SetDateTime( CTOD("30.10.2018") , "23:59:01" )

   st3 := ft64_ElapSeconds(st1,st2)
   IF st3 > nOneDay
      nDays := INT(st3 / nOneDay)
      st3   -= nDays * nOneDay
   ENDIF
   IF !EMPTY(nOneDay)
      ? LTRIM(STR(nDays)) +" Day(s) " + Sec2HMS(st3)
   ELSE
      ? Sec2HMS(st3)
   ENDIF
   WAIT
RETURN
gibt mir
3 Day(s) 00:00:01
Press any key to continue...
=D>
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Zeit über Mitternacht

Beitrag von AUGE_OHR »

eine verbesserte Version, mit TimeZone, liefert nun Andreas Gehrs-Pahl

Code: Alles auswählen

#include "OT4XB.CH"
Procedure Main()
LOCAL cDate1    := '2018-10-27'
LOCAL cDate2    := '2018-10-30'
LOCAL cTime1    := '23:59:00'
LOCAL cTime2    := '23:59:01'
LOCAL cOffset1  := '+02:00'            // CEST ==> +02:00
LOCAL cOffset2  := '+01:00'            // CET   ==> +01:00
LOCAL cPrefix   := 'Difference is: '
LOCAL nOneDay   := 86400               // 60 * 60 * 24
LOCAL nMinutes1 := 0                   // CEST ==> 120
LOCAL nMinutes2 := 0                   // CET  ==> 60
LOCAL nSeconds  := 0
LOCAL nDays     := 0
LOCAL oFT1      := FileTime64():New()
LOCAL oFT2      := FileTime64():New()

  oFT1:SetTimeStamp(cDate1 + 'T' + cTime1 + cOffset1, @nMinutes1)
  QOut('Local Date Time:  ' + oFT1:GetTimeStamp())
  QOut('Time Zone Offset: ' + alltrim(str(nMinutes1)) + ' Minutes')
  oFT1:AddMinutes(0 - nMinutes1)
  QOut('UTC as Date Time: ' + DtoC(oFT1:dDate) + ' ' + oFT1:cTime)
  QOut('UTC as TimeStamp: ' + oFT1:GetTimeStamp())
  QOut('UTC for RFC 822:  ' + oFT1:ToHTTP())
  QOut('')

  oFT2:SetTimeStamp(cDate2 + 'T' + cTime2 + cOffset2, @nMinutes2)
  QOut('Local Date Time:  ' + oFT2:GetTimeStamp())
  QOut('Time Zone Offset: ' + alltrim(str(nMinutes2)) + ' Minutes')
  oFT2:AddMinutes(0 - nMinutes2)
  QOut('UTC as Date Time: ' + DtoC(oFT2:dDate) + ' ' + oFT2:cTime)
  QOut('UTC as TimeStamp: ' + oFT2:GetTimeStamp())
  QOut('UTC for RFC 822:  ' + oFT2:ToHTTP())
  QOut('')

  nSeconds := ft64_ElapSeconds(oFT1, oFT2)
  if nSeconds < 0
     cPrefix  += 'Negative '
     nSeconds := abs(nSeconds)
  endif
  QOut(cPrefix)
  if nSeconds > nOneDay
     nDays    := int(nSeconds / nOneDay)
     nSeconds -= nDays * nOneDay
  endif
  if nDays > 0
     QQOut(alltrim(str(nDays)) + " Day" + iif(nDays == 1, " ", "s "))
  endif
  QQOut(Seconds_to_Time(nSeconds))
return

Function Seconds_to_Time(nSeconds)
LOCAL nHours    := int(nSeconds / 3600)
LOCAL nMinutes  := int((nSeconds - (nHours * 3600)) / 60)
LOCAL nRest     := nSeconds - (nHours * 3600 + nMinutes * 60)
LOCAL lDecimals := nSeconds > int(nSeconds)
return (StrZero(nHours, 2) + ':' + StrZero(nMinutes, 2) + ':' + ;
        StrZero(int(nRest), 2) + iif(lDecimals, '.' + StrZero(100 * (nSeconds - ;
        int(nSeconds)), 2), ''))
^

---

da ich nur die "absolute" Zeit haben will kann ich auch die API Funktion "GetTickCount" verwenden

Code: Alles auswählen

FUNCTION SystemUpTime()
RETURN DllCall("Kernel32.dll",DLL_STDCALL,"GetTickCount")
damit erhalte ich die "Ticks" wie lange der PC schon läuft.
gruss by OHR
Jimmy
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Zeit über Mitternacht

Beitrag von Werner_Bayern »

In 2.0er Syntax:

Code: Alles auswählen

EXTERN UINTEGER GetTickCount() IN KERNEL32
EXTERN UINTEGER64 GetTickCount64() IN KERNEL32
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Zeit über Mitternacht

Beitrag von AUGE_OHR »

Werner_Bayern hat geschrieben: Sa, 25. Aug 2018 0:06 In 2.0er Syntax:
aus Pablos Forum
Since Xbase++ Version 2.00.437 you have the function MicroSeconds(), which does the same (but in Millionth of a Second, rather than Thousands of a Second).
dummerweise sagt MicroSeconds() nun nicht welche der beiden API verwendet wird.
die "alte" Version hat ein Overflow/Reset nach > 49 Tagen.
gruss by OHR
Jimmy
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2120
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 29 Mal
Danksagung erhalten: 70 Mal

Re: Zeit über Mitternacht

Beitrag von Werner_Bayern »

Servus Jimmy,

das interessante an getTickCount ist, es liefert die Anzahl Millisekunden seit dem Windows-Start. Damit kannst Du also feststellen, wielange der PC / Server schon nicht mehr gestartet wurde.
es grüßt

Werner

<when the music is over, turn off the lights!>
Antworten