Aktuelle Zeit: 05.12.2019 20:00

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




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

Registriert: 24.11.2004 13:12
Wohnort: Germany
Im jahr 2038 ist es aus mit den Datumsfunktionen mit Unix Time Format 32. Weiss nicht wann PB da umgestellt wird.

Vielen Dank an Sicro und ts-soft für die Erweiterung für Linux und Mac

Update v2.02

Update v2.04
- Stand CodeArchiv von 12.08.2018

Code:
;-TOP
;
;   Description: Support for enlarged date range (64 bit unix timestamp)
;            OS: Windows, Linux, Mac
; English-Forum:
;  French-Forum:
;  German-Forum: http://www.purebasic.fr/german/viewtopic.php?p=335727#p335727
; -----------------------------------------------------------------------------

; MIT License
;
; Copyright (c) 2012 mk-soft
; Copyright (c) 2013-2017 Sicro
; Copyright (c) 2014 ts-soft
; Copyright (c) 2017 wilbert
;
; Permission is hereby granted, free of charge, to any person obtaining a copy
; of this software and associated documentation files (the "Software"), to deal
; in the Software without restriction, including without limitation the rights
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
; copies of the Software, and to permit persons to whom the Software is
; furnished to do so, subject to the following conditions:
;
; The above copyright notice and this permission notice shall be included in all
; copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
; SOFTWARE.

; -----------------------------------------------------------------------------

