Aktuelle Zeit: 04.04.2020 16:50

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 58 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5, 6  Nächste
Autor Nachricht
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 21.02.2016 19:11 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
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.

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 18.03.2016 21:28 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
So, ich habe mich nochmal an den Code ran gemacht. :)

Ä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 :D (getestet unter Xubuntu_x86, LinuxMint_x64 und WindowsXP)

Änderungen (19.03.2016):
  • Doppelter Code per Macros reduziert (Code-Zeilen-Einsparung: 140 Zeilen)

Code:
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

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 19.03.2016 11:39 
Offline
Benutzeravatar

Registriert: 24.11.2004 13:12
Wohnort: Germany
Läuft nicht unter Mac
Zitat:
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)

:cry:

_________________
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul / OPC-Helper DLL
PB v3.30 / v5.4x - OS Mac Mini OSX 10.xx / Window 10 Pro. (X64) /Window 7 Pro. (X64) / Window XP Pro. (X86) / Ubuntu 14.04
Downloads auf My Webspace


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 19.03.2016 13:39 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
gmtime_r() müsste es aber eigentlich unter Mac geben:
https://developer.apple.com/search/?q=gmtime_r

Vielleicht hilft das:
Code:
ImportC "-lc"

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 27.05.2016 21:01 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
Code im CodeArchiv unter Time_and_Date/Date64[WIN,LIN].pbi aktualisiert.

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 28.05.2016 11:24 
Offline

Registriert: 21.01.2008 19:11
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:
Code:
#HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
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.

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 23.07.2016 11:45 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
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.php?Eintrag=Einf%FChrungGregorKal

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 27.07.2017 14:29 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
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-CodeArchiv-Rebirth/blob/master/Date/Date64%5BWin%2CLin%2CMac%5D.pbi
Code:
;   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


Edit: Warnhinweis für Datumsberechnungen vor dem gregorianischen Kalender zum Code hinzugefügt

_________________
Bild
Warum OpenSource eine Lizenz haben sollte
PureBasic-CodeArchiv-Rebirth: Git-Repository / Download – Jede Hilfe ist willkommen!
Manjaro Xfce x64 (Hauptsystem) :: WindowsXP/Xubuntu x86 (VirtualBox) :: PureBasic (Linux: x86/x64, Windows: x86) :: jeweils neueste Version


Zuletzt geändert von Sicro am 30.07.2017 19:43, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 28.07.2017 11:28 
Offline

Registriert: 21.01.2008 19:11
Hallo Sicro!

Darf ich darauf hinweisen, daß
Zitat:
Debug DaysInMonth64(1700, 2)
weiterhin für große Teile Deutschlands/Europas/der Welt fehlerhafte Werte liefert?

Danke!

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 28.07.2017 12:21 
Offline

Registriert: 13.05.2010 09:26
Wohnort: Berlin
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.

Und mancherorts ist der Gregorianisache Kalender wahrscheinlich bis heute nicht eingeführt ...
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.

_________________
Dieser Satz ist falsch.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 58 Beiträge ]  Gehe zu Seite Vorherige  1, 2, 3, 4, 5, 6  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 Gäste


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye