Everything works fine but the days value is invalid, looks like (bug->month->day) it's broken after year calculation and everything after fails because of that...
Code: Select all
Structure LARGE_INTEGER_
StructureUnion
x.LARGE_INTEGER
QuadPart.q
EndStructureUnion
EndStructure
Structure TIME_FIELDS
Year.c ; range [1601...]
Month.c ; range [1..12]
Day.c ; range [1..31]
Hour.c ; range [0..23]
Minute.c ; range [0..59]
Second.c ; range [0..59]
Milliseconds.c ; range [0..999]
Weekday.c ; range [0..6] == [Sunday..Saturday]
EndStructure ; TIME_FIELDS
#TICKSPERMIN = 600000000
#TICKSPERSEC = 10000000
#TICKSPERMSEC = 10000
#SECSPERDAY = 86400
#SECSPERHOUR = 3600
#SECSPERMIN = 60
#MINSPERHOUR = 60
#HOURSPERDAY = 24
#EPOCHWEEKDAY = 1
#DAYSPERWEEK = 7
#EPOCHYEAR = 1601
#DAYSPERNORMALYEAR = 365
#DAYSPERLEAPYEAR = 366
#MONSPERYEAR = 12
Procedure YearLengths(LeapYear.l)
If LeapYear
ProcedureReturn #DAYSPERLEAPYEAR ; 366
Else
ProcedureReturn #DAYSPERNORMALYEAR ; 365
EndIf
EndProcedure
Procedure.l IsLeapYear(Year.l)
If Year < 1600
ProcedureReturn Bool(Year % 4 = 0)
Else
ProcedureReturn Bool((Year % 4 = 0 And (Year % 100) <> 0) Or (Year % 400) = 0)
EndIf
EndProcedure
Procedure DaysSinceEpoch(Year.l)
Protected Days.i
Year-1 ; Don't include a leap day from the current year
Days = Year * #DAYSPERNORMALYEAR + Year / 4 - Year / 100 + Year / 400
Days - (#EPOCHYEAR - 1) * #DAYSPERNORMALYEAR + (#EPOCHYEAR - 1) / 4 - (#EPOCHYEAR - 1) / 100 + (#EPOCHYEAR - 1) / 400
ProcedureReturn Days
EndProcedure
Procedure TimeToSystemTime(*Time.LARGE_INTEGER_, *TimeFields.TIME_FIELDS)
Protected SecondsInDay.l
Protected CurYear.l
Protected LeapYear.l
Protected CurMonth.l
Protected Days.l
Protected IntTime.q = *Time\QuadPart
; Extract millisecond from time And convert time into seconds
*TimeFields\Milliseconds = (IntTime % #TICKSPERSEC) / #TICKSPERMSEC
IntTime = IntTime / #TICKSPERSEC
; Split the time into days And seconds within the day
Days = IntTime / #SECSPERDAY
SecondsInDay = IntTime % #SECSPERDAY
; Compute time of day
*TimeFields\Hour = SecondsInDay / #SECSPERHOUR
SecondsInDay = SecondsInDay % #SECSPERHOUR
*TimeFields\Minute = SecondsInDay / #SECSPERMIN
*TimeFields\Second = SecondsInDay % #SECSPERMIN
; Compute day of week
*TimeFields\Weekday = (#EPOCHWEEKDAY + Days) % #DAYSPERWEEK
; Compute year
CurYear = #EPOCHYEAR
CurYear + (Days / #DAYSPERLEAPYEAR)
Days = Days - DaysSinceEpoch(CurYear)
Repeat
LeapYear = IsLeapYear(CurYear)
If Days < YearLengths(LeapYear)
Break
EndIf
CurYear+1
Days - YearLengths(LeapYear)
ForEver
*TimeFields\Year = CurYear
; Compute month of year
Protected Dim MontsArray.c(11)
MontsArray(0) = 31
MontsArray(1) = 28 + IsLeapYear(CurYear)
MontsArray(2) = 31
MontsArray(3) = 30
MontsArray(4) = 31
MontsArray(5) = 30
MontsArray(6) = 31
MontsArray(7) = 31
MontsArray(8) = 30
MontsArray(9) = 31
MontsArray(10) = 30
MontsArray(11) = 31
For CurMonth = 0 To 11
If Days >= MontsArray(CurMonth)
Days - MontsArray(CurMonth)
EndIf
Next
*TimeFields\Month = CurMonth ; (+1)
*TimeFields\Day = Days ; (+1)
FreeArray(MontsArray())
EndProcedure
Define Time.q = 131902383805223176
Define TimeFields.TIME_FIELDS
TimeToSystemTime(@Time, @TimeFields)
Debug Str(TimeFields\Year)+"."+Str(TimeFields\Month)+"."+Str(TimeFields\Day)+" "+Str(TimeFields\Weekday)+" "+RSet(Str(TimeFields\Hour), 2, "0")+":"+RSet(Str(TimeFields\Minute), 2, "0")+":"+Str(TimeFields\Second)+":"+Str(TimeFields\Milliseconds)
;Validate
st.SYSTEMTIME
FileTimeToSystemTime_(@Time, @st)
Debug Str(st\wYear)+"."+Str(st\wMonth)+"."+Str(st\wDay)+" "+Str(st\wDayOfWeek)+" "+RSet(Str(st\wHour), 2, "0")+":"+RSet(Str(st\wMinute), 2, "0")+":"+Str(st\wSecond)+":"+Str(st\wMilliseconds)