; Version : v2.04
; Create  : 22.10.2012
; Update  : 12.08.2018
; OS      : All
; Link DE : http://www.purebasic.fr/german/viewtopic.php?f=8&t=26001

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

  ; !!! >>> WARNING <<< !!!
  ; The Gregorian calendar was introduced in many regions at different times.
  ; This module uses the API date functions of the operating system and these have implemented a
  ; uniform introduction time, so that date calculations before the introduction of the Gregorian
  ; calendar usually lead to wrong results.

  ; == 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

  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    ImportC ""
      CFCalendarAddComponents(calendar, *at, options, componentDesc.p-ascii, value)
      CFCalendarComposeAbsoluteTime(calendar, *at, componentDesc.p-ascii, year, month, day, hour, minute, second)
      CFCalendarCreateWithIdentifier(allocator, identifier)
      CFCalendarDecomposeAbsoluteTime(calendar, at.d, componentDesc.p-ascii, *component)
      CFCalendarSetTimeZone(calendar, tz)
      CFTimeZoneCopyDefault()
      CFTimeZoneCreateWithTimeIntervalFromGMT(allocator, ti.d)
      CFTimeZoneGetSecondsFromGMT.d(tz, at.d)
    EndImport

    Global.i GregorianGMT, TimeZone

    Procedure Date64Init(); Init global variables GregorianGMT and TimeZone
      Protected *kCFGregorianCalendar.Integer = dlsym_(#RTLD_DEFAULT, "kCFGregorianCalendar")
      TimeZone = CFTimeZoneCreateWithTimeIntervalFromGMT(0, 0)
      GregorianGMT = CFCalendarCreateWithIdentifier(0, *kCFGregorianCalendar\i)
      CFCalendarSetTimeZone(GregorianGMT, TimeZone)
      CFRelease_(TimeZone)
      TimeZone = CFTimeZoneCopyDefault()
    EndProcedure

    Date64Init()
  CompilerEndIf

  ;{ Structure definition for "tm"
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    If Not Defined(tm, #PB_Structure)
      Structure tm Align #PB_Structure_AlignC
        tm_sec.l    ; 0 to 59 or up to 60 at leap second
        tm_min.l    ; 0 to 59
        tm_hour.l   ; 0 to 23
        tm_mday.l   ; Day of the month: 1 to 31
        tm_mon.l    ; Month: 0 to 11 (0 = January)
        tm_year.l   ; Number of years since the year 1900
        tm_wday.l   ; Weekday: 0 to 6, 0 = Sunday
        tm_yday.l   ; Days since the beginning of the year: 0 to 365 (365 is therefore 366 because after 1. January is counted)
        tm_isdst.l  ; Is summer time? tm_isdst > 0 = Yes
                    ;                             tm_isdst = 0 = No
                    ;                             tm_isdst < 0 = Unknown
        CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
          tm_gmtoff.l ; Offset of UTC in seconds
          *tm_zone    ; Abbreviation of the time zone
        CompilerElse
          tm_zone.l   ; Placeholder
          tm_gmtoff.l ; Offset of UTC in seconds
          *tm_zone64  ; Abbreviation of the time zone
        CompilerEndIf

      EndStructure
    EndIf
  CompilerEndIf
  ;}

  Procedure.i IsLeapYear64(Year.i)
    If Year < 1600
      ; Every year before 1600 are leap years if they are divisible by 4 with no remainder
      ProcedureReturn Bool(Year % 4 = 0)
    Else
      ; From the year 1600 are all year leap years that meet the following conditions:
      ; => Can be divided by 4 without remainder, but can not be divided by 100 without remainder
      ; => Divisible by 400 without remainder
      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) ; February has one more day in the leap year
    EndSelect
  EndProcedure

  Procedure.q Date64(Year.i=-1, Month.i=1, Day.i=1, Hour.i=0, Minute.i=0, Second.i=0)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
        Protected.FILETIME   ft, ft2
        Protected.i          DaysInMonth

        If Year > -1 ; Valid date

          ; Correct the data, if necessary

          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

          ; Convert system time (UTC) to file time (UTC)
          SystemTimeToFileTime_(@st, @ft)

          ; Convert UTC time to seconds
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        Else
          ; No valid date. Local system time is determined
          GetLocalTime_(@st)
          SystemTimeToFileTime_(@st, @ft) ; "st" is read as UTC and convert to file time

          ; Convert UTC time to seconds
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        EndIf

      CompilerCase #PB_OS_Linux
        Protected.tm tm
        Protected.q time
       
        If Year > -1 ; Valid date
          tm\tm_year  = Year - 1900 ; Years from 1900
          tm\tm_mon   = Month - 1   ; Months from January
          tm\tm_mday  = Day
          tm\tm_hour  = Hour
          tm\tm_min   = Minute
          tm\tm_sec   = Second

          ; mktime corrects the data itself and delivers seconds
          time = timegm_(@tm) ; Convert structured UTC time to UTC time as seconds

          ProcedureReturn time ; UTC time in seconds
        Else
          ; No valid date. Local system time is determined
          time = time_(0)
          If localtime_r_(@time, @tm) <> 0
            time = timegm_(@tm)
          EndIf

          ProcedureReturn time  ; UTC time in seconds
        EndIf

      CompilerCase #PB_OS_MacOS
        Protected at.d
        If Year > -1 ; Valid date
          CFCalendarComposeAbsoluteTime(GregorianGMT, @at, "yMdHms", Year, Month, Day, Hour, Minute, Second)
        Else ; No valid date. Local system time is determined
          at = CFAbsoluteTimeGetCurrent_()
          at + CFTimeZoneGetSecondsFromGMT(TimeZone, at)
        EndIf
        ProcedureReturn at + 978307200
    CompilerEndSelect
  EndProcedure

  Macro Windows_ReturnDatePart(Type)
    Protected.SYSTEMTIME st

    Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
    FileTimeToSystemTime_(@Date, @st)

    ProcedureReturn st\Type
  EndMacro

  Macro Linux_ReturnDatePart(Type, ReturnCode)
    Protected.tm *tm
    Protected.i  Value

    *tm = gmtime_(@Date)
    If *tm
      Value = *tm\Type
    EndIf

    ProcedureReturn ReturnCode
  EndMacro

  Macro Mac_ReturnDatePart(Type)
    Protected.i DatePart

    CFCalendarDecomposeAbsoluteTime(GregorianGMT, Date - 978307200, Type, @DatePart)

    CompilerIf Type = "E"
      ProcedureReturn DatePart - 1
    CompilerElse
      ProcedureReturn DatePart
    CompilerEndIf
  EndMacro

  Procedure.i Year64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wYear)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_year, Value + 1900)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("y")
    CompilerEndSelect
  EndProcedure

  Procedure.i Month64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wMonth)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_mon, Value + 1)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("M")
    CompilerEndSelect
  EndProcedure

  Procedure.i Day64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wDay)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_mday, Value)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("d")
    CompilerEndSelect
  EndProcedure

  Procedure.i Hour64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wHour)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_hour, Value)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("H")
    CompilerEndSelect
  EndProcedure

  Procedure.i Minute64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wMinute)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_min, Value)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("m")
    CompilerEndSelect
  EndProcedure

  Procedure.i Second64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wSecond)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_sec, Value)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("s")
    CompilerEndSelect
  EndProcedure

  Procedure.i DayOfWeek64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows : Windows_ReturnDatePart(wDayOfWeek)
      CompilerCase #PB_OS_Linux   : Linux_ReturnDatePart(tm_wday, Value)
      CompilerCase #PB_OS_MacOS   : Mac_ReturnDatePart("E")
    CompilerEndSelect
  EndProcedure

  Procedure.i DayOfYear64(Date.q)
    CompilerSelect #PB_Compiler_OS

      CompilerCase #PB_OS_Windows
        Protected.q TempDate
        TempDate = Date64(Year64(Date))
        ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1

      CompilerCase #PB_OS_Linux
        Linux_ReturnDatePart(tm_yday, Value + 1)

      CompilerCase #PB_OS_MacOS
        Mac_ReturnDatePart("D")

    CompilerEndSelect
  EndProcedure

  Procedure.q AddDate64(Date.q, Type.i, Value.i)
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      Protected at.d = Date - 978307200

      Select Type
        Case #PB_Date_Year:   CFCalendarAddComponents(GregorianGMT, @at, 0, "y", Value)
        Case #PB_Date_Month:  CFCalendarAddComponents(GregorianGMT, @at, 0, "M", Value)
        Case #PB_Date_Week:   CFCalendarAddComponents(GregorianGMT, @at, 0, "d", Value * 7)
        Case #PB_Date_Day:    CFCalendarAddComponents(GregorianGMT, @at, 0, "d", Value)
        Case #PB_Date_Hour:   CFCalendarAddComponents(GregorianGMT, @at, 0, "H", Value)
        Case #PB_Date_Minute: CFCalendarAddComponents(GregorianGMT, @at, 0, "m", Value)
        Case #PB_Date_Second: CFCalendarAddComponents(GregorianGMT, @at, 0, "s", Value)
      EndSelect

      ProcedureReturn at + 978307200
    CompilerElse ; Windows or Linux
      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 corrects the date unlike PB-AddDate it does
            ; >> mktime:     31.03.2004 => 1 month later => 01.05.2004
            ; >> PB-AddDate: 31.03.2004 => 1 month later => 30.04.2004

            ; Set day to the maximum of the new month
            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
    CompilerEndIf

  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 ; Skip the 2 numbers of the number
      i + 2       ; Skip the 3 characters of the variable
      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$ = "%" ; Maybe a variable?

          If Mid(Mask$, i, 5) = "%yyyy"
            IsVariableFound = #True
            Year = Val(Mid(Date$, DatePos, 4))
            DatePos + 4 ; Skip the 4 numbers of the year
            i + 4       ; Skip the 5 characters of the variable "%yyyy"
            Continue

          ElseIf Mid(Mask$, i, 3) = "%yy"
            IsVariableFound = #True
            Year = Val(Mid(Date$, DatePos, 2))
            DatePos + 2 ; Skip the 2 numbers of the year
            i + 2       ; Skip the 3 characters of the variable "%yy"
            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 "Small compatibility test - error:"

  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 is wrong:"
      Debug "> Expected was: " + Date64$
      Debug "> It was returned: " + 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 is wrong:"
      Debug "> Expected was: " + Date64$
      Debug "> It was returned: " + Result64$
    EndIf
   
  EndMacro
 
  Debug "---------------------"
  Debug "Test of date limits - error:"
 
  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 was carried out"
