Date64 - Unixtime 64bit
Re: Date64 - Unixtime 64bit
Hallo NicTheQuick,
bezüglich der langsamen While-Schleifen hast du mich ja schon in einem anderem Thread hingewiesen. Ja, sie sind langsam. Als ich den Code programmiert habe, war es so verständlicher für mich und optimieren kann man später noch, dachte ich. Nun hatte ich genug Zeit, die geplanten Änderungen umzusetzen.
Warum ich bei der Korrektur der negativen Werte "59" statt "60" geschrieben habe, lag daran, dass bei einer älteren Code-Version sonst falsche Werte zurückgegeben wurden. Die aktuelle Code-Version läuft nun anscheinend fehlerfrei mit "60".
Vielen Dank für deine Hinweise!
Letzter Code wurde auf den aktuellen Stand gebracht.
bezüglich der langsamen While-Schleifen hast du mich ja schon in einem anderem Thread hingewiesen. Ja, sie sind langsam. Als ich den Code programmiert habe, war es so verständlicher für mich und optimieren kann man später noch, dachte ich. Nun hatte ich genug Zeit, die geplanten Änderungen umzusetzen.
Warum ich bei der Korrektur der negativen Werte "59" statt "60" geschrieben habe, lag daran, dass bei einer älteren Code-Version sonst falsche Werte zurückgegeben wurden. Die aktuelle Code-Version läuft nun anscheinend fehlerfrei mit "60".
Vielen Dank für deine Hinweise!
Letzter Code wurde auf den aktuellen Stand gebracht.
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
So, ich habe mich nochmal an den Code ran gemacht.
Änderungen (18.03.2016):
Änderungen (18.03.2016):
- AllocateMemory() entfernt. Normale Variable reicht.
- mktime() durch timegm() ersetzt
- Procedure "LocalDateAsUTC()" entfernt, weil alle Funktionen UTC zurückgeben
- Test-Code prüft nun alle Rückgaben selbstständig
- Kommentar zur maximalen Grenze bei Windows angepasst
- Code läuft nun auch unter Linux fehlerfrei (getestet unter Xubuntu_x86, LinuxMint_x64 und WindowsXP)
- Doppelter Code per Macros reduziert (Code-Zeilen-Einsparung: 140 Zeilen)
Code: Alles auswählen
DeclareModule Date64
Declare.i IsLeapYear(Year.i)
Declare.i DaysInMonth(Year.i, Month.i)
Declare.q Date64(Year.i=-1, Month.i=1, Day.i=1, Hour.i=0, Minute.i=0, Second.i=0)
Declare.i Year64(Date.q)
Declare.i Month64(Date.q)
Declare.i Day64(Date.q)
Declare.i Hour64(Date.q)
Declare.i Minute64(Date.q)
Declare.i Second64(Date.q)
Declare.i DayOfWeek64(Date.q)
Declare.i DayOfYear64(Date.q)
Declare.q AddDate64(Date.q, Type.i, Value.i)
Declare.s FormatDate64(Mask$, Date.q)
Declare.q ParseDate64(Mask$, Date$)
EndDeclareModule
Module Date64
EnableExplicit
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS And #PB_Compiler_Processor = #PB_Processor_x86
CompilerError "32-Bit not supported on MacOS"
CompilerEndIf
CompilerIf #PB_Compiler_OS <> #PB_OS_Windows
ImportC ""
gmtime_r_(*timep, *result) As "gmtime_r"
EndImport
CompilerEndIf
; == Windows ==
; >> Minimum: 01.01.1601 00:00:00
; >> Maximum: 31.12.9999 23:59:59
; == Linux ==
; 32-Bit:
; >> Minimum: 01.01.1902 00:00:00
; >> Maximum: 18.01.2038 23:59:59
; 64-Bit:
; >> Minimum: 01.01.0000 00:00:00
; >> Maximum: 31.12.9999 23:59:59
; == MacOS ==
; wie bei Linux?
#SecondsInOneHour = 60 * 60
#SecondsInOneDay = #SecondsInOneHour * 24
#HundredNanosecondsInOneSecond = 10000000
#HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
;{ Struktur-Definition für "tm"
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
If Not Defined(tm, #PB_Structure)
Structure tm Align #PB_Structure_AlignC
tm_sec.l ; 0 bis 59 oder bis 60 bei Schaltsekunde
tm_min.l ; 0 bis 59
tm_hour.l ; 0 bis 23
tm_mday.l ; Tag des Monats: 1 bis 31
tm_mon.l ; Monat: 0 bis 11 (Monate seit Januar)
tm_year.l ; Anzahl der Jahre seit dem Jahr 1900
tm_wday.l ; Wochentag: 0 bis 6, 0 = Sonntag
tm_yday.l ; Tage seit Jahresanfang: 0 bis 365 (365 ist also 366, da nach 1. Januar gezählt wird)
tm_isdst.l ; Ist Sommerzeit? tm_isdst > 0 = Ja
; tm_isdst = 0 = Nein
; tm_isdst < 0 = Unbekannt
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone ; Abkürzungsname der Zeitzone
CompilerElse
tm_zone.l ; Platzhalter
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone64 ; Abkürzungsname der Zeitzone
CompilerEndIf
EndStructure
EndIf
CompilerCase #PB_OS_MacOS
If Not Defined(tm, #PB_Structure)
Structure tm Align #PB_Structure_AlignC
tm_sec.l ; 0 bis 59 oder bis 60 bei Schaltsekunde
tm_min.l ; 0 bis 59
tm_hour.l ; 0 bis 23
tm_mday.l ; Tag des Monats: 1 bis 31
tm_mon.l ; Monat: 0 bis 11 (Monate seit Januar)
tm_year.l ; Anzahl der Jahre seit dem Jahr 1900
tm_wday.l ; Wochentag: 0 bis 6, 0 = Sonntag
tm_yday.l ; Tage seit Jahresanfang: 0 bis 365 (365 ist also 366, da nach 1. Januar gezählt wird)
tm_isdst.l ; Ist Sommerzeit? tm_isdst > 0 = Ja
; tm_isdst = 0 = Nein
; tm_isdst < 0 = Unbekannt
tm_zone.l ; Abkürzungsname der Zeitzone (Auch bei 64bit ein 32bit Wert)
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone64 ; Abkürzungsname der Zeitzone
EndStructure
EndIf
CompilerEndSelect
;}
Procedure.i IsLeapYear(Year.i)
If Year < 1600
; vor dem Jahr 1600 sind alle Jahre Schaltjahre, die durch 4 restlos teilbar sind
ProcedureReturn Bool(Year % 4 = 0)
Else
; ab dem Jahr 1600 sind alle Jahre Schaltjahre, die folgende Bedingungen erfüllen:
; => restlos durch 4 teilbar, jedoch nicht restlos durch 100 teilbar
; => restlos durch 400 teilbar
ProcedureReturn Bool((Year % 4 = 0 And Year % 100 <> 0) Or Year % 400 = 0)
EndIf
EndProcedure
Procedure.i DaysInMonth(Year.i, Month.i)
While Month > 12
Year + 1
Month - 12
Wend
While Month < 0
Year - 1
Month + 13
Wend
If Month = 0
Month = 1
EndIf
Select Month
Case 1, 3, 5, 7, 8, 10, 12: ProcedureReturn 31
Case 4, 6, 9, 11: ProcedureReturn 30
Case 2: ProcedureReturn 28 + IsLeapYear(Year) ; Februar hat im Schaltjahr ein Tag mehr
EndSelect
EndProcedure
Procedure.q Date64(Year.i=-1, Month.i=1, Day.i=1, Hour.i=0, Minute.i=0, Second.i=0)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Protected.SYSTEMTIME st
Protected.FILETIME ft, ft2
Protected.i DaysInMonth
If Year > -1 ; Gültiges Datum
; Angaben evtl. korrigieren
Minute + Second/60
Second % 60
If Second < 0
Minute - 1
Second + 60
EndIf
Hour + Minute/60
Minute % 60
If Minute < 0
Hour - 1
Minute + 60
EndIf
Day + Hour/24
Hour % 24
If Hour < 0
Day - 1
Hour + 24
EndIf
While Month > 12
Year + 1
Month - 12
Wend
If Month = 0
Month = 1
EndIf
DaysInMonth = DaysInMonth(Year, Month)
While Day > DaysInMonth
Day - DaysInMonth
Month + 1
If Month > 12
Year + 1
Month - 12
EndIf
DaysInMonth = DaysInMonth(Year, Month)
Wend
If Day < 0
Month - 1
If Month = 0
Year - 1
Month = 12
EndIf
Day + DaysInMonth(Year, Month)
EndIf
st\wYear = Year
st\wMonth = Month
st\wDay = Day
st\wHour = Hour
st\wMinute = Minute
st\wSecond = Second
; Konvertiert Systemzeit (UTC) zu Dateizeit (UTC)
SystemTimeToFileTime_(@st, @ft)
; UTC-Zeit in Sekunden umrechnen
ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
Else
; Kein gültiges Datum. Lokale Systemzeit wird ermittelt
GetLocalTime_(@st)
SystemTimeToFileTime_(@st, @ft) ; "st" wird als UTC gelesen und zu Dateizeit konvertiert
; UTC-Zeit in Sekunden umrechnen
ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
EndIf
CompilerElse ; Linux oder Mac
Protected.tm tm
Protected.q time
If Year > -1 ; Gültiges Datum
tm\tm_year = Year - 1900 ; Jahre ab 1900
tm\tm_mon = Month - 1 ; Monate ab Januar
tm\tm_mday = Day
tm\tm_hour = Hour
tm\tm_min = Minute
tm\tm_sec = Second
; mktime korrigiert die Angaben selber und liefert bereits Sekunden
time = timegm_(@tm) ; Konvertiert UTC-Zeit zu UTC-Zeit
ProcedureReturn time ; UTC-Zeit in Sekunden
Else
; Kein gültiges Datum. Systemzeit wird ermittelt
time = time_(0)
If localtime_r_(@time, @tm) <> 0
time = timegm_(@tm)
EndIf
ProcedureReturn time ; UTC-Zeit in Sekunden
EndIf
CompilerEndIf
EndProcedure
Macro Windows_ReturnDatePart(Type)
Protected.SYSTEMTIME st
Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
FileTimeToSystemTime_(@Date, @st)
ProcedureReturn st\Type
EndMacro
Macro LinuxMac_ReturnDatePart(Type, ReturnCode)
Protected.tm tm
Protected.i Value
If gmtime_r_(@Date, @tm) <> 0 ; Per Memory ist es thread-sicher
Value = tm\Type
ProcedureReturn ReturnCode
EndIf
EndMacro
Procedure.i Year64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wYear)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_year, Value + 1900)
CompilerEndIf
EndProcedure
Procedure.i Month64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wMonth)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_mon, Value + 1)
CompilerEndIf
EndProcedure
Procedure.i Day64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wDay)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_mday, Value)
CompilerEndIf
EndProcedure
Procedure.i Hour64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wHour)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_hour, Value)
CompilerEndIf
EndProcedure
Procedure.i Minute64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wMinute)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_min, Value)
CompilerEndIf
EndProcedure
Procedure.i Second64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wSecond)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_sec, Value)
CompilerEndIf
EndProcedure
Procedure.i DayOfWeek64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wDayOfWeek)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_wday, Value)
CompilerEndIf
EndProcedure
Procedure.i DayOfYear64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Protected.q TempDate
TempDate = Date64(Year64(Date))
ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_yday, Value + 1)
CompilerEndIf
EndProcedure
Procedure.q AddDate64(Date.q, Type.i, Value.i)
Protected.i Day, Month, Year
Select Type
Case #PB_Date_Year: ProcedureReturn Date64(Year64(Date) + Value, Month64(Date), Day64(Date), Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Month
Day = Day64(Date)
Month = Month64(Date) + Value
Year = Year64(Date)
If Day > DaysInMonth(Year, Month)
; mktime korrigiert das zwar auch, wendet dabei aber eine andere Methode als PB-AddDate an:
; >> mktime: 31.03.2004 => 1 Monat später => 01.05.2004
; >> PB-AddDate: 31.03.2004 => 1 Monat später => 30.04.2004
; Setzte Tag auf das Maximum des neuen Monats
Day = DaysInMonth(Year, Month)
EndIf
ProcedureReturn Date64(Year64(Date), Month, Day, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Week: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date) + Value * 7, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Day: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date) + Value, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Hour: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date) + Value, Minute64(Date), Second64(Date))
Case #PB_Date_Minute: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date), Minute64(Date) + Value, Second64(Date))
Case #PB_Date_Second: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date), Minute64(Date), Second64(Date) + Value)
EndSelect
EndProcedure
Procedure.s FormatDate64(Mask$, Date.q)
Protected Result$
Result$ = ReplaceString(Mask$, "%yyyy", RSet(Str(Year64(Date)), 4, "0"))
Result$ = ReplaceString(Result$, "%yy", RSet(Right(Str(Year64(Date)), 2), 2, "0"))
Result$ = ReplaceString(Result$, "%mm", RSet(Str(Month64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%dd", RSet(Str(Day64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%hh", RSet(Str(Hour64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%ii", RSet(Str(Minute64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%ss", RSet(Str(Second64(Date)), 2, "0"))
ProcedureReturn Result$
EndProcedure
Macro ReadMaskVariable(MaskVariable, ReturnVariable)
If Mid(Mask$, i, 3) = MaskVariable
IsVariableFound = #True
ReturnVariable = Val(Mid(Date$, DatePos, 2))
DatePos + 2 ; Die 2 Nummern der Zahl überspringen
i + 2 ; Die 3 Zeichen der Variable überspringen
Continue
EndIf
EndMacro
Procedure.q ParseDate64(Mask$, Date$)
Protected.i i, DatePos = 1, IsVariableFound, Year, Month = 1, Day = 1, Hour, Minute, Second
Protected MaskChar$, DateChar$
For i = 1 To Len(Mask$)
MaskChar$ = Mid(Mask$, i, 1)
DateChar$ = Mid(Date$, DatePos, 1)
If MaskChar$ <> DateChar$
If MaskChar$ = "%" ; Vielleicht eine Variable?
If Mid(Mask$, i, 5) = "%yyyy"
IsVariableFound = #True
Year = Val(Mid(Date$, DatePos, 4))
DatePos + 4 ; Die 4 Nummern der Jahreszahl überspringen
i + 4 ; Die 5 Zeichen der Variable "%yyyy" überspringen
Continue
ElseIf Mid(Mask$, i, 3) = "%yy"
IsVariableFound = #True
Year = Val(Mid(Date$, DatePos, 2))
DatePos + 2 ; Die 2 Nummern der Jahreszahl überspringen
i + 2 ; Die 3 Zeichen der Variable "%yy" überspringen
Continue
EndIf
ReadMaskVariable("%mm", Month)
ReadMaskVariable("%dd", Day)
ReadMaskVariable("%hh", Hour)
ReadMaskVariable("%ii", Minute)
ReadMaskVariable("%ss", Second)
If Not IsVariableFound
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndIf
DatePos + 1
Next
ProcedureReturn Date64(Year, Month, Day, Hour, Minute, Second)
EndProcedure
EndModule
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
;-Test
UseModule Date64
Define.i Year, Month, Day, Hour, Minute, Second, Result, Result64
Define.q Date, Date64
Define Date$, Date64$, Result64$
Debug "Kleiner Kompatibilitäts-Test - Fehler:"
For Year = 1970 To 2037
For Month = 1 To 12
For Day = 1 To 28
For Hour = 0 To 23
;For Minute = 0 To 59
;For Second = 0 To 59
Date = Date(Year, Month, Day, Hour, Minute, Second)
Date64 = Date64(Year, Month, Day, Hour, Minute, Second)
If Date <> Date64
Debug "Date() <> Date64()"
Debug Date
Debug Date64
Debug ""
EndIf
Date$ = FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date)
Date64$ = FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64)
If Date$ <> Date64$
Debug "FormatDate() <> FormatDate64()"
Debug Date$
Debug Date64$
Debug ""
EndIf
Result = ParseDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date$)
Result64 = ParseDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64$)
If Result <> Result64
Debug "ParseDate() <> ParseDate64()"
Debug Result
Debug Result64
Debug ""
EndIf
Result = DayOfWeek(Date)
Result64 = DayOfWeek64(Date64)
If Result <> Result64
Debug "DayOfWeek() <> DayOfWeek64()"
Debug Result
Debug Result64
Debug ""
EndIf
Result = DayOfYear(Date)
Result64 = DayOfYear64(Date64)
If Result <> Result64
Debug "DayOfYear() <> DayOfYear64()"
Debug Result
Debug Result64
Debug ""
EndIf
;Next Second
;Next Minute
Next Hour
Next Day
Next Month
Next Year
If Date() <> Date64()
Debug "Date() <> Date64()"
EndIf
Macro AddDateTest(Type, TypeS)
If AddDate(Date(), #PB_Date_#Type, 1) <> AddDate64(Date64(), #PB_Date_#Type, 1)
Debug "AddDate(Date(), #PB_Date_" + TypeS + ", 1) <> AddDate64(Date64(), #PB_Date_" + TypeS + ", 1)"
EndIf
If AddDate(Date(), #PB_Date_#Type, -1) <> AddDate64(Date64(), #PB_Date_#Type, -1)
Debug "AddDate(Date(), #PB_Date_" + TypeS + ", -1) <> AddDate64(Date64(), #PB_Date_" + TypeS + ", -1)"
EndIf
EndMacro
AddDateTest(Year, "Year")
AddDateTest(Month, "Month")
AddDateTest(Day, "Day")
AddDateTest(Hour, "Hour")
AddDateTest(Minute, "Minute")
AddDateTest(Second, "Second")
AddDateTest(Week, "Week")
Macro TestDateLimits(Minimum, Maximum)
Date64$ = Minimum
Date64 = ParseDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64$)
Result64$ = FormatDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64)
If Date64$ <> Result64$
Debug "Minimum stimmt nicht:"
Debug "> Erwartet wurde: " + Date64$
Debug "> Zurückgegeben wurde: " + Result64$
EndIf
Date64$ = Maximum
Date64 = ParseDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64$)
Result64$ = FormatDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64)
If Date64$ <> Result64$
Debug "Maximum stimmt nicht:"
Debug "> Erwartet wurde: " + Date64$
Debug "> Zurückgegeben wurde: " + Result64$
EndIf
EndMacro
Debug "---------------------"
Debug "Test der Datum-Grenzen - Fehler:"
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
TestDateLimits("01.01.1601 00:00:00", "31.12.9999 23:59:59")
CompilerElse ; Linux oder Mac
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
TestDateLimits("01.01.1902 00:00:00", "18.01.2038 23:59:59")
CompilerElse
TestDateLimits("01.01.0000 00:00:00", "31.12.9999 23:59:59")
CompilerEndIf
CompilerEndIf
Debug "---------------------"
Debug "Test wurde durchgeführt"
CompilerEndIf
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
Läuft nicht unter Mac
Undefined symbols for architecture x86_64:
"gmtime_r", referenced from:
_Procedure16.ClearLoop in purebasic.o
_Procedure8.ClearLoop in purebasic.o
_Procedure10.ClearLoop in purebasic.o
_Procedure12.ClearLoop in purebasic.o
_Procedure18.ClearLoop in purebasic.o
...
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Re: Date64 - Unixtime 64bit
gmtime_r() müsste es aber eigentlich unter Mac geben:
https://developer.apple.com/search/?q=gmtime_r
Vielleicht hilft das:
https://developer.apple.com/search/?q=gmtime_r
Vielleicht hilft das:
Code: Alles auswählen
ImportC "-lc"
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
Code im CodeArchiv unter Time_and_Date/Date64[WIN,LIN].pbi aktualisiert.
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
Hallo!
Ich möchte doch darauf hinweisen, daß das Modul so nicht ohne weiteres
grundsätzlich einsetzbar ist.
So ist zum Beispiel im Programm definiert:Dieser Wert ist nur teilweise gültig.
Es wird nicht berücksichtigt, daß in großen Teilen Deutschlands/Europas/der Welt
der Gregorianische Kalender zu unterschiedlichen Zeiten umgesetzt wurde.
Es muß somit immer der Ort, für den eine Zeitrechnung durcheführt werden
soll, berücksichtigt werden.
Für den Zeitraum 1601 bis 1700 fehlen in vielen Gebieten die Tage 19.02 bis
28.02.1700, weil die Umstellung erst da erfolgte.
In der VR China erfolgte die Umstellung erst 1949, im KR Griechenland erst 1923,
in der UdSSR erst 1922, ... usw.
So gesehen ist diese Routine so nicht brauchbar, da sie fehlerhafte Ergebnisse
liefern kann.
Es müßte also ein gebietsspezifischer Korrekturwert eingeführt werden.
Ich möchte doch darauf hinweisen, daß das Modul so nicht ohne weiteres
grundsätzlich einsetzbar ist.
So ist zum Beispiel im Programm definiert:
Code: Alles auswählen
#HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
Es wird nicht berücksichtigt, daß in großen Teilen Deutschlands/Europas/der Welt
der Gregorianische Kalender zu unterschiedlichen Zeiten umgesetzt wurde.
Es muß somit immer der Ort, für den eine Zeitrechnung durcheführt werden
soll, berücksichtigt werden.
Für den Zeitraum 1601 bis 1700 fehlen in vielen Gebieten die Tage 19.02 bis
28.02.1700, weil die Umstellung erst da erfolgte.
In der VR China erfolgte die Umstellung erst 1949, im KR Griechenland erst 1923,
in der UdSSR erst 1922, ... usw.
So gesehen ist diese Routine so nicht brauchbar, da sie fehlerhafte Ergebnisse
liefern kann.
Es müßte also ein gebietsspezifischer Korrekturwert eingeführt werden.
Re: Date64 - Unixtime 64bit
Hallo Lord,
vielen Dank für den Hinweis.
Sobald ich genug Zeit habe, werde ich mir das mal ansehen und versuchen, es im Code umzusetzen.
Auf die Schnelle habe ich folgende Seite für die unterschiedlichen Einführungszeiten gefunden:
http://www.kalenderlexikon.de/anzeigen. ... gGregorKal
vielen Dank für den Hinweis.
Sobald ich genug Zeit habe, werde ich mir das mal ansehen und versuchen, es im Code umzusetzen.
Auf die Schnelle habe ich folgende Seite für die unterschiedlichen Einführungszeiten gefunden:
http://www.kalenderlexikon.de/anzeigen. ... gGregorKal
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
Ich habe nun "gmtime_r" wieder zu "gmtime" geändert, um die Unterstützung für MacOS wiederherzustellen.
Der minimale Datumsbereich bei MacOS wurde ebenfalls korrigiert.
https://github.com/SicroAtGit/PureBasic ... Mac%5D.pbi
Edit: Warnhinweis für Datumsberechnungen vor dem gregorianischen Kalender zum Code hinzugefügt
Der minimale Datumsbereich bei MacOS wurde ebenfalls korrigiert.
https://github.com/SicroAtGit/PureBasic ... Mac%5D.pbi
Code: Alles auswählen
; Description: Support for enlarged date range (64 bit unix timestamp)
; Author: mk-soft (Windows); Sicro (Windows, Linux, Mac; converted to module; and more); ts-soft (fixed structures for Windows, Linux and Mac)
; Date: 2017-07-30
; OS: Windows, Linux, Mac
; English-Forum:
; French-Forum:
; German-Forum: http://www.purebasic.fr/german/viewtopic.php?p=335727#p335727
; -----------------------------------------------------------------------------
DeclareModule Date64
Declare.i IsLeapYear64(Year.i)
Declare.i DaysInMonth64(Year.i, Month.i)
Declare.q Date64(Year.i=-1, Month.i=1, Day.i=1, Hour.i=0, Minute.i=0, Second.i=0)
Declare.i Year64(Date.q)
Declare.i Month64(Date.q)
Declare.i Day64(Date.q)
Declare.i Hour64(Date.q)
Declare.i Minute64(Date.q)
Declare.i Second64(Date.q)
Declare.i DayOfWeek64(Date.q)
Declare.i DayOfYear64(Date.q)
Declare.q AddDate64(Date.q, Type.i, Value.i)
Declare.s FormatDate64(Mask$, Date.q)
Declare.q ParseDate64(Mask$, Date$)
EndDeclareModule
Module Date64
EnableExplicit
CompilerIf #PB_Compiler_OS = #PB_OS_MacOS And #PB_Compiler_Processor = #PB_Processor_x86
CompilerError "32-Bit not supported on MacOS"
CompilerEndIf
; !!! >>> WARNUNG <<< !!!
; Der gregorianische Kalender wurde in vielen Gebieten zu unterschiedlichen Zeiten eingeführt.
; Dieses Modul verwendet die API-Datumsfunktionen des Betriebssystems und diese haben eine
; vereinheitlichte Einführungszeit einprogrammiert, wodurch Datumsberechnungen vor Einführung
; des gregorianischen Kalenders meistens falsche Ergebnisse liefern.
; == Windows ==
; >> Minimum: 01.01.1601 00:00:00
; >> Maximum: 31.12.9999 23:59:59
; == Linux ==
; 32-Bit:
; >> Minimum: 01.01.1902 00:00:00
; >> Maximum: 18.01.2038 23:59:59
; 64-Bit:
; >> Minimum: 01.01.0000 00:00:00
; >> Maximum: 31.12.9999 23:59:59
; == MacOS ==
; >> Minimum: 31.12.1969 23:59:59
; >> Maximum: 31.12.9999 23:59:59
#SecondsInOneHour = 60 * 60
#SecondsInOneDay = #SecondsInOneHour * 24
#HundredNanosecondsInOneSecond = 10000000
#HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
;{ Struktur-Definition für "tm"
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Linux
If Not Defined(tm, #PB_Structure)
Structure tm Align #PB_Structure_AlignC
tm_sec.l ; 0 bis 59 oder bis 60 bei Schaltsekunde
tm_min.l ; 0 bis 59
tm_hour.l ; 0 bis 23
tm_mday.l ; Tag des Monats: 1 bis 31
tm_mon.l ; Monat: 0 bis 11 (Monate seit Januar)
tm_year.l ; Anzahl der Jahre seit dem Jahr 1900
tm_wday.l ; Wochentag: 0 bis 6, 0 = Sonntag
tm_yday.l ; Tage seit Jahresanfang: 0 bis 365 (365 ist also 366, da nach 1. Januar gezählt wird)
tm_isdst.l ; Ist Sommerzeit? tm_isdst > 0 = Ja
; tm_isdst = 0 = Nein
; tm_isdst < 0 = Unbekannt
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone ; Abkürzungsname der Zeitzone
CompilerElse
tm_zone.l ; Platzhalter
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone64 ; Abkürzungsname der Zeitzone
CompilerEndIf
EndStructure
EndIf
CompilerCase #PB_OS_MacOS
If Not Defined(tm, #PB_Structure)
Structure tm Align #PB_Structure_AlignC
tm_sec.l ; 0 bis 59 oder bis 60 bei Schaltsekunde
tm_min.l ; 0 bis 59
tm_hour.l ; 0 bis 23
tm_mday.l ; Tag des Monats: 1 bis 31
tm_mon.l ; Monat: 0 bis 11 (Monate seit Januar)
tm_year.l ; Anzahl der Jahre seit dem Jahr 1900
tm_wday.l ; Wochentag: 0 bis 6, 0 = Sonntag
tm_yday.l ; Tage seit Jahresanfang: 0 bis 365 (365 ist also 366, da nach 1. Januar gezählt wird)
tm_isdst.l ; Ist Sommerzeit? tm_isdst > 0 = Ja
; tm_isdst = 0 = Nein
; tm_isdst < 0 = Unbekannt
tm_zone.l ; Abkürzungsname der Zeitzone (Auch bei 64bit ein 32bit Wert)
tm_gmtoff.l ; Offset von UTC in Sekunden
*tm_zone64 ; Abkürzungsname der Zeitzone
EndStructure
EndIf
CompilerEndSelect
;}
Procedure.i IsLeapYear64(Year.i)
If Year < 1600
; vor dem Jahr 1600 sind alle Jahre Schaltjahre, die durch 4 restlos teilbar sind
ProcedureReturn Bool(Year % 4 = 0)
Else
; ab dem Jahr 1600 sind alle Jahre Schaltjahre, die folgende Bedingungen erfüllen:
; => restlos durch 4 teilbar, jedoch nicht restlos durch 100 teilbar
; => restlos durch 400 teilbar
ProcedureReturn Bool((Year % 4 = 0 And Year % 100 <> 0) Or Year % 400 = 0)
EndIf
EndProcedure
Procedure.i DaysInMonth64(Year.i, Month.i)
While Month > 12
Year + 1
Month - 12
Wend
While Month < 0
Year - 1
Month + 13
Wend
If Month = 0
Month = 1
EndIf
Select Month
Case 1, 3, 5, 7, 8, 10, 12: ProcedureReturn 31
Case 4, 6, 9, 11: ProcedureReturn 30
Case 2: ProcedureReturn 28 + IsLeapYear64(Year) ; Februar hat im Schaltjahr ein Tag mehr
EndSelect
EndProcedure
Procedure.q Date64(Year.i=-1, Month.i=1, Day.i=1, Hour.i=0, Minute.i=0, Second.i=0)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Protected.SYSTEMTIME st
Protected.FILETIME ft, ft2
Protected.i DaysInMonth
If Year > -1 ; Gültiges Datum
; Angaben evtl. korrigieren
Minute + Second/60
Second % 60
If Second < 0
Minute - 1
Second + 60
EndIf
Hour + Minute/60
Minute % 60
If Minute < 0
Hour - 1
Minute + 60
EndIf
Day + Hour/24
Hour % 24
If Hour < 0
Day - 1
Hour + 24
EndIf
While Month > 12
Year + 1
Month - 12
Wend
If Month = 0
Month = 1
EndIf
DaysInMonth = DaysInMonth64(Year, Month)
While Day > DaysInMonth
Day - DaysInMonth
Month + 1
If Month > 12
Year + 1
Month - 12
EndIf
DaysInMonth = DaysInMonth64(Year, Month)
Wend
If Day < 0
Month - 1
If Month = 0
Year - 1
Month = 12
EndIf
Day + DaysInMonth64(Year, Month)
EndIf
st\wYear = Year
st\wMonth = Month
st\wDay = Day
st\wHour = Hour
st\wMinute = Minute
st\wSecond = Second
; Konvertiert Systemzeit (UTC) zu Dateizeit (UTC)
SystemTimeToFileTime_(@st, @ft)
; UTC-Zeit in Sekunden umrechnen
ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
Else
; Kein gültiges Datum. Lokale Systemzeit wird ermittelt
GetLocalTime_(@st)
SystemTimeToFileTime_(@st, @ft) ; "st" wird als UTC gelesen und zu Dateizeit konvertiert
; UTC-Zeit in Sekunden umrechnen
ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
EndIf
CompilerElse ; Linux oder Mac
Protected.tm tm
Protected.q time
If Year > -1 ; Gültiges Datum
tm\tm_year = Year - 1900 ; Jahre ab 1900
tm\tm_mon = Month - 1 ; Monate ab Januar
tm\tm_mday = Day
tm\tm_hour = Hour
tm\tm_min = Minute
tm\tm_sec = Second
; mktime korrigiert die Angaben selber und liefert bereits Sekunden
time = timegm_(@tm) ; Konvertiert UTC-Zeit zu UTC-Zeit
ProcedureReturn time ; UTC-Zeit in Sekunden
Else
; Kein gültiges Datum. Systemzeit wird ermittelt
time = time_(0)
If localtime_r_(@time, @tm) <> 0
time = timegm_(@tm)
EndIf
ProcedureReturn time ; UTC-Zeit in Sekunden
EndIf
CompilerEndIf
EndProcedure
Macro Windows_ReturnDatePart(Type)
Protected.SYSTEMTIME st
Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
FileTimeToSystemTime_(@Date, @st)
ProcedureReturn st\Type
EndMacro
Macro LinuxMac_ReturnDatePart(Type, ReturnCode)
Protected.tm *tm
Protected.i Value
*tm = gmtime_(@Date)
If *tm
Value = *tm\Type
EndIf
ProcedureReturn ReturnCode
EndMacro
Procedure.i Year64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wYear)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_year, Value + 1900)
CompilerEndIf
EndProcedure
Procedure.i Month64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wMonth)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_mon, Value + 1)
CompilerEndIf
EndProcedure
Procedure.i Day64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wDay)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_mday, Value)
CompilerEndIf
EndProcedure
Procedure.i Hour64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wHour)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_hour, Value)
CompilerEndIf
EndProcedure
Procedure.i Minute64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wMinute)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_min, Value)
CompilerEndIf
EndProcedure
Procedure.i Second64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wSecond)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_sec, Value)
CompilerEndIf
EndProcedure
Procedure.i DayOfWeek64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Windows_ReturnDatePart(wDayOfWeek)
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_wday, Value)
CompilerEndIf
EndProcedure
Procedure.i DayOfYear64(Date.q)
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
Protected.q TempDate
TempDate = Date64(Year64(Date))
ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1
CompilerElse ; Linux oder Mac
LinuxMac_ReturnDatePart(tm_yday, Value + 1)
CompilerEndIf
EndProcedure
Procedure.q AddDate64(Date.q, Type.i, Value.i)
Protected.i Day, Month, Year
Select Type
Case #PB_Date_Year: ProcedureReturn Date64(Year64(Date) + Value, Month64(Date), Day64(Date), Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Month
Day = Day64(Date)
Month = Month64(Date) + Value
Year = Year64(Date)
If Day > DaysInMonth64(Year, Month)
; mktime korrigiert das zwar auch, wendet dabei aber eine andere Methode als PB-AddDate an:
; >> mktime: 31.03.2004 => 1 Monat später => 01.05.2004
; >> PB-AddDate: 31.03.2004 => 1 Monat später => 30.04.2004
; Setzte Tag auf das Maximum des neuen Monats
Day = DaysInMonth64(Year, Month)
EndIf
ProcedureReturn Date64(Year64(Date), Month, Day, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Week: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date) + Value * 7, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Day: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date) + Value, Hour64(Date), Minute64(Date), Second64(Date))
Case #PB_Date_Hour: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date) + Value, Minute64(Date), Second64(Date))
Case #PB_Date_Minute: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date), Minute64(Date) + Value, Second64(Date))
Case #PB_Date_Second: ProcedureReturn Date64(Year64(Date), Month64(Date), Day64(Date), Hour64(Date), Minute64(Date), Second64(Date) + Value)
EndSelect
EndProcedure
Procedure.s FormatDate64(Mask$, Date.q)
Protected Result$
Result$ = ReplaceString(Mask$, "%yyyy", RSet(Str(Year64(Date)), 4, "0"))
Result$ = ReplaceString(Result$, "%yy", RSet(Right(Str(Year64(Date)), 2), 2, "0"))
Result$ = ReplaceString(Result$, "%mm", RSet(Str(Month64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%dd", RSet(Str(Day64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%hh", RSet(Str(Hour64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%ii", RSet(Str(Minute64(Date)), 2, "0"))
Result$ = ReplaceString(Result$, "%ss", RSet(Str(Second64(Date)), 2, "0"))
ProcedureReturn Result$
EndProcedure
Macro ReadMaskVariable(MaskVariable, ReturnVariable)
If Mid(Mask$, i, 3) = MaskVariable
IsVariableFound = #True
ReturnVariable = Val(Mid(Date$, DatePos, 2))
DatePos + 2 ; Die 2 Nummern der Zahl überspringen
i + 2 ; Die 3 Zeichen der Variable überspringen
Continue
EndIf
EndMacro
Procedure.q ParseDate64(Mask$, Date$)
Protected.i i, DatePos = 1, IsVariableFound, Year, Month = 1, Day = 1, Hour, Minute, Second
Protected MaskChar$, DateChar$
For i = 1 To Len(Mask$)
MaskChar$ = Mid(Mask$, i, 1)
DateChar$ = Mid(Date$, DatePos, 1)
If MaskChar$ <> DateChar$
If MaskChar$ = "%" ; Vielleicht eine Variable?
If Mid(Mask$, i, 5) = "%yyyy"
IsVariableFound = #True
Year = Val(Mid(Date$, DatePos, 4))
DatePos + 4 ; Die 4 Nummern der Jahreszahl überspringen
i + 4 ; Die 5 Zeichen der Variable "%yyyy" überspringen
Continue
ElseIf Mid(Mask$, i, 3) = "%yy"
IsVariableFound = #True
Year = Val(Mid(Date$, DatePos, 2))
DatePos + 2 ; Die 2 Nummern der Jahreszahl überspringen
i + 2 ; Die 3 Zeichen der Variable "%yy" überspringen
Continue
EndIf
ReadMaskVariable("%mm", Month)
ReadMaskVariable("%dd", Day)
ReadMaskVariable("%hh", Hour)
ReadMaskVariable("%ii", Minute)
ReadMaskVariable("%ss", Second)
If Not IsVariableFound
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
EndIf
DatePos + 1
Next
ProcedureReturn Date64(Year, Month, Day, Hour, Minute, Second)
EndProcedure
EndModule
;-Example
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
;-Test
UseModule Date64
Define.i Year, Month, Day, Hour, Minute, Second, Result, Result64
Define.q Date, Date64
Define Date$, Date64$, Result64$
Debug "Kleiner Kompatibilitäts-Test - Fehler:"
For Year = 1970 To 2037
For Month = 1 To 12
For Day = 1 To 28
For Hour = 0 To 23
;For Minute = 0 To 59
;For Second = 0 To 59
Date = Date(Year, Month, Day, Hour, Minute, Second)
Date64 = Date64(Year, Month, Day, Hour, Minute, Second)
If Date <> Date64
Debug "Date() <> Date64()"
Debug Date
Debug Date64
Debug ""
EndIf
Date$ = FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date)
Date64$ = FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64)
If Date$ <> Date64$
Debug "FormatDate() <> FormatDate64()"
Debug Date$
Debug Date64$
Debug ""
EndIf
Result = ParseDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date$)
Result64 = ParseDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64$)
If Result <> Result64
Debug "ParseDate() <> ParseDate64()"
Debug Result
Debug Result64
Debug ""
EndIf
Result = DayOfWeek(Date)
Result64 = DayOfWeek64(Date64)
If Result <> Result64
Debug "DayOfWeek() <> DayOfWeek64()"
Debug Result
Debug Result64
Debug ""
EndIf
Result = DayOfYear(Date)
Result64 = DayOfYear64(Date64)
If Result <> Result64
Debug "DayOfYear() <> DayOfYear64()"
Debug Result
Debug Result64
Debug ""
EndIf
;Next Second
;Next Minute
Next Hour
Next Day
Next Month
Next Year
If Date() <> Date64()
Debug "Date() <> Date64()"
EndIf
Macro AddDateTest(Type, TypeS)
If AddDate(Date(), #PB_Date_#Type, 1) <> AddDate64(Date64(), #PB_Date_#Type, 1)
Debug "AddDate(Date(), #PB_Date_" + TypeS + ", 1) <> AddDate64(Date64(), #PB_Date_" + TypeS + ", 1)"
EndIf
If AddDate(Date(), #PB_Date_#Type, -1) <> AddDate64(Date64(), #PB_Date_#Type, -1)
Debug "AddDate(Date(), #PB_Date_" + TypeS + ", -1) <> AddDate64(Date64(), #PB_Date_" + TypeS + ", -1)"
EndIf
EndMacro
AddDateTest(Year, "Year")
AddDateTest(Month, "Month")
AddDateTest(Day, "Day")
AddDateTest(Hour, "Hour")
AddDateTest(Minute, "Minute")
AddDateTest(Second, "Second")
AddDateTest(Week, "Week")
Macro TestDateLimits(Minimum, Maximum)
Date64$ = Minimum
Date64 = ParseDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64$)
Result64$ = FormatDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64)
If Date64$ <> Result64$
Debug "Minimum stimmt nicht:"
Debug "> Erwartet wurde: " + Date64$
Debug "> Zurückgegeben wurde: " + Result64$
EndIf
Date64$ = Maximum
Date64 = ParseDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64$)
Result64$ = FormatDate64("%dd.%mm.%yyyy %hh:%ii:%ss", Date64)
If Date64$ <> Result64$
Debug "Maximum stimmt nicht:"
Debug "> Erwartet wurde: " + Date64$
Debug "> Zurückgegeben wurde: " + Result64$
EndIf
EndMacro
Debug "---------------------"
Debug "Test der Datum-Grenzen - Fehler:"
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
TestDateLimits("01.01.1601 00:00:00", "31.12.9999 23:59:59")
CompilerCase #PB_OS_Linux
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
TestDateLimits("01.01.1902 00:00:00", "18.01.2038 23:59:59")
CompilerElse
TestDateLimits("01.01.0000 00:00:00", "31.12.9999 23:59:59")
CompilerEndIf
CompilerCase #PB_OS_MacOS
TestDateLimits("31.12.1969 23:59:59", "31.12.9999 23:59:59")
CompilerEndSelect
Debug "---------------------"
Debug "Test wurde durchgeführt"
CompilerEndIf
Zuletzt geändert von Sicro am 30.07.2017 19:43, insgesamt 1-mal geändert.
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
Re: Date64 - Unixtime 64bit
Hallo Sicro!
Darf ich darauf hinweisen, daß
Danke!
Darf ich darauf hinweisen, daß
weiterhin für große Teile Deutschlands/Europas/der Welt fehlerhafte Werte liefert?Debug DaysInMonth64(1700, 2)
Danke!
Re: Date64 - Unixtime 64bit
Und mancherorts ist der Gregorianisache Kalender wahrscheinlich bis heute nicht eingeführt ...Lord hat geschrieben:Es wird nicht berücksichtigt, daß in großen Teilen Deutschlands/Europas/der Welt
der Gregorianische Kalender zu unterschiedlichen Zeiten umgesetzt wurde.
Es muß somit immer der Ort, für den eine Zeitrechnung durcheführt werden
soll, berücksichtigt werden.
Für den Zeitraum 1601 bis 1700 fehlen in vielen Gebieten die Tage 19.02 bis
28.02.1700, weil die Umstellung erst da erfolgte.
In der VR China erfolgte die Umstellung erst 1949, im KR Griechenland erst 1923,
in der UdSSR erst 1922, ... usw.
So gesehen ist diese Routine so nicht brauchbar, da sie fehlerhafte Ergebnisse
liefern kann.
Es müßte also ein gebietsspezifischer Korrekturwert eingeführt werden.
Dieser Code stellt Berechnungen mit dem Gregorianischen Kalender an. Derjenige, der dieses Modul in einem Programm verwendet, ist letztlich selbst dafür verantwortlich dass Berechnungen im Zusammenhang seines Programms sinnvoll sind.
Sicher wäre so eine Liste o. Ä. wie du vorschlägst hilfreich, aber viele Benutzer des Moduls brauchen das gar nicht, da für die Zeitberechnungen die sie durchführen immer der Gregorianische Kalender gilt.
Diejenigen welche die genannten zusätzlichen Informationen benötigen, müssen sich momentan halt selbst darum bemühen und Zeitdifferenzen u. Ä. ggf. entsprechend korrigieren.