Seite 1 von 4

Include - Quad-Timestamp

Verfasst: 06.08.2008 17:30
von STARGÅTE
Tachchen,

aus der Frage (Hier) heraus ob es irgendwo Datumsproceduren für Quads gibt habe ich hier mal was zusammen geschrieben:

Ein paar extra Proceduren fehlen noch, werden aber kommen :

Code: Alles auswählen



; Umrechungskonstanten

#MinuteSeconds = 60
#HourMinutes = 60
#DayHours = 24
#YearDays = 365

#HourSeconds = #HourMinutes*#MinuteSeconds
#DaySeconds = #DayHours*#HourSeconds

#StartYear = 1970



; Proceduren

Procedure DayOfYearQ(Time.q)
 Protected TempDays.q = Time / #DaySeconds
 Protected TempYear.q = TempDays / #YearDays
 ; Schaltjahre
 Protected SD = ((TempYear+1)/4)-((TempYear+69)/100)+((TempYear+369)/400)
 Protected TempDayOfYear = (TempDays - SD) % #YearDays +1
 Protected Year = (TempDays - SD) / #YearDays + #StartYear
 Protected AddDay
 If #YearDays-TempDayOfYear < SD
  If Not Year % 4   : AddDay + 1 : EndIf
  If Not Year % 100 : AddDay - 1 : EndIf
  If Not Year % 400 : AddDay + 1 : EndIf
 EndIf
 ProcedureReturn TempDayOfYear+AddDay
EndProcedure

Procedure DayOfWeekQ(Time.q)
 Protected TempDays.q = Time / #DaySeconds
 Protected DayOfWeek = (TempDays+4) % 7
 ProcedureReturn DayOfWeek
EndProcedure
   

Procedure YearQ(Time.q)
 Protected TempDays = Time / #DaySeconds
 Protected TempYear = TempDays / #YearDays
 Protected SD = ((TempYear+1)/4)-((TempYear+69)/100)+((TempYear+369)/400)
 Protected Year = (TempDays - SD) / #YearDays + #StartYear
 ProcedureReturn Year
EndProcedure

Procedure MonthQ(Time.q)
 Protected Year = YearQ(Time)
 Protected DayOfYear = DayOfYearQ(Time)
 Protected AddDay
 If DayOfYear > 31+28
  If Not Year % 4   : AddDay + 1 : EndIf
  If Not Year % 100 : AddDay - 1 : EndIf
  If Not Year % 400 : AddDay + 1 : EndIf
 EndIf
 Restore MonthDays
 Protected n
 For n = 1 To 12
  Read MonthDays
  If n = 2 : MonthDays+AddDay : EndIf
  If DayOfYear < MonthDays+1
   ProcedureReturn n
  EndIf
  DayOfYear - MonthDays
 Next 
EndProcedure

Procedure DayQ(Time.q)
 Protected Year = YearQ(Time)
 Protected DayOfYear = DayOfYearQ(Time)
 Protected AddDay
 If DayOfYear > 31+28
  If Not Year % 4   : AddDay + 1 : EndIf
  If Not Year % 100 : AddDay - 1 : EndIf
  If Not Year % 400 : AddDay + 1 : EndIf
 EndIf
 Restore MonthDays
 Protected n
 For n = 1 To 12
  Read MonthDays
  If n = 2 : MonthDays+AddDay : EndIf
  If DayOfYear < MonthDays+1
   ProcedureReturn DayOfYear
  EndIf
  DayOfYear - MonthDays
 Next 
EndProcedure