CompilerEndIf

_________________
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 Webspace


Zuletzt geändert von mk-soft am 22.07.2019 22:41, insgesamt 6-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 22.10.2012 22:43 
Offline
Kommando SG1
Benutzeravatar

Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Na hoffentlich erinnern wir uns in 26 Jahren noch an
diesen Thread,
dieses Forum,
die Sprache Pure Basic,
das Betriebssystem Windows

_________________
Bild
 
BildBildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 11.08.2013 17:23 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
Hab mal einen komplett neuen Code geschrieben, der unter allen 3 Betriebssystemen laufen sollte.
Unter Windows (Windows 7 HE) und Linux (Xubuntu) läuft alles, MacOS kann ich nicht testen.
Code:
#SecondsInOneHour = 60 * 60
#SecondsInOneDay  = #SecondsInOneHour * 24

#HundredNanosecondsInOneSecond               = 10000000
#HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Linux
    If Not Defined(tm, #PB_Structure)
      Structure tm
        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
      EndStructure
    EndIf
  CompilerCase #PB_OS_MacOS
    If Not Defined(tm, #PB_Structure)
      Structure tm
        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    ; Abkürzungsname der Zeitzone
        tm_gmtoff   ; Offset von UTC in Sekunden
      EndStructure
    EndIf
CompilerEndSelect

; == Windows ==
; >> Minimum: 01.01. 1601 00:00:00
; >> Maximum: 31.12.30827 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.999999999 23:59:59

; == MacOS ==
; wie bei Linux?

Procedure.i IsLeapYear(Year)
  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, Month)
  While Month > 12
    Month - 12
  Wend
 
  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)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
      Protected.FILETIME   ft
     
      If Year > -1 ; Gültiges Datum
        ; Angaben evtl. korrigieren
   
        ; >>> Positive Angaben
     
        While Second > 59
          Minute + 1
          Second - 60
        Wend
       
        While Minute > 59
          Hour   + 1
          Minute - 60
        Wend
       
        While Hour > 23
          Day  + 1
          Hour - 24
        Wend
       
        While Day > DaysInMonth(Year, Month)
          Day - DaysInMonth(Year, Month)
          Month + 1
        Wend
       
        While Month > 12
          Year  + 1
          Month - 12
        Wend
       
        ; >>> Negative Angaben
       
        While Second < 0
          Minute - 1
          Second + 59
        Wend
       
        While Minute < 0
          Hour   - 1
          Minute + 59
        Wend
       
        While Hour < 0
          Day  - 1
          Hour + 23
        Wend
       
        While Day < 0
          Day + DaysInMonth(Year, Month)
          Month - 1
        Wend
       
        While Month < 0
          Year  - 1
          Month + 12
        Wend
       
        st\wYear   = Year
        st\wMonth  = Month
        st\wDay    = Day
        st\wHour   = Hour
        st\wMinute = Minute
        st\wSecond = Second
       
        SystemTimeToFileTime_(@st, @ft)
       
        ; Zeit in Sekunden umrechnen
        ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
      Else ; Kein gültiges Datum. Systemzeit wird ermittelt
        GetLocalTime_(@st)
        SystemTimeToFileTime_(@st, @ft)
       
        ; Zeit in Sekunden umrechnen
        ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
      EndIf
    CompilerCase #PB_OS_Linux
      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
        ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
      Else ; Kein gültiges Datum. Systemzeit wird ermittelt
        time = time_(0)
        If time > -1
          CompilerSelect #PB_Compiler_Processor
            CompilerCase #PB_Processor_x86
              *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
            CompilerCase #PB_Processor_x64
              *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerEndSelect
         
          If *Memory_localtime
            localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
            time = mktime_(*Memory_localtime)
            FreeMemory(*Memory_localtime)
            If time > -1
              ProcedureReturn time
            EndIf
          EndIf
        EndIf
      EndIf
    CompilerCase #PB_OS_MacOS
      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
        ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
      Else ; Kein gültiges Datum. Systemzeit wird ermittelt
        time = time_(0)
        If time > -1
          *Memory_localtime = AllocateMemory(SizeOf(tm))
          If *Memory_localtime
            localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
            time = mktime_(*Memory_localtime)
            FreeMemory(*Memory_localtime)
            If time > -1
              ProcedureReturn time
            EndIf
          EndIf
        EndIf
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Year64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
 
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
   
      ProcedureReturn st\wYear
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Year
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Year = *Memory_localtime\tm_year + 1900
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Year
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Year
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Year = *Memory_localtime\tm_year + 1900
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Year
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Month64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wMonth
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Month
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Month = *Memory_localtime\tm_mon + 1
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Month
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Month
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Month = *Memory_localtime\tm_mon + 1
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Month
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Day64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wDay
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Day
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Day = *Memory_localtime\tm_mday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Day
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Day
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Day = *Memory_localtime\tm_mday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Day
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Hour64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wHour
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Hour
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Hour = *Memory_localtime\tm_hour
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Hour
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Hour
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Hour = *Memory_localtime\tm_hour
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Hour
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Minute64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wMinute
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Minute
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Minute = *Memory_localtime\tm_min
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Minute
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Minute
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Minute = *Memory_localtime\tm_min
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Minute
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i Second64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wSecond
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  Second
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Second = *Memory_localtime\tm_sec
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Second
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  Second
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        Second = *Memory_localtime\tm_sec
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn Second
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i DayOfWeek64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.SYSTEMTIME st
     
      Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
      FileTimeToSystemTime_(@Date, @st)
     
      ProcedureReturn st\wDayOfWeek
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  DayOfWeek
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        DayOfWeek = *Memory_localtime\tm_wday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn DayOfWeek
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  DayOfWeek
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        DayOfWeek = *Memory_localtime\tm_wday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn DayOfWeek
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
EndProcedure

Procedure.i DayOfYear64(Date.q)
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
      Protected.q TempDate
     
      TempDate = Date64(Year64(Date))
     
      ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1
    CompilerCase #PB_OS_Linux
      Protected.tm *Memory_localtime
      Protected.i  DayOfYear
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      CompilerSelect #PB_Compiler_Processor
        CompilerCase #PB_Processor_x86
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerCase #PB_Processor_x64
          *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
      CompilerEndSelect
     
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        DayOfYear = *Memory_localtime\tm_yday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn DayOfYear + 1
      Else
        ProcedureReturn -1
      EndIf
    CompilerCase #PB_OS_MacOS
      Protected.tm *Memory_localtime
      Protected.i  DayOfYear
     
      Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
     
      *Memory_localtime = AllocateMemory(SizeOf(tm))
      If *Memory_localtime
        localtime_r_(@Date, *Memory_localtime)
        DayOfYear = *Memory_localtime\tm_yday
        FreeMemory(*Memory_localtime)
       
        ProcedureReturn DayOfYear + 1
      Else
        ProcedureReturn -1
      EndIf
  CompilerEndSelect
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.s, Date.q)
  Protected.s Retval
 
  Retval = ReplaceString(Mask,   "%yyyy", RSet(Str(Year64(Date)),   4, "0"))
  Retval = ReplaceString(Retval, "%yy",   RSet(Right(Str(Year64(Date)), 2), 2, "0"))
  Retval = ReplaceString(Retval, "%mm",   RSet(Str(Month64(Date)),  2, "0"))
  Retval = ReplaceString(Retval, "%dd",   RSet(Str(Day64(Date)),    2, "0"))
  Retval = ReplaceString(Retval, "%hh",   RSet(Str(Hour64(Date)),   2, "0"))
  Retval = ReplaceString(Retval, "%ii",   RSet(Str(Minute64(Date)), 2, "0"))
  Retval = ReplaceString(Retval, "%ss",   RSet(Str(Second64(Date)), 2, "0"))
   
  ProcedureReturn Retval
EndProcedure

Procedure.q ParseDate64(Mask.s, Date.s)
  Protected.i i, DatePos = 1, IsVariableFound, Year, Month = 1, Day = 1, Hour, Minute, Second
  Protected.s 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
          Debug "Year: " + Str(Year)
          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
          Debug "Year: " + Str(Year)
          Continue
        EndIf
       
        If Mid(Mask, i, 3) = "%mm"
          IsVariableFound = #True
          Month = Val(Mid(Date, DatePos, 2))
          DatePos + 2 ; Die 2 Nummern der Monatszahl überspringen
          i + 2       ; Die 3 Zeichen der Variable "%mm" überspringen
          Debug "Month: " + Str(Month)
          Continue
        EndIf
       
        If Mid(Mask, i, 3) = "%dd"
          IsVariableFound = #True
          Day = Val(Mid(Date, DatePos, 2))
          DatePos + 2 ; Die 2 Nummern der Tageszahl überspringen
          i + 2       ; Die 3 Zeichen der Variable "%dd" überspringen
          Debug "Day: " + Str(Day)
          Continue
        EndIf
       
        If Mid(Mask, i, 3) = "%hh"
          IsVariableFound = #True
          Hour = Val(Mid(Date, DatePos, 2))
          DatePos + 2 ; Die 2 Nummern der Stundenzahl überspringen
          i + 2       ; Die 3 Zeichen der Variable "%hh" überspringen
          Debug "Hour: " + Str(Hour)
          Continue
        EndIf
       
        If Mid(Mask, i, 3) = "%ii"
          IsVariableFound = #True
          Minute = Val(Mid(Date, DatePos, 2))
          DatePos + 2 ; Die 2 Nummern der Minutenzahl überspringen
          i + 2       ; Die 3 Zeichen der Variable "%ii" überspringen
          Debug "Minute: " + Str(Minute)
          Continue
        EndIf
       
        If Mid(Mask, i, 3) = "%ss"
          IsVariableFound = #True
          Second = Val(Mid(Date, DatePos, 2))
          DatePos + 2 ; Die 2 Nummern der Sekundenzahl überspringen
          i + 2       ; Die 3 Zeichen der Variable "%ss" überspringen
          Debug "Second: " + Str(Second)
          Continue
        EndIf
       
        If Not IsVariableFound
          ProcedureReturn 0
        EndIf
      Else
        ProcedureReturn 0
      EndIf
    EndIf
   
    DatePos + 1
  Next
 
  ProcedureReturn Date64(Year, Month, Day, Hour, Minute, Second)
EndProcedure

; ======== Funktionstests ========

Define.i i, Date
Define.q Date64

For i = 1970 To 2038
  Date   = Date  (i, 1, 1, 22, 49, 33)
  Date64 = Date64(i, 1, 1, 22, 49, 33)
 
  If Date <> Date64
    Debug "Date-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Year(Date) <> Year64(Date64)
    Debug "Year-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Month(Date) <> Month64(Date64)
    Debug "Month-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Day(Date) <> Day64(Date64)
    Debug "Day-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Hour(Date) <> Hour64(Date64)
    Debug "Hour-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Minute(Date) <> Minute64(Date64)
    Debug "Minute-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If Second(Date) <> Second64(Date64)
    Debug "Second-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If DayOfWeek(Date) <> DayOfWeek64(Date64)
    Debug "DayOfWeek-Unterschied bei Jahr: " + Str(i)
  EndIf
 
  If DayOfYear(Date) <> DayOfYear64(Date64)
    Debug "DayOfYear-Unterschied bei Jahr: " + Str(i)
  EndIf
Next