Procedure HourQ(Time.q)
 Protected Hour = (Time / #HourSeconds) % #DayHours
 ProcedureReturn Hour
EndProcedure

Procedure MinuteQ(Time.q)
 Protected Minute = (Time / #MinuteSeconds) % #HourMinutes
 ProcedureReturn Minute
EndProcedure

Procedure SecondQ(Time.q)
 Protected Second = (Time) % #MinuteSeconds 
 ProcedureReturn Second
EndProcedure



Procedure.q DateQ(Year,Month,Day,Hour,Minute,Second)
 Protected Time.q
 Protected TempYear = Year-#StartYear
 Time + TempYear*365*#DaySeconds
 Protected SD = ((TempYear+1)/4)-((TempYear+69)/100)+((TempYear+369)/400)
 Time + #DaySeconds*SD
 If Month > 2 :
  If Not Year % 4   : Time + #DaySeconds : EndIf
  If Not Year % 100 : Time - #DaySeconds : EndIf
  If Not Year % 400 : Time + #DaySeconds : EndIf
 EndIf
 Restore MonthDays
 Protected n
 For n = 1 To Month-1
  Read MonthDays
  Time + #DaySeconds*MonthDays
 Next 
 Time + (Day-1)*#DaySeconds
 Time + Hour*#HourSeconds
 Time + Minute*#MinuteSeconds
 Time + Second
 ProcedureReturn Time
EndProcedure



Procedure.s FormatDateQ(Maske$, Time.q)
 Maske$ = ReplaceString(Maske$, "%yyyy", StrQ(YearQ(Time)))
 Maske$ = ReplaceString(Maske$, "%yy", Right(StrQ(YearQ(Time)  ), 2)     )
 Maske$ = ReplaceString(Maske$, "%mm",  RSet(StrQ(MonthQ(Time) ), 2, "0"))
 Maske$ = ReplaceString(Maske$, "%dd",  RSet(StrQ(DayQ(Time)   ), 2, "0"))
 Maske$ = ReplaceString(Maske$, "%hh", RSet(StrQ(HourQ(Time)  ), 2, "0"))
 Maske$ = ReplaceString(Maske$, "%ii",  RSet(StrQ(MinuteQ(Time)), 2, "0"))
 Maske$ = ReplaceString(Maske$, "%ss",  RSet(StrQ(SecondQ(Time)), 2, "0"))
 ProcedureReturn Maske$
EndProcedure



DataSection
 MonthDays:
 Data.l 31,28,31,30,31,30,31,31,30,31,30,31
EndDataSection

Beispiel:

Code: Alles auswählen

Time = Date(2008,2,29,12,00,00) 
Debug "Long: "+Str(Time) 
TimeQ.q = DateQ(2008,2,29,12,00,00) 
Debug "Quad: "+StrQ(TimeQ) 
Debug "Long: "+FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", Time)
Debug "Quad: "+FormatDateQ("%dd.%mm.%yyyy %hh:%ii:%ss", Time)
TimeQ.q = DateQ(3333,3,3,3,33,33) 
Debug "NEU: "+StrQ(TimeQ) 
Debug "NEU: "+FormatDateQ("%dd.%mm.%yyyy %hh:%ii:%ss", TimeQ)
UPDATE 1.1 : 6.8.2008 17:42
DayOfWeekQ
DayOfYearQ

UPDATE 1.2 : 6.8.2008 18:00
Protected
FormatDateQ

Verfasst: 06.08.2008 18:36
von NicTheQuick
Hier noch ein kleiner Testcode für die Zuverlässigkeit des Stempels:

Code: Alles auswählen

refDate.q = 0
y.l = 1970
m.l = 1
d.l = 1
dy.l = 1
dw.l = 4
cerrors.l = 0
Repeat
  error.s = ""
  date.q = DateQ(y, m, d, 0, 0, 0)
  If date <> refDate : error + "ref" : EndIf
  If DayOfYearQ(date) <> dy : error + " dy" : EndIf
  If DayOfWeekQ(date) <> dw : error + " dw" : EndIf
  If YearQ(date) <> y : error + " y" : EndIf
  If MonthQ(date) <> m : error + " m" : EndIf
  If DayQ(date) <> d : error + " d" : EndIf
  
  If m = 12 And d = 31 ;letzter Tag im Jahr
    dy = 1
    m = 1
    d = 1
    y + 1
  Else
    dy + 1
    Select m
      Case 1, 3, 5, 7, 8, 10, 12 : md.l = 31
      Case 4, 6, 9, 11 : md.l = 30
      Case 2 : If ((Not (y % 4)) And (y % 100)) Or Not (y % 400) : md = 29 : Else : md = 28 : EndIf
    EndSelect
    If d = md ;letzter Tag im Monat
      m + 1
      d = 1
    Else
      d + 1
    EndIf
  EndIf
  dw = (dw + 1) % 7
  refDate + 86400
  
  If error
    Debug "Errors: " + error + " - " + Str(d) + "." + Str(m) + "." + Str(y)
    cerrors + 1
  EndIf
Until y = 4000
Debug "Errors: " + Str(cerrors)
Er läuft ab dem 1.1.1970 tagweise vorwärts und überprüft, ob der
Zeitstempel richtig ist, indem er ihn mit einem Referenzstempel
vergleicht, der pro Tag um 84600 erhöht wird.
Dabei wird deutlich, dass das Ergebnis ab dem 2.1.3476 nicht mehr
stimmt. Die Abkürzungen der Fehlermeldungen lassen sich leicht dem
Code entnehmen.

///Edit:
84600 durch 86400 ersetzt. <)

Verfasst: 06.08.2008 18:54
von STARGÅTE
Der/Die Fehler treten ab 3476 auf, weil es dort beides so viele Schalttage gab, dass wieder ein ganzes Jahr gefüllt wurde.

Das problem liegt jedoch auf "beiden" Seiten, sowohl bei DateQ() als auch bei den rück Proceduren.

Das Problem wird demnächst behoben!

Re: Include - Quad-Timestamp

Verfasst: 06.08.2008 21:41
von AND51
STARGÅTE hat geschrieben:

Code: Alles auswählen

Procedure HourQ(Time.q)
 Protected Hour = (Time / #HourSeconds) % #DayHours
 ProcedureReturn Hour
EndProcedure
Warum aus sowas nicht Macros machen?

Man kann mit Makros die PB-Nativen Proceduren überschreiben. Wenn dein Macro also Hour() heißt, wird das Makro aufgerufen, nicht die PB-Prozedur.
Du solltest außerdem Makros verwenden, wenn du sowieso nur Einzeilerprozeduren hast.

Verfasst: 06.08.2008 21:51
von NicTheQuick
Man muss ja nicht aus allem Makros machen.
Ich find's so okay. :allright:

Verfasst: 06.08.2008 23:02
von AND51
NicTheQuick hat geschrieben:Man muss ja nicht aus allem Makros machen.
Man muss auch nicht jeden Zehner vom Boden aufheben... :wink:
Und wenn er sich dir (wie hier der Performancegewinn) noch so aufdrängt.

Verfasst: 06.08.2008 23:07
von Kaeru Gaman
und man muss nicht bei jedem furz recht haben wollen.

Verfasst: 06.08.2008 23:10
von Andreas_S
Was ist so schlimm daran?

Man soll doch auch noch die 32 Bit Methoden verwenden können...
Viele DLLs usw. haben auch hinten die Abkürzung vom Datentyp dran.
Ist auch besser so... so kann man nähmlich auch Performance sparen:
Wenns höher als das mögliche 32 Bit Datum wird, dann verwendest du 64 Bit.

Verfasst: 06.08.2008 23:13
von AND51
Kaeru Gaman hat geschrieben:und man muss nicht bei jedem furz recht haben wollen.
Wo hab ich denn hier auf mein Recht beharrt? :wink:

Verfasst: 06.08.2008 23:53
von Helle
@Nic: 84600? 86400! :mrgreen:

Gruß
Helle