; Schaltjahr-Test
Date64 = Date64(2004, 2, 1)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "29 Tage später:"
Date64 = AddDate64(Date64, #PB_Date_Day, 29)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "==================================="
Date64 = Date64(2005, 2, 1)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "29 Tage später:"
Date64 = AddDate64(Date64, #PB_Date_Day, 29)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)

; Überlauf-Test
Date64 = Date64(2004, 3, 31)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "1 Monat später:"
Date64 = AddDate64(Date64, #PB_Date_Month, 1)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)

; Unterlauf-Test
Date64 = Date64(2004, 7, 31)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "1 Monat früher:"
Date64 = AddDate64(Date64, #PB_Date_Month, -1)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)

; Parse Datum
Date64 = ParseDate64("%dd.%mm.%yyyy - %hh:%ii:%ss", "21.05.2013 - 16:47:12")
Debug FormatDate64("%dd.%mm.%yyyy - %hh:%ii:%ss", Date64)

_________________
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: 12.08.2013 11:59 
Offline

Registriert: 21.01.2008 19:11
Hallo sicro!

Mach ich etwas falsch?
Beispiel:

Code:
date64=Date64(1950, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, -100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(1950, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, 100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(2050, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, -100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(2050, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, 100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)

Ich erhalte:
Debug hat geschrieben:
2145998973
01.01.1950
01.01.1938
-------------
2145998973
01.01.1950
01.01.2138
-------------
2145998973
01.01.2050
01.01.1938
-------------
2145998973
01.01.2050
01.01.2138

_________________
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 12.08.2013 18:44 
Offline
Benutzeravatar

Registriert: 11.08.2005 19:08
Du verwendest zwei unterschiedliche Date-Variablen:

Lord hat geschrieben:
date64=Date64(1950, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, -100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(1950, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, 100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(2050, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, -100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Debug "-------------"
date64=Date64(2050, 1, 1)
Debug Date
Debug FormatDate64("%dd.%mm.%yyyy", Date64)
Date64=AddDate64(Date, #PB_Date_Year, 100)
Debug FormatDate64("%dd.%mm.%yyyy", Date64)

_________________
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: 12.08.2013 22:33 
Offline

Registriert: 21.01.2008 19:11
Hallo Sicro!

Da kann man nur eines dazu sagen:
"Kartoffeln auf den Augen!" :oops:

_________________
Bild


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

Registriert: 11.08.2005 19:08
Ich habe den Code nun auch mal in ein Modul umgeschrieben:
Code:
DeclareModule Date64
  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.s, Date.q)
  Declare.q ParseDate64(Mask.s, Date.s)
EndDeclareModule

Module Date64
  ; == Windows ==
  ; >> Minimum: 01.01. 1601 00:00:00
  ; >> Maximum: 31.12.30827 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.999999999 23:59:59

  ; == MacOS ==
  ; wie bei Linux?
 
  #SecondsInOneHour = 60 * 60
  #SecondsInOneDay  = #SecondsInOneHour * 24
 
  #HundredNanosecondsInOneSecond               = 10000000
  #HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
 
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Linux
      If Not Defined(tm, #PB_Structure)
        Structure tm
          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
        EndStructure
      EndIf
    CompilerCase #PB_OS_MacOS
      If Not Defined(tm, #PB_Structure)
        Structure tm
          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    ; Abkürzungsname der Zeitzone
          tm_gmtoff   ; Offset von UTC in Sekunden
        EndStructure
      EndIf
  CompilerEndSelect
   
  Procedure.i IsLeapYear(Year)
    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, Month)
    While Month > 12
      Month - 12
    Wend
   
    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)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
        Protected.FILETIME   ft
       
        If Year > -1 ; Gültiges Datum
          ; Angaben evtl. korrigieren
     
          ; >>> Positive Angaben
       
          While Second > 59
            Minute + 1
            Second - 60
          Wend
         
          While Minute > 59
            Hour   + 1
            Minute - 60
          Wend
         
          While Hour > 23
            Day  + 1
            Hour - 24
          Wend
         
          While Day > DaysInMonth(Year, Month)
            Day - DaysInMonth(Year, Month)
            Month + 1
          Wend
         
          While Month > 12
            Year  + 1
            Month - 12
          Wend
         
          ; >>> Negative Angaben
         
          While Second < 0
            Minute - 1
            Second + 59
          Wend
         
          While Minute < 0
            Hour   - 1
            Minute + 59
          Wend
         
          While Hour < 0
            Day  - 1
            Hour + 23
          Wend
         
          While Day < 0
            Day + DaysInMonth(Year, Month)
            Month - 1
          Wend
         
          While Month < 0
            Year  - 1
            Month + 12
          Wend
         
          st\wYear   = Year
          st\wMonth  = Month
          st\wDay    = Day
          st\wHour   = Hour
          st\wMinute = Minute
          st\wSecond = Second
         
          SystemTimeToFileTime_(@st, @ft)
         
          ; Zeit in Sekunden umrechnen
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          GetLocalTime_(@st)
          SystemTimeToFileTime_(@st, @ft)
         
          ; Zeit in Sekunden umrechnen
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        EndIf
      CompilerCase #PB_OS_Linux
        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
          ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          time = time_(0)
          If time > -1
            CompilerSelect #PB_Compiler_Processor
              CompilerCase #PB_Processor_x86
                *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
              CompilerCase #PB_Processor_x64
                *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
            CompilerEndSelect
           
            If *Memory_localtime
              localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
              time = mktime_(*Memory_localtime)
              FreeMemory(*Memory_localtime)
              If time > -1
                ProcedureReturn time
              EndIf
            EndIf
          EndIf
        EndIf
      CompilerCase #PB_OS_MacOS
        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
          ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          time = time_(0)
          If time > -1
            *Memory_localtime = AllocateMemory(SizeOf(tm))
            If *Memory_localtime
              localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
              time = mktime_(*Memory_localtime)
              FreeMemory(*Memory_localtime)
              If time > -1
                ProcedureReturn time
              EndIf
            EndIf
          EndIf
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Year64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
   
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
     
        ProcedureReturn st\wYear
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Year
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Year = *Memory_localtime\tm_year + 1900
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Year
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Year
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Year = *Memory_localtime\tm_year + 1900
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Year
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Month64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wMonth
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Month
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Month = *Memory_localtime\tm_mon + 1
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Month
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Month
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Month = *Memory_localtime\tm_mon + 1
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Month
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Day64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wDay
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Day
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Day = *Memory_localtime\tm_mday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Day
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Day
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Day = *Memory_localtime\tm_mday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Day
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Hour64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wHour
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Hour
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Hour = *Memory_localtime\tm_hour
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Hour
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Hour
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Hour = *Memory_localtime\tm_hour
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Hour
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Minute64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wMinute
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Minute
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Minute = *Memory_localtime\tm_min
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Minute
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Minute
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Minute = *Memory_localtime\tm_min
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Minute
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Second64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wSecond
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Second
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Second = *Memory_localtime\tm_sec
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Second
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Second
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Second = *Memory_localtime\tm_sec
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Second
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i DayOfWeek64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wDayOfWeek
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  DayOfWeek
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfWeek = *Memory_localtime\tm_wday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfWeek
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  DayOfWeek
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfWeek = *Memory_localtime\tm_wday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfWeek
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i DayOfYear64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.q TempDate
       
        TempDate = Date64(Year64(Date))
       
        ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  DayOfYear
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        CompilerSelect #PB_Compiler_Processor
          CompilerCase #PB_Processor_x86
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 8)  ; Wenn keine 8 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
          CompilerCase #PB_Processor_x64
            *Memory_localtime = AllocateMemory(SizeOf(tm) + 20) ; Wenn keine 20 Bytes zusätzlich reserviert werden, kommt ein Überlauf. Struktur falsch?
        CompilerEndSelect
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfYear = *Memory_localtime\tm_yday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfYear + 1
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  DayOfYear
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfYear = *Memory_localtime\tm_yday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfYear + 1
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  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.s, Date.q)
    Protected.s Retval
   
    Retval = ReplaceString(Mask,   "%yyyy", RSet(Str(Year64(Date)),   4, "0"))
    Retval = ReplaceString(Retval, "%yy",   RSet(Right(Str(Year64(Date)), 2), 2, "0"))
    Retval = ReplaceString(Retval, "%mm",   RSet(Str(Month64(Date)),  2, "0"))
    Retval = ReplaceString(Retval, "%dd",   RSet(Str(Day64(Date)),    2, "0"))
    Retval = ReplaceString(Retval, "%hh",   RSet(Str(Hour64(Date)),   2, "0"))
    Retval = ReplaceString(Retval, "%ii",   RSet(Str(Minute64(Date)), 2, "0"))
    Retval = ReplaceString(Retval, "%ss",   RSet(Str(Second64(Date)), 2, "0"))
     
    ProcedureReturn Retval
  EndProcedure
 
  Procedure.q ParseDate64(Mask.s, Date.s)
    Protected.i i, DatePos = 1, IsVariableFound, Year, Month = 1, Day = 1, Hour, Minute, Second
    Protected.s 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
            Debug "Year: " + Str(Year)
            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
            Debug "Year: " + Str(Year)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%mm"
            IsVariableFound = #True
            Month = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Monatszahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%mm" überspringen
            Debug "Month: " + Str(Month)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%dd"
            IsVariableFound = #True
            Day = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Tageszahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%dd" überspringen
            Debug "Day: " + Str(Day)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%hh"
            IsVariableFound = #True
            Hour = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Stundenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%hh" überspringen
            Debug "Hour: " + Str(Hour)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%ii"
            IsVariableFound = #True
            Minute = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Minutenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%ii" überspringen
            Debug "Minute: " + Str(Minute)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%ss"
            IsVariableFound = #True
            Second = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Sekundenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%ss" überspringen
            Debug "Second: " + Str(Second)
            Continue
          EndIf
         
          If Not IsVariableFound
            ProcedureReturn 0
          EndIf
        Else
          ProcedureReturn 0
        EndIf
      EndIf
     
      DatePos + 1
    Next
   
    ProcedureReturn Date64(Year, Month, Day, Hour, Minute, Second)
  EndProcedure
EndModule

_________________
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: 23.03.2014 22:56 
Offline
Benutzeravatar

Registriert: 08.09.2004 00:57
Wohnort: Berlin
Danke Sicro :allright:

Hab jetzt noch kleinere Anpassungen vorgenommen, vor allem die Structure für Linux und Mac angepasst.
Unter MacOS sollte noch mal jemand testen, der die Möglichkeit hat, bei mir läuft es unter Win und Lin in
allen Modi.

Code:
DeclareModule Date64
  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.s, Date.q)
  Declare.q ParseDate64(Mask.s, Date.s)
EndDeclareModule

Module Date64
 
  CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
    CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
      CompilerError "32-Bit not supported on MacOS"
    CompilerEndIf
  CompilerEndIf
 
  EnableExplicit
 
  ; == Windows ==
  ; >> Minimum: 01.01. 1601 00:00:00
  ; >> Maximum: 31.12.30827 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.999999999 23:59:59
 
  ; == MacOS ==
  ; wie bei Linux?
 
  #SecondsInOneHour = 60 * 60
  #SecondsInOneDay  = #SecondsInOneHour * 24
 
  #HundredNanosecondsInOneSecond               = 10000000
  #HundredNanosecondsFrom_1Jan1601_To_1Jan1970 = 116444736000000000
 
  CompilerSelect #PB_Compiler_OS
    CompilerCase #PB_OS_Windows
    CompilerDefault
      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    ; Abkürzungsname der Zeitzone
          tm_gmtoff.l ; Offset von UTC in Sekunden
        EndStructure
      EndIf
  CompilerEndSelect
 
  Procedure.i IsLeapYear(Year)
    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, Month)
    While Month > 12
      Month - 12
    Wend
   
    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)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
        Protected.FILETIME   ft
       
        If Year > -1 ; Gültiges Datum
          ; Angaben evtl. korrigieren
         
          ; >>> Positive Angaben
         
          While Second > 59
            Minute + 1
            Second - 60
          Wend
         
          While Minute > 59
            Hour   + 1
            Minute - 60
          Wend
         
          While Hour > 23
            Day  + 1
            Hour - 24
          Wend
         
          While Day > DaysInMonth(Year, Month)
            Day - DaysInMonth(Year, Month)
            Month + 1
          Wend
         
          While Month > 12
            Year  + 1
            Month - 12
          Wend
         
          ; >>> Negative Angaben
         
          While Second < 0
            Minute - 1
            Second + 59
          Wend
         
          While Minute < 0
            Hour   - 1
            Minute + 59
          Wend
         
          While Hour < 0
            Day  - 1
            Hour + 23
          Wend
         
          While Day < 0
            Day + DaysInMonth(Year, Month)
            Month - 1
          Wend
         
          While Month < 0
            Year  - 1
            Month + 12
          Wend
         
          st\wYear   = Year
          st\wMonth  = Month
          st\wDay    = Day
          st\wHour   = Hour
          st\wMinute = Minute
          st\wSecond = Second
         
          SystemTimeToFileTime_(@st, @ft)
         
          ; Zeit in Sekunden umrechnen
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          GetLocalTime_(@st)
          SystemTimeToFileTime_(@st, @ft)
         
          ; Zeit in Sekunden umrechnen
          ProcedureReturn (PeekQ(@ft) - #HundredNanosecondsFrom_1Jan1601_To_1Jan1970) / #HundredNanosecondsInOneSecond
        EndIf
      CompilerCase #PB_OS_Linux
        Protected.tm tm
        Protected.q time
        Protected *Memory_localtime
       
        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
          ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          time = time_(0)
          If time > -1
            *Memory_localtime = AllocateMemory(SizeOf(tm))
           
            If *Memory_localtime
              localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
              time = mktime_(*Memory_localtime)
              FreeMemory(*Memory_localtime)
              If time > -1
                ProcedureReturn time
              EndIf
            EndIf
          EndIf
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm tm
        Protected.q time
        Protected *Memory_localtime
       
        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
          ProcedureReturn mktime_(@tm) + #SecondsInOneHour ; Rückgabewert von mktime ist eine Stunde zu wenig
        Else ; Kein gültiges Datum. Systemzeit wird ermittelt
          time = time_(0)
          If time > -1
            *Memory_localtime = AllocateMemory(SizeOf(tm))
            If *Memory_localtime
              localtime_r_(@time, *Memory_localtime) ; Per Memory ist es thread-sicher
              time = mktime_(*Memory_localtime)
              FreeMemory(*Memory_localtime)
              If time > -1
                ProcedureReturn time
              EndIf
            EndIf
          EndIf
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Year64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wYear
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Year
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Year = *Memory_localtime\tm_year + 1900
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Year
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Year
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Year = *Memory_localtime\tm_year + 1900
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Year
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Month64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wMonth
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Month
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
        *Memory_localtime = AllocateMemory(SizeOf(tm))

        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Month = *Memory_localtime\tm_mon + 1
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Month
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Month
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Month = *Memory_localtime\tm_mon + 1
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Month
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Day64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wDay
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Day
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Day = *Memory_localtime\tm_mday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Day
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Day
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Day = *Memory_localtime\tm_mday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Day
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Hour64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wHour
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Hour
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Hour = *Memory_localtime\tm_hour
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Hour
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Hour
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Hour = *Memory_localtime\tm_hour
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Hour
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Minute64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wMinute
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Minute
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Minute = *Memory_localtime\tm_min
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Minute
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Minute
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Minute = *Memory_localtime\tm_min
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Minute
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i Second64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wSecond
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  Second
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Second = *Memory_localtime\tm_sec
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Second
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  Second
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          Second = *Memory_localtime\tm_sec
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn Second
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i DayOfWeek64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.SYSTEMTIME st
       
        Date = Date * #HundredNanosecondsInOneSecond + #HundredNanosecondsFrom_1Jan1601_To_1Jan1970
        FileTimeToSystemTime_(@Date, @st)
       
        ProcedureReturn st\wDayOfWeek
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  DayOfWeek
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfWeek = *Memory_localtime\tm_wday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfWeek
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  DayOfWeek
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfWeek = *Memory_localtime\tm_wday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfWeek
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  EndProcedure
 
  Procedure.i DayOfYear64(Date.q)
    CompilerSelect #PB_Compiler_OS
      CompilerCase #PB_OS_Windows
        Protected.q TempDate
       
        TempDate = Date64(Year64(Date))
       
        ProcedureReturn (Date - TempDate) / #SecondsInOneDay + 1
      CompilerCase #PB_OS_Linux
        Protected.tm *Memory_localtime
        Protected.i  DayOfYear
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
       
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfYear = *Memory_localtime\tm_yday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfYear + 1
        Else
          ProcedureReturn -1
        EndIf
      CompilerCase #PB_OS_MacOS
        Protected.tm *Memory_localtime
        Protected.i  DayOfYear
       
        Date - #SecondsInOneHour ; Hinzugerechnete Stunde wieder abziehen
       
        *Memory_localtime = AllocateMemory(SizeOf(tm))
        If *Memory_localtime
          localtime_r_(@Date, *Memory_localtime)
          DayOfYear = *Memory_localtime\tm_yday
          FreeMemory(*Memory_localtime)
         
          ProcedureReturn DayOfYear + 1
        Else
          ProcedureReturn -1
        EndIf
    CompilerEndSelect
  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.s, Date.q)
    Protected.s Retval
   
    Retval = ReplaceString(Mask,   "%yyyy", RSet(Str(Year64(Date)),   4, "0"))
    Retval = ReplaceString(Retval, "%yy",   RSet(Right(Str(Year64(Date)), 2), 2, "0"))
    Retval = ReplaceString(Retval, "%mm",   RSet(Str(Month64(Date)),  2, "0"))
    Retval = ReplaceString(Retval, "%dd",   RSet(Str(Day64(Date)),    2, "0"))
    Retval = ReplaceString(Retval, "%hh",   RSet(Str(Hour64(Date)),   2, "0"))
    Retval = ReplaceString(Retval, "%ii",   RSet(Str(Minute64(Date)), 2, "0"))
    Retval = ReplaceString(Retval, "%ss",   RSet(Str(Second64(Date)), 2, "0"))
   
    ProcedureReturn Retval
  EndProcedure
 
  Procedure.q ParseDate64(Mask.s, Date.s)
    Protected.i i, DatePos = 1, IsVariableFound, Year, Month = 1, Day = 1, Hour, Minute, Second
    Protected.s 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
            Debug "Year: " + Str(Year)
            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
            Debug "Year: " + Str(Year)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%mm"
            IsVariableFound = #True
            Month = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Monatszahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%mm" überspringen
            Debug "Month: " + Str(Month)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%dd"
            IsVariableFound = #True
            Day = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Tageszahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%dd" überspringen
            Debug "Day: " + Str(Day)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%hh"
            IsVariableFound = #True
            Hour = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Stundenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%hh" überspringen
            Debug "Hour: " + Str(Hour)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%ii"
            IsVariableFound = #True
            Minute = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Minutenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%ii" überspringen
            Debug "Minute: " + Str(Minute)
            Continue
          EndIf
         
          If Mid(Mask, i, 3) = "%ss"
            IsVariableFound = #True
            Second = Val(Mid(Date, DatePos, 2))
            DatePos + 2 ; Die 2 Nummern der Sekundenzahl überspringen
            i + 2       ; Die 3 Zeichen der Variable "%ss" überspringen
            Debug "Second: " + Str(Second)
            Continue
          EndIf
         
          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
  ;-Test
 
  UseModule Date64
 
  For jahr = 1970 To 2038 Step 1
    d1.s = FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date(jahr,3,1,0,0,0))
    d2.s = FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64(jahr,3,1,0,0,0))
    If d1 <> d2
      Debug d1
      Debug d2
      Debug ""
    EndIf
  Next
 
  Debug DayOfWeek(Date())
  Debug DayOfWeek64(Date64())
  Debug ""
  Debug FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date(1600,1,1,0,0,0))
  Debug FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64(2300,1,1,0,0,0))
  Debug FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date(1971,8,20,0,0,0))
  Debug FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64(1971,8,20))
  Debug FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date())
  Debug FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64())
CompilerEndIf


Gruß
Thomas

_________________
PureBasic 5.71 | SpiderBasic 2.21 | Windows 10 Pro (x64) | Linux Mint 19.2 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild


Zuletzt geändert von ts-soft am 24.03.2014 09:13, insgesamt 2-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 24.03.2014 08:49 
Offline
-= Anfänger =-
Benutzeravatar

Registriert: 29.08.2004 03:07
ts-soft hat geschrieben:
Hab jetzt noch kleinere Anpassungen vorgenommen, vor allem die Structure für Linux und Mac angepasst.
Unter MacOS sollte noch mal jemand testen, der die Möglichkeit hat, bei mir läuft es unter Win und Lin in allen Modi.

In der Procedure Date64 fehlte ein 'Protected *Memory_localtime' für Mac OS X. Habe es als Zeile 200 eingefügt.

Die Zeilen 197 bis 202:
Code:
      CompilerCase #PB_OS_MacOS
        Protected.tm tm
        Protected.q time
        Protected *Memory_localtime ; Hinzugefügt
       
        If Year > -1 ; Gültiges Datum

Danach lief es.

Ausgabe mit PB 32bit auf Mac OS X:
Code:
1969.12.31 23:59:59
1970.01.01 00:59:59

1
1

1969.12.31 23:59:59
1970.01.01 00:59:59
1971.08.20 00:00:00
1971.08.20 00:00:00
2014.03.24 07:27:19
2014.03.24 06:27:19

Ausgabe mit PB 64bit auf Mac OS X:
Code:
1969.12.31 23:59:59
2038.03.01 00:00:00

1
1

1969.12.31 23:59:59
2300.01.01 00:00:00
1971.08.20 00:00:00
1971.08.20 00:00:00
2014.03.24 07:30:02
2014.03.24 06:30:02

Habe es jetzt nicht weiter angeschaut, aber scheint wohl nur mit 64bit brauchbar zu sein.
Wenn dem so ist, wäre es wohl besser einen CompilerError einzufügen, wenn man PB 32bit verwendet.

Aber:
Code:
  Debug FormatDate("%yyyy.%mm.%dd %hh:%ii:%ss", Date(1600,1,1,0,0,0))
  Debug FormatDate64("%yyyy.%mm.%dd %hh:%ii:%ss", Date64(1600,1,1,0,0,0))

Ausgabe mit PB 64bit auf Mac OS X:
Code:
1969.12.31 23:59:59
1970.01.01 00:59:59
Da stimmt etwas noch nicht mit kleinen Jahreszahlen. 2300 funktioniert aber.

_________________
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Date64 - Unixtime 64bit
BeitragVerfasst: 24.03.2014 09:09 
Offline
Benutzeravatar

Registriert: 08.09.2004 00:57
Wohnort: Berlin
Danke Danilo fürs testen :allright:

Hab jetzt im obigen Code die fehlende Deklaration für MacOS eingefügt, sowie den CompilerError für MacOS 32-Bit.

Gruß
Thomas

_________________
PureBasic 5.71 | SpiderBasic 2.21 | Windows 10 Pro (x64) | Linux Mint 19.2 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild


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 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 2 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:  
cron

 


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