Seite zurück / Previous page
links
Seite vor / Next page
rechts
Kapitel zurück / Previous Chapter
zurück
Kapitel vor / Next Chapter
vor
Seitenanfang / Top of page
oben
Seitenende / End of page
unten
DD380800.HTM
DD-Software.DATETIME
Add this page to your favorites
Save this document

Date and Time Functions


DATETIME.WBT   Version 1.19  2003:10:02

User Defined Functions Library for WinBatch.

Includes calculations for German Holidays.
Enthält Berechnungen für deutsche Feiertage.


If you have questions about WinBatch, you are encouraged to use online WebBoard BBS at http://webboard.windowware.com


;==========================================================================================================================================
; udflib.DateTime.wbt
;==========================================================================================================================================
; Date and Time Functions v1.19
; User Defined Functions for WinBatch.
;
; Detlev Dalitz.20010325.20020201.20020709.20020719.20020722.20020723.20020725.20020804.20021112.20021202...
; ...20030213.20030604.20030620.20030711.20030819.20030820.20030920.20030924.20030925.20031002.
;==========================================================================================================================================

;==========================================================================================================================================
; Overview
;------------------------------------------------------------------------------------------------------------------------------------------
; udfSayNoYes (bool)                  ; Returns string "No" or "Yes"
;------------------------------------------------------------------------------------------------------------------------------------------
; udfTimeFormatStr (YmdHms,TaggedStr) ; Returns string formatted as defined in TaggedStr
;------------------------------------------------------------------------------------------------------------------------------------------
; udfIsValidDate (YmdHms)             ; Returns boolean, false or true (0..1)
; udfIsValidDateTime (YmdHms)         ; Returns boolean, false or true (0..1)
;------------------------------------------------------------------------------------------------------------------------------------------
; udfIsLeapYear (YmdHms)              ; Returns boolean, false or true (0..1)
; udfIsJulianLeapYear (YmdHms)        ; Returns boolean, false or true (0..1)
;------------------------------------------------------------------------------------------------------------------------------------------
; udfJulianDayOfWeek (YmdHms)         ; Returns number, range=0..6 = Sunday..Saturday
; udfDayOfWeek (YmdHms)               ; Returns number, range=1..7 = Monday..Sunday
; udfDayOfYear (YmdHms)               ; Returns number, range=1..366
; udfWeekOfYear (YmdHms)              ; Returns number, range=0..53
; udfWeekOfMonth (sYmdHms, iMode)     ; Returns number, range=1..6
;------------------------------------------------------------------------------------------------------------------------------------------
; udfNameOfDay (sYmdHms, iLength)     ; Returns string of at least iLength number of characters. Range iLength=0..n
; udfNameOfMonth (sYmdHms, iLength)   ; Returns string of at least iLength number of characters. Range iLength=0..n
;------------------------------------------------------------------------------------------------------------------------------------------
; udfTimeDMY (YmdHms)                 ; Returns string formatted as "dd.mm.yyyy"
; udfTimeDMYShort (YmdHms)            ; Returns string formatted as "ddd dd.mm.yyyy"
; udfTimeDMYLong (YmdHms)             ; Returns string formatted as "dddd dd.mm.yyyy"
;------------------------------------------------------------------------------------------------------------------------------------------
; udfDaysInYear (YmdHms)              ; Returns number, range=365..366
; udfDaysInMonth (YmdHms)             ; Returns number, range=28..31
; udfGetLastDayOfMonth (sYmdHms)      ; Returns datetime string  ; The day item is set to the last day of given month.
; udfGetLastDayOfMonth_2 (sYmdHms)    ; Returns datetime string  ; The day item is set to the last day of given month.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfIsLastDayInMonth (YmdHms)        ; Returns boolean, false or true (0..1)
; udfIsFirstDayOfMonth (YmdHms)       ; Returns boolean, false or true (0..1)
; udfIsLastDayOfMonth (YmdHms)        ; Returns boolean, false or true (0..1)
; udfIsNthDayOfMonth (n, YmdHms)      ; Returns boolean, false or true (0..1)
; udfIsWeekDay (YmdHms)               ; Returns boolean, false or true (0..1)  ; True if day is Monday,Tuesday,Wednesday,Thursday,Friday.
; udfIsWeekendDay (YmdHms)            ; Returns boolean, false or true (0..1)  ; True if day is Saturday,Sunday.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetCountDowInMonth (sYmdHms, iDayOfWeek)              ; Returns number, range=1..5  ; uses iDayOfWeek = 0..6 = Sunday..Saturday
; udfGetNthDowInMonth (sYmdHms, iOccurrence, iDayOfWeek)   ; Returns datetime string     ; uses iDayOfWeek = 0..6 = Sunday..Saturday
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetWeekDayNext (YmdHms)          ; Returns datetime string
; udfGetWeekDayPrev (YmdHms)          ; Returns datetime string
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetSundayOfWeek (YmdHms)         ; Returns datetime string  ; leaves Hms as is
; udfGetMondayOfWeek (YmdHms)         ; Returns datetime string  ; leaves Hms as is
; udfGetTuesdayOfWeek (YmdHms)        ; Returns datetime string  ; leaves Hms as is
; udfGetWednesdayOfWeek (YmdHms)      ; Returns datetime string  ; leaves Hms as is
; udfGetThursdayOfWeek (YmdHms)       ; Returns datetime string  ; leaves Hms as is
; udfGetFridayOfWeek (YmdHms)         ; Returns datetime string  ; leaves Hms as is
; udfGetSaturdayOfWeek (YmdHms)       ; Returns datetime string  ; leaves Hms as is
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetYmd (sYmdHms)                 ; Returns the Ymd date part of the specified sYmdhms.
; udfGetHms (sYmdHms)                 ; Returns the Hms time part of the specified sYmdhms.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfSetYmd (sYmdHms, sYmd)           ; Sets the Ymd date part of the sYmdHms to the specified sYmd date value.
; udfSetHms (sYmdHms, sHms)           ; Sets the Hms time part of the sYmdHms to the specified sHms time value.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetYear (sYmdHms)                ; Returns the number of the year of the specified date.
; udfGetMonth (sYmdHms)               ; Returns the number of the month of the specified date.
; udfGetDay (sYmdHms)                 ; Returns the number of the day of the specified date.
; udfGetHour (sYmdHms)                ; Returns the number of the hour of the specified date.
; udfGetMinute (sYmdHms)              ; Returns the number of the minute of the specified date.
; udfGetSecond (sYmdHms)              ; Returns the number of the second of the specified date.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfSetYear (sYmdHms, iYear)         ; Sets the year to the specified value.
; udfSetMonth (sYmdHms, iMonth)       ; Sets the month to the specified value.
; udfSetDay (sYmdHms, iDay)           ; Sets the day to the specified value.
; udfSetHour (sYmdHms, iHour)         ; Sets the hour to the specified value.
; udfSetMinute (sYmdHms, iMinute)     ; Sets the minute to the specified value.
; udfSetSecond (sYmdHms, iSecond)     ; Sets the second to the specified value.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfSecondsToDhms (iSeconds, iMode)  ; Returns numbers for days, hours, minutes, seconds for a given number of seconds.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfYmdHmsToHTTPStamp (sYmdHms, iMode) ; Returns string formatted as (1) "Sun, 06 Nov 1994 08:49:37 GMT"  ; RFC 822, updated by RFC 1123
;                                       ; Returns string formatted as (2) "Sunday, 06-Nov-94 08:49:37 GMT" ; RFC 850, obsoleted by RFC 1036
;                                       ; Returns string formatted as (3) "Sun Nov  6 08:49:37 1994"       ; ANSI C's asctime() format
;                                       ; Returns string formatted as (4) "1994-11-06T08:49:37"            ; ISO 8601 format
;                                       ; Returns string formatted as (5) "19941106T084937"                ; ISO 8601 compacted format
;------------------------------------------------------------------------------------------------------------------------------------------
; udfYmdHmsToYwd (sYmdHms, iMode)     ; Returns ISO 8601 notation for the week in a formatted string like "yyyyWwwd".
; udfYwdtoYmdHms (sYwd)               ; Returns the YmdHms datetime string available from ISO 8601 week notation string.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfRoundToMinute (sYmdHms, iMode)   ; Returns datetime string.
; udfRoundToHour (sYmdHms, iMode)     ; Returns datetime string.
; udfRoundToDay (sYmdHms, iMode)      ; Returns datetime string.
; udfRoundToMonth (sYmdHms, iMode)    ; Returns datetime string.
; udfRoundToYear (sYmdHms, iMode)     ; Returns datetime string.
; udfRoundToQuarter (sYmdHms, iMode)  ; Returns datetime string.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfAgeDifference (sYmdHms1, sYmdHms2, iMode) ; Returns integer number.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfYmdHmsToUnixSeconds (YmdHms)     ; Returns number UnixTimeStamp 0..999999999..?
; udfUnixSecondsToYmdHms (Seconds)    ; Returns datetime string
;------------------------------------------------------------------------------------------------------------------------------------------
; udfHmsToDecimalHour (Hms)           ; Returns decimal number
; udfDecimalHourToYmdHms (fDecHour)   ; Returns datetime string
;------------------------------------------------------------------------------------------------------------------------------------------
; udfYmdHmsToFloat (sYmdHms)          ; Returns floating point number that represents the DateTime.
; udfFloatToYmdHms (fDateTime)        ; Returns datetime string on a given floating point number that represents the DateTime.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfStrDateTo3Char (sYmdHms)         ; Returns a three-character string suitable for use as the prefix for a file name.
; udfStrDateTo4Char (sYmdHms)         ; Returns a four-character string suitable for use as the prefix for a file name.
; udfStrDateTo8Char (sYmdHms)         ; Returns a eight-character string suitable for use as a dos file name.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfCalendar (YmdHms)                ; Returns a small calendar table.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetSeason (sYmdHms)              ; Returns a string containing the name of the season for the given date.
; udfGetZodiac (sYmdHms)              ; Returns a string containing the name of the zodiac sign for the given date.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfEasterSunday_Gauss (sYmdHms)            ; Returns datetime string.
; udfEasterSunday_Schlyter (sYmdHms)         ; Returns datetime string.
; udfEasterSunday_Lilius_Clavius (sYmdHms)   ; Returns datetime string.
; udfEasterSunday_Passah (sYmdHms)           ; Returns datetime string.
; udfEasterSunday (sYmdHms)                  ; Returns datetime string.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGetTimezoneInfo()                ; Returns a tab delimited list about Daylight saving and Standard time settings.
;------------------------------------------------------------------------------------------------------------------------------------------
; udfGD_AscherMittwoch (YmdHms)       ; Returns datetime string
; udfGD_PalmSonntag (YmdHms)          ; Returns datetime string
; udfGD_KarFreitag (YmdHms)           ; Returns datetime string
; udfGD_OsterSonntag (YmdHms)         ; Returns datetime string
; udfGD_OsterMontag (YmdHms)          ; Returns datetime string
; udfGD_WeisserSonntag (YmdHms)       ; Returns datetime string
; udfGD_ChristiHimmelfahrt (YmdHms)   ; Returns datetime string
; udfGD_PfingstSonntag (YmdHms)       ; Returns datetime string
; udfGD_PfingstMontag (YmdHms)        ; Returns datetime string
; udfGD_Fronleichnam (YmdHms)         ; Returns datetime string
; udfGD_MariaeHimmelfahrt (YmdHms)    ; Returns datetime string
; udfGD_TagDerEinheit (YmdHms)        ; Returns datetime string
; udfGD_Reformationstag (YmdHms)      ; Returns datetime string
; udfGD_HeiligAbend (YmdHms)          ; Returns datetime string
; udfGD_ErsterWeihnachten (YmdHms)    ; Returns datetime string
; udfGD_ZweiterWeihnachten (YmdHms)   ; Returns datetime string
; udfGD_Silvester (YmdHms)            ; Returns datetime string
; udfGD_Neujahr (YmdHms)              ; Returns datetime string
; udfGD_ErsterAdvent (YmdHms)         ; Returns datetime string
; udfGD_ZweiterAdvent (YmdHms)        ; Returns datetime string
; udfGD_DritterAdvent (YmdHms)        ; Returns datetime string
; udfGD_VierterAdvent (YmdHms)        ; Returns datetime string
; udfGD_BussUndBettag (YmdHms)        ; Returns datetime string
; udfGD_HeiligeDreiKoenige (YmdHms)   ; Returns datetime string
; udfGD_Allerheiligen (YmdHms)        ; Returns datetime string
; udfGD_TagDerArbeit (YmdHms)         ; Returns datetime string
;------------------------------------------------------------------------------------------------------------------------------------------
; udfNameOfGD (YmdHms)                ; Returns string (fast speed)
; udfNameOfGD2 (YmdHms)               ; Returns string (slow speed)
; udfGDHashTable (YmdHms, Mode)       ; Returns string (middle speed)
;                                   ... Returns string Mode=0 => creates hash table
;                                   ... Returns string Mode=1 => Name of German Holiday
;                                   ... Returns string Mode=2 => List of German Holidays
;==========================================================================================================================================



;==========================================================================================================================================
; User Defined Functions for Date and Time Calculations.
;==========================================================================================================================================

;==========================================================================================================================================
#DefineFunction udfSayNoYes (bool) ; returns string "No" or "Yes" ; for test purposes
NoYesArray = Arrayize("Nein,Ja",",")
;NoYesArray = Arrayize("No,Yes",",")
Return (NoYesArray[bool])
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfIsValidDate (sYmdHms) ; returns boolean, false or true (0..1)
ciYmdLen = 10 ; StrLen("0000:00:00")
sYmd = StrSub(sYmdHms,1,ciYmdLen)
If (StrLen(sYmd)!=ciYmdLen) Then Return (@FALSE)
iLastErrorMode = ErrorMode(@OFF)
LastError()
TimeDiffDays(sYmd,sYmd)
ErrorMode(iLastErrorMode)
Return (LastError()==0)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfIsValidDateTime (sYmdHms) ; returns boolean, false or true (0..1)
ciYmdHmsLen = 19 ; StrLen("0000:00:00:00:00:00")
If (StrLen(sYmdHms)!=ciYmdHmsLen) Then Return (@FALSE)
iLastErrorMode = ErrorMode(@OFF)
LastError()
TimeDiff(sYmdHms,sYmdHms)
ErrorMode(iLastErrorMode)
Return (LastError()==0)
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfIsLeapYear (YmdHms) ; returns boolean, false or true (0..1)
Year = ItemExtract(1,YmdHms,":")
Return ((0==(year mod 4))&&(0!=(year mod 4000))&&((0!=(year mod 100))||(0==(year mod 400))))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfIsJulianLeapYear (sYmdHms) ; returns boolean, false or true (0..1)
iYear = ItemExtract(1,sYmdHms,":")
Return (TimeJulianDay(StrCat(iYear,":03:01"))-TimeJulianDay(StrCat(iYear,":02:28"))>1)
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfJulianDayOfWeek (sYmdHms) ; returns number, range 0..6
Return ((TimeJulianDay(sYmdHms)+5) mod 7) ; Range=0..6 = Sunday..Saturday
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfDayOfWeek (sYmdHms) ; returns number, range 1..7
iJulianDow = (TimeJulianDay(sYmdHms)+5) mod 7
Return (iJulianDow+(7*!iJulianDow)) ; Range=1..7 = Monday..Sunday
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfDayOfYear (sYmdHms) ; returns number, range=1..366
Return (1+TimeDiffDays(sYmdHms,StrCat(ItemExtract(1,sYmdHms,":"),":01:01:00:00:00")))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfWeekOfYear (sYmdHms) ; returns number, range 0..53
iJulianNow     = TimeJulianDay(sYmdHms)
iJulianJan4    = TimeJulianDay(StrCat(ItemExtract(1,sYmdHms,":"),":01:04:00:00:00"))
iJulianDowJan4 = (iJulianJan4+5) mod 7 ; Range=0..6 = Sunday..Saturday
iJulianMonday  = 1+iJulianJan4-iJulianDowJan4-(7*!iJulianDowJan4)
iWeek          = (iJulianNow-iJulianMonday)/7
iWeek          = iWeek+(iJulianNow>=iJulianMonday)
Return (iWeek)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
;   #DefineFunction udfWeekOfMonth (sYmdHms) ; Returns number, range 1..6.
;   Return (udfWeekOfYear(sYmdHms) - udfWeekOfYear(udfSetDay(sYmdHms,1)) + 1)
;   #EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfWeekOfMonth (sYmdHms, iMode)
iDay = ItemExtract(3,sYmdHms,":")
iDow = (7 + TimeJulianDay(sYmdHms) - iDay - iMode) mod 7
If !iDow Then iDow = 7
iDay = iDay + iDow - 2
Return (1 + (iDay / 7))
;..........................................................................................................................................
; This function udfWeekOfMonth returns the number of the week within the month
; that is given by the first parameter sYmdHms datetime string.
; This function returns a number in range 1..6.
;
; The second parameter iMode controls whether a week begins with Sunday or Monday.
; iMode = 0 ... Week begins with Sunday.
; iMode = 1 ... Week begins with Monday.
;
; Detlev Dalitz.20030819
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfNameOfDay (sYmdHms, iLength)   ; Returns string.
sOut = ItemExtract(1+((TimeJulianDay(sYmdHms)+5) mod 7),"Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag",",")
; sOut = ItemExtract(1+((TimeJulianDay(sYmdHms)+5) mod 7),"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",",")
iLength = Max(0,iLength)
If !!iLength Then sOut = StrFix(sOut," ",iLength)
Return (sOut)
; Returns a string with at least iLength number of characters.
; Use iLength=0 for returning the trimmed length of day name as is.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfNameOfMonth (sYmdHms, iLength) ; Returns string.
sOut = ItemExtract(ItemExtract(2,sYmdHms,":"),"Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",",")
; sOut = ItemExtract(ItemExtract(2,sYmdHms,":"),"January,February,March,April,May,June,July,August,September,October,November,December",",")
iLength = Max(0,iLength)
If !!iLength Then sOut = StrFix(sOut," ",iLength)
Return (sOut)
; Returns a string with at least iLength number of characters.
; Use iLength=0 for returning the trimmed length of month name as is.
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfTimeDMY (YmdHms) ; returns string formatted as "dd.mm.yyyy"
DTArray = Arrayize(YmdHms,":")
Return (StrCat(DTArray[2],".",DTArray[1],".",DTArray[0]))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfTimeDMYShort (YmdHms) ; returns string formatted as "ddd dd.mm.yyyy"
DTArray = Arrayize(YmdHms,":")
Return (StrCat(udfNameOfDay(YmdHms,3)," ",DTArray[2],".",DTArray[1],".",DTArray[0]))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfTimeDMYLong (YmdHms) ; returns string formatted as "dddd dd.mm.yyyy"
DTArray = Arrayize(YmdHms,":")
Return (StrCat(udfNameOfDay(YmdHms,0)," ",DTArray[2],".",DTArray[1],".",DTArray[0]))
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfDaysInYear (YmdHms)
Return (udfIsLeapYear(YmdHms) + 365)
; Returns number, range 365..366.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfDaysInMonth (sYmdHms)
iDaysInMonth = ItemExtract(ItemExtract(2,sYmdHms,":"),"31,28,31,30,31,30,31,31,30,31,30,31",",")
If (iDaysInMonth==28) Then iDaysInMonth = iDaysInMonth+udfIsLeapYear(sYmdHms)
Return (iDaysInMonth)
; Returns number, range=28..31.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetLastDayOfMonth (sYmdHms)
Return (ItemReplace(udfDaysInMonth(sYmdHms),3,sYmdHms,":"))
; Returns YmdHms datetime string.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetLastDayOfMonth_2 (sYmdHms)
Return (TimeSubtract(ItemReplace(1,3,TimeAdd(sYmdHms,"0:1:0"),":"),"0:0:1"))
; Returns YmdHms datetime string, leaves Hms as is.
; I prefer this version of udfGetLastDayOfMonth.
; LastDayofNextMonth = TimeSubtract(ItemReplace(1,3,TimeAdd(sYmdHms,"0:2:0"),":"),"0:0:1")
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfIsLastDayInMonth (YmdHms) ; returns boolean, false or true (0..1)
YmdHmsArray = Arrayize(YmdHms,":")
Return (YmdHmsArray[2]==udfDaysInMonth(YmdHms))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfisfirstdayofmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfisfirstdayofmonth

#DefineFunction udfIsFirstDayOfMonth (sYmdHms)
Return (1==(0+ItemExtract(3,sYmdHms,":")))
#EndFunction

:skip_udfisfirstdayofmonth
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfislastdayofmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfislastdayofmonth

#DefineFunction udfIsLastDayOfMonth (sYmdHms)
Return ((0+ItemExtract(2,sYmdHms,":"))!=(0+ItemExtract(2,TimeAdd(sYmdHms,"0:0:1:0:0:0"),":")))
#EndFunction

:skip_udfislastdayofmonth
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfisnthdayofmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfisnthdayofmonth

#DefineFunction udfIsNthDayOfMonth (n, sYmdHms)
If ((n<1)||(n>31))
   Return ((0+ItemExtract(2,sYmdHms,":"))!=(0+ItemExtract(2,TimeAdd(sYmdHms,"0:0:1:0:0:0"),":")))
Else
   Return (n==(0+ItemExtract(3,sYmdHms,":")))
EndIf
; to refer to the "last day" of month use any n out of range 1..31, e.g. n=0
#EndFunction

:skip_udfisnthdayofmonth
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfgetcountdowinmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetcountdowinmonth

#DefineFunction udfGetCountDOWInMonth (sYmdHms, iDayOfWeek)                 ; With iDayOfWeek = 0..6 = Sunday..Saturday.
iDayOfWeek = Min(6,Max(-1,iDayOfWeek))                 ; Limit iDayOfWeek to -1..0..6 days. -1 means current DayofWeek of sYmdHms.
If (iDayOfWeek<0) Then iDayOfWeek = ((TimeJulianDay(sYmdHms)+5) mod 7)      ; 0..6 = Sunday..Saturday.
iMonth = ItemExtract(2,sYmdHms,":")                                         ; Store iMonth for later check.
sYmdHms = ItemReplace("01",3,sYmdHms,":")                                   ; Set the 01.mm.yyyy of month.
iFirstDay = ((TimeJulianDay(sYmdHms)+5) mod 7)                              ; Sunday=0
sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:",(7+iDayOfWeek-iFirstDay) mod 7))    ; Add diff. days to the first occurrence.
iCount = 0
While (iMonth==ItemExtract(2,sYmdHms,":"))
   iCount = iCount+1
   sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:",7))                              ; Add weeks.
EndWhile
Return (iCount)
;..........................................................................................................................................
; This Function "udfGetCountDowInMonth" returns the number of times
; the specified day of the week occurs in the month containing the date.
; If you pass a iDayOfWeek value of -1, then the function counts the number of times the day
; indicated by the date parameter occurs within its own month.
;
; Detlev Dalitz.20020720
;..........................................................................................................................................
#EndFunction

:skip_udfgetcountdowinmonth
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetnthdowinmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetnthdowinmonth

#DefineFunction udfGetNthDOWInMonth (sYmdHms, iOccurrence, iDayOfWeek)
; With iDayOfWeek = 0..6 ; Sunday..Saturday.
@YM0 = "0:0:0"
@YM7 = "0:0:7"
@YMD = "0:0:D"
@D   = "D"
@58  = ":"
iOccurrence = Min(5,Max(1,iOccurrence))                                             ; Limit to 1..5 weeks.
iDayOfWeek  = Min(6,Max(0,iDayOfWeek))                                              ; Limit to 0..6 days.
iMonth  = ItemExtract(2,sYmdHms,@58)                                                ; Save for later check.
sYmdHms = ItemReplace(1,3,sYmdHms,@58)                                              ; Set the 01.mm.yyyy of month.
iFirstDay = ((TimeJulianDay(sYmdHms)+5) mod 7)                                      ; Sunday=0
If ((iOccurrence==1)&&(iDayOfWeek==iFirstDay)) Then Return (TimeAdd(sYmdHms,@YM0))  ; Return if first day of month hits the rule.
sYmdHms = TimeAdd(sYmdHms,StrReplace(@YMD,@D,(7+iDayOfWeek-iFirstDay) mod 7))       ; Add diff. days to the first occurrence.
If (iOccurrence==1) Then Return (sYmdHms)                                           ; Return if this day hits the rule.
sYmdHms = TimeAdd(sYmdHms,StrReplace(@YMD,@D,(7*(iOccurrence-1))))                  ; Add diff. weeks to hit the rule.
If (iMonth!=ItemExtract(2,sYmdHms,@58)) Then sYmdHms = TimeSubtract(sYmdHms,@YM7)   ; Fallback if necessary and subtract 7 days.
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfGetNthDowInMonth" returns the Nth occurence of the day of the week
; (for example, the second Tuesday) in the specified month.
; If the Nth day cannot be resolved in this month, then the last occurence of day will be returned.
; (for example : the fifth Thursday in July 2002 does not exist (actually it will be calculated to the 01.08.2002),
; so this function returns the last 'good' Thursday 25.07.2002.
;..........................................................................................................................................
#EndFunction

:skip_udfgetnthdowinmonth
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfgetweekdaynext",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetweekdaynext

#DefineFunction udfGetWeekDayNext (sYmdHms)
iJulianNow = TimeJulianDay(sYmdHms)
While 1
   iJulianNow = iJulianNow+1
   iJulianDowNow = (iJulianNow+5) mod 7
   If (6!=iJulianDowNow) Then If (0!=iJulianDowNow) Then Break ; if not a weekend day then break
EndWhile
Return (TimeJulToYmd(iJulianNow))
;..........................................................................................................................................
; This Function "udfGetWeekDayNext" returns a DateTime string containing the next WeekDay.
; The date whose following weekday (Monday through Friday) is returned.
; Skips over the Weekend if necessary. No check about holidays which are reside on weekdays.
;
; Detlev Dalitz.20020723
;..........................................................................................................................................
#EndFunction

:skip_udfgetweekdaynext
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetweekdayprev",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetweekdayprev

#DefineFunction udfGetWeekDayPrev (sYmdHms)
iJulianNow = TimeJulianDay(sYmdHms)
While 1
   iJulianNow = iJulianNow-1
   iJulianDowNow = (iJulianNow+5) mod 7
   If (6!=iJulianDowNow) Then If (0!=iJulianDowNow) Then Break ; if not a weekend day then break
EndWhile
Return (TimeJulToYmd(iJulianNow))
;..........................................................................................................................................
; This Function "udfGetWeekDayPrev" returns a DateTime string containing the previous WeekDay.
; The date whose previous weekday (Monday through Friday) is returned.
; Skips over the Weekend if necessary. No check about holidays which are reside on weekdays.
;
; Detlev Dalitz.20020723
;..........................................................................................................................................
#EndFunction

:skip_udfgetweekdayprev
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfGetSundayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetMondayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:1"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetTuesdayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:2"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetWednesdayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:3"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetThursdayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:4"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetFridayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:5"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetSaturdayOfWeek (YmdHms) ; returns datetime string ; leaves Hms untouched
Return (TimeAdd(TimeSubtract(YmdHms,StrCat("0:0:",(TimeJulianDay(YmdHms)+5) mod 7)),"0:0:6"))
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfisweekday",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfisweekday

#DefineFunction udfIsWeekDay (YmdHms)
iJulianDow = ((TimeJulianDay(YmdHms)+5) mod 7)
If (6==iJulianDow) Then Return (@FALSE)
If (0==iJulianDow) Then Return (@FALSE)
Return (@TRUE)
; "Is Date A Weekday"
; Returns @True if a date is a weekday such as Monday, Tuesday, Wednesday, Thursday, or Friday.
#EndFunction

:skip_udfisweekday
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfisweekendday",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfisweekendday

#DefineFunction udfIsWeekendDay (YmdHms)
iJulianDow = ((TimeJulianDay(YmdHms)+5) mod 7)
If (6==iJulianDow) Then Return (@TRUE)
If (0==iJulianDow) Then Return (@TRUE)
Return (@FALSE)
; "Is Date A Weekend Day"
; Returns @True if a date is a weekend day such as Saturday or Sunday.
#EndFunction

:skip_udfisweekendday
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfgetymd",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetymd

#DefineFunction udfGetYmd (sYmdHms)
Return (StrSub(sYmdHms,1,10))
; This Function "udfGetYmd" returns the Ymd date part of the specified sYmdhms.
#EndFunction

:skip_udfgetymd
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgethms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgethms

#DefineFunction udfGetHms (sYmdHms)
Return (StrSub(sYmdHms,12,-1))
; This Function "udfGetHms" returns the Hms time part of the specified sYmdhms.
#EndFunction
If ItemLocate("udfsetymd",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetymd
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfsetymd",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetymd

#DefineFunction udfSetYmd (sYmdHms, sYmd)
sYmdHms = ItemReplace(ItemExtract(1,sYmd,":"),1,sYmdHms,":")
sYmdHms = ItemReplace(ItemExtract(2,sYmd,":")-1,2,sYmdHms,":")
sYmdHms = ItemReplace(ItemExtract(3,sYmd,":")-1,3,sYmdHms,":")
Return (TimeAdd("0000:01:01:00:00:00",sYmdHms)) ; make valid datetime string
; This Function "udfSetYmd" sets the Ymd date part of the sYmdHms to the specified sYmd date value.
#EndFunction

:skip_udfsetymd
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsethms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsethms

#DefineFunction udfSetHms (sYmdHms, sHms)
sYmdHms = ItemReplace("00",4,sYmdHms,":")
sYmdHms = ItemReplace("00",5,sYmdHms,":")
sYmdHms = ItemReplace("00",6,sYmdHms,":")
Return (TimeAdd(sYmdHms,StrCat("0:0:0:",sHms))) ; make valid datetime string
; This Function "udfsetHms" sets the Hms time part of the sYmdHms to the specified sHms time value.
#EndFunction

:skip_udfsethms
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfgetyear",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetyear

#DefineFunction udfGetYear (sYmdHms)
Return (ItemExtract(1,sYmdHms,":"))
; This Function "udfGetYear" returns the number of the year of the specified date.
#EndFunction

:skip_udfgetyear
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetmonth

#DefineFunction udfGetMonth (sYmdHms)
Return (ItemExtract(2,sYmdHms,":"))
; This Function "udfGetMonth" returns the number of the month of the specified date.
#EndFunction

:skip_udfgetmonth
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetday",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetday

#DefineFunction udfGetDay (sYmdHms)
Return (ItemExtract(3,sYmdHms,":"))
; This Function "udfGetDay" returns the number of the day of the specified date.
#EndFunction

:skip_udfgetday
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgethour",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgethour

#DefineFunction udfGetHour (sYmdHms)
Return (ItemExtract(4,sYmdHms,":"))
; This Function "udfGetHour" returns the number of the hour of the specified date.
#EndFunction

:skip_udfgethour
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetminute",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetminute

#DefineFunction udfGetMinute (sYmdHms)
Return (ItemExtract(5,sYmdHms,":"))
; This Function "udfGetMinute" returns the number of the minute of the specified date.
#EndFunction

:skip_udfgetminute
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetsecond",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetsecond

#DefineFunction udfGetSecond (sYmdHms)
Return (ItemExtract(6,sYmdHms,":"))
; This Function "udfGetSecond" returns the number of the second of the specified date.
#EndFunction

:skip_udfgetsecond
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfsetyear",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetyear

#DefineFunction udfSetYear (sYmdHms, iYear)
Return (TimeAdd(ItemReplace("0000",1,sYmdHms,":"),StrCat(iYear,":0:0:0:0:0"))) ; make valid datetime string
; This Function "udfSetYear" sets the year to the specified value.
#EndFunction

:skip_udfsetyear
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsetmonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetmonth

#DefineFunction udfSetMonth (sYmdHms, iMonth)
Return (TimeAdd(ItemReplace("01",2,sYmdHms,":"),StrCat("0:",iMonth-1,":0:0:0:0"))) ; make valid datetime string
; This Function "udfSetMonth" sets the month to the specified value.
#EndFunction

:skip_udfsetmonth
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsetday",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetday

#DefineFunction udfSetDay (sYmdHms, iDay)
Return (TimeAdd(ItemReplace("01",3,sYmdHms,":"),StrCat("0:0:",iDay-1,":0:0:0"))) ; make valid datetime string
; This Function "udfSetDay" sets the day to the specified value.
#EndFunction

:skip_udfsetday
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsethour",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsethour

#DefineFunction udfSetHour (sYmdHms, iHour)
Return (TimeAdd(ItemReplace("00",4,sYmdHms,":"),StrCat("0:0:0:",iHour,":0:0"))) ; make valid datetime string
; This Function "udfSetHour" sets the hour to the specified value.
#EndFunction

:skip_udfsethour
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsetminute",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetminute

#DefineFunction udfSetMinute (sYmdHms, iMinute)
Return (TimeAdd(ItemReplace("00",5,sYmdHms,":"),StrCat("0:0:0:0:",iMinute,":0"))) ; make valid datetime string
; This Function "udfSetMinute" sets the minute to the specified value.
#EndFunction

:skip_udfsetminute
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfsetsecond",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsetsecond

#DefineFunction udfSetSecond (sYmdHms, iSecond)
Return (TimeAdd(ItemReplace("00",6,sYmdHms,":"),StrCat("0:0:0:0:0:",iSecond))) ; make valid datetime string
; This Function "udfSetSecond" sets the second to the specified value.
#EndFunction

:skip_udfsetsecond
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfsecondstodhms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfsecondstodhms

#DefineFunction udfSecondsToDhms (iSeconds, iMode)
iDays    = iSeconds / 86400
iSeconds = iSeconds mod 86400
iHours   = iSeconds / 3600
iSeconds = iSeconds mod 3600
iMinutes = iSeconds / 60
iSeconds = iSeconds mod 60

If Min(Max(0,iMode),1) Then Return (StrCat(iDays,@TAB,iHours,@TAB,iMinutes,@TAB,iSeconds))

; English Version.
sOut = "!1 Day!5  !2 Hour!6  !3 Minute!7  !4 Second!8"
sOut = StrReplace(StrReplace(StrReplace(StrReplace(sOut,"!5",StrSub("s",iDays!=1,1)),"!6",StrSub("s",iHours!=1,1)),"!7",StrSub("s",iMinutes!=1,1)),"!8",StrSub("s",iSeconds!=1,1))
sOut = StrReplace(StrReplace(StrReplace(StrReplace(sOut,"!1",iDays),"!2",iHours),"!3",iMinutes),"!4",iSeconds)
Return (sOut)

;   ; German Version.
;   sOut = "!1 Tag!5  !2 Stunde!6  !3 Minute!7  !4 Sekunde!8"
;   sOut = StrReplace(StrReplace(StrReplace(StrReplace(sOut,"!5",StrSub("e",iDays!=1,1)),"!6",StrSub("n",iHours!=1,1)),"!7",StrSub("n",iMinutes!=1,1)),"!8",StrSub("n",iSeconds!=1,1))
;   sOut = StrReplace(StrReplace(StrReplace(StrReplace(sOut,"!1",iDays),"!2",iHours),"!3",iMinutes),"!4",iSeconds)
;   Return (sOut)

;..........................................................................................................................................
; This Function "udfSecondsToDhms" accepts an integer number of seconds,
; and returns numbers for days, hours, minutes, seconds calculated accordingly.
; Output string can be modified by parameter iMode.
;
; iMode=0 ... Returns a formatted textstring, e.g. "1 Day  2 Hours  1 Minute 4 Seconds".
; iMode=1 ... Returns a tab delimited itemlist, e.g. "1@TAB2@TAB1@TAB4".
;
; Detlev Dalitz.20030110
;..........................................................................................................................................
#EndFunction

:skip_udfsecondstodhms
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfymdhmstohttpstamp",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfymdhmstohttpstamp

#DefineFunction udfYmdHmsToHTTPStamp (sYmdHms, iMode)
iMode  = Min(5,Max(1,iMode)) ; Force iMode=1..5.
sYear  = ItemExtract(1,sYmdHms,":")
sMonth = ItemExtract(2,sYmdHms,":")
sDay   = ItemExtract(3,sYmdHms,":")
sHms   = StrSub(sYmdHms,12,8)
sMName = ItemExtract(sMonth,"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",",")
sDName = ItemExtract(1+((TimeJulianDay(sYmdHms)+5) mod 7),"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",",")
Select iMode
Case 1
   sHTTPStamp = StrCat(StrSub(sDName,1,3),', ',sDay,' ',sMName,' ',sYear,' ',sHms,' GMT')
   Break
Case 2
   sHTTPStamp = StrCat(sDName,', ',sDay,'-',sMName,'-',StrSub(sYear,3,2),' ',sHms,' GMT')
   Break
Case 3
   sHTTPStamp = StrCat(StrSub(sDName,1,3),' ',sMName,' ',StrFixLeft(0+sDay,' ',2),' ',sHms,' ',sYear)
   Break
Case 4
   sHTTPStamp = StrCat(sYear,'-',sMonth,'-',sDay,'T',sHms)
   Break
Case 5
   sHTTPStamp = StrCat(sYear,sMonth,sDay,'T',StrReplace(sHms,":",""))
   Break
EndSelect
Return (sHTTPStamp)
;..........................................................................................................................................
; This function udfYmdHmsToHTTP (sYmdHms, iMode) returns a string representation of date/time stamps for HTTP applications.
;
; iMode=1 : "Sun, 06 Nov 1994 08:49:37 GMT"  ; RFC 822, updated by RFC 1123
; iMode=2 : "Sunday, 06-Nov-94 08:49:37 GMT" ; RFC 850, obsoleted by RFC 1036
; iMode=3 : "Sun Nov  6 08:49:37 1994"       ; ANSI C's asctime() format
; iMode=4 : "1994-11-06T08:49:37"            ; ISO 8601 (European Standard EN 28601) (see altered German standard DIN 5008)
; iMode=5 : "19941106T084937"                ; ISO 8601 compacted
;
; The first format is preferred as an Internet standard and
; represents a fixed-length subset of that defined by RFC 1123 (an update to RFC 822).
; The second format is in common use, but is based on the obsolete RFC 850 date format and lacks a four-digit year.
;
; HTTP/1.1 clients and servers that parse the date value MUST accept
; all three formats (iMode=1..3) (for compatibility with HTTP/1.0), though they MUST
; only generate the RFC 1123 (iMode=1) format for representing HTTP-date values in header fields.
;
; All HTTP date/time stamps MUST be represented in Greenwich Mean Time (GMT) without exception.
; For the purposes of HTTP, GMT is exactly equal to UTC (Coordinated Universal Time).
; This is indicated in the first two formats by the inclusion of "GMT"
; as the three-letter abbreviation for time zone, and MUST be assumed when reading the asctime format.
; HTTP-date is case sensitive and MUST NOT include additional linear white spaces.
;
;..........................................................................................................................................
#EndFunction

:skip_udfymdhmstohttpstamp
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfymdhmstoywd",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfymdhmstoywd

#DefineFunction udfYmdHmsToYwd (sYmdHms, iMode)
iJulianNow = TimeJulianDay(sYmdHms)
iJulianDowNow = (iJulianNow + 5) mod 7 ; Number of the day. Range=0..6 = Sunday..Saturday.
If !iJulianDowNow Then iJulianDowNow = 7 ; Make the Julian Sunday the last day in a Calendar week.
iJulian = iJulianNow - iJulianDowNow
iJulianMon = iJulian + 1 ; Monday begins the Calendar week.
sYmdHmsMon = TimeJulToYmd(iJulianMon)
sYearMon = ItemExtract(1,sYmdHmsMon,":")
sYwd = sYearMon
sYmdHmsWeek = sYmdHmsMon
iMonth = Int(ItemExtract(2,sYmdHms,":"))
If ((iMonth==12)||(iMonth==1))
   iDay = Int(ItemExtract(3,sYmdHms,":"))
   If ((iDay>25)||(iDay<7))
      iJulianSun = iJulian + 7 ; Sunday ends the Calendar week.
      sYmdHmsSun = TimeJulToYmd(iJulianSun)
      sYearSun = ItemExtract(1,sYmdHmsSun,":")
      If (sYearSun>sYearMon)
         iJulianJan4 = TimeJulianDay(StrCat(sYearSun,":01:04:00:00:00"))
         iJulianDowJan4 = (iJulianJan4 + 5) mod 7 ; Number of the day. Range=0..6 = Sunday..Saturday.
         If !iJulianDowJan4 Then iJulianDowJan4 = 7 ; Make the Julian Sunday the last day in a Calendar week.
         If (iJulianDowJan4>3)
            sYwd = sYearSun
            sYmdHmsWeek = sYmdHmsSun
         EndIf
      EndIf
   EndIf
EndIf
sYwd = StrCat(sYwd,"W",StrFixLeft(udfWeekOfYear(sYmdHmsWeek),"0",2))
If Min(1,Max(0,iMode)) Then sYwd = StrCat(sYwd,iJulianDowNow)
Return (sYwd)
;..........................................................................................................................................
; This Function "udfYmdHmsToYwd" returns ISO 8601 standard notation
; for the given YmdHms datetime string in a formatted string like "yyyyWwwd".
; For example, the first week of the year 1997 lasts from 1996-12-30 to 1997-01-05 and
; can be written in standard notation as "1997W01",
; and "1996:12:31" becomes "1997W012".
; iMode=0 ... Format "yyyyWww"
; iMode=1 ... Format "yyyyWwwd" ; appends the calendarian number of the day of the week, with d=1..7 = Monday..Sunday.
;
; Detlev Dalitz.20030820
;..........................................................................................................................................
#EndFunction

:skip_udfymdhmstoywd
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfywdtoymdhms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfywdtoymdhms

#DefineFunction udfYwdtoYmdHms (sYwd)
iJulianJan4 = TimeJulianDay(StrCat(StrSub(sYwd,1,4),":01:04:00:00:00"))
iJulianDay = (iJulianJan4-((iJulianJan4 + 5) mod 7)) + (7*(StrSub(sYwd,6,2)-1)) + Max(1,StrCat("0",StrSub(sYwd,8,1)))
Return (TimeJulToYmd(iJulianDay))
;..........................................................................................................................................
; This Function "udfYwdToYmdHms" returns the ymdHms DateTime string available from the given Ywd YearWeekDay string.
; Input string sYwd can be formatted as "yyyyWwwd" or "yyyyWww".
; If the day number is ommitted, then this udf returns the Monday of the given week.
;
; Note: The String sYwd is not checked about valid content.
; The YearWeek string "2001W53" may be logical invalid but will be calculated to "2001:12:31:00:00:00" Monday.
; The YearWeekDay string "2001W537" may be logical invalid but will be calculated to "2002:01:06:00:00:00" Sunday.
;
; Detlev Dalitz.20020722
;..........................................................................................................................................
#EndFunction

:skip_udfywdtoymdhms
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfroundtominute",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtominute

#DefineFunction udfRoundToMinute (sYmdHms, iMode)
If !Min(1,Max(0,iMode))
   sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:0:0:",(ItemExtract(6,sYmdHms,":")>29),":0"))
EndIf
sYmdHms = StrCat(StrSub(sYmdHms,1,17),"00")
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfRoundToMinute" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor minute.
;..........................................................................................................................................
#EndFunction

:skip_udfroundtominute
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfroundtohour",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtohour

#DefineFunction udfRoundToHour (sYmdHms, iMode)
If !Min(1,Max(0,iMode))
   sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:0:",(ItemExtract(5,sYmdHms,":")>29),":0:0"))
EndIf
sYmdHms = StrCat(StrSub(sYmdHms,1,14),"00:00")
Return (sYmdHms)
; This Function "udfRoundToHour" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor hour.
;
#EndFunction

:skip_udfroundtohour
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfroundtoday",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtoday

#DefineFunction udfRoundToDay (sYmdHms, iMode)
If !Min(1,Max(0,iMode))
   sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:",(ItemExtract(4,sYmdHms,":")>11),":0:0:0"))
EndIf
sYmdHms = StrCat(StrSub(sYmdHms,1,11),"00:00:00")
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfRoundToDay" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor day.
;..........................................................................................................................................
#EndFunction

:skip_udfroundtoday
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfroundtomonth",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtomonth

#DefineFunction udfRoundToMonth (sYmdHms, iMode)
If !Min(1,Max(0,iMode))
   sYmdHms = TimeAdd(sYmdHms,StrCat("0:",(ItemExtract(3,sYmdHms,":")>15),":0:0:0:0"))
EndIf
sYmdHms = StrCat(StrSub(sYmdHms,1,8),"01:00:00:00")
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfRoundToMonth" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor month.
;..........................................................................................................................................
#EndFunction

:skip_udfroundtomonth
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfroundtoyear",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtoyear

#DefineFunction udfRoundToYear (sYmdHms, iMode)
If !Min(1,Max(0,iMode))
   sYmdHms = TimeAdd(sYmdHms,StrCat((ItemExtract(2,sYmdHms,":")>6),":0:0:0:0:0"))
EndIf
sYmdHms = StrCat(StrSub(sYmdHms,1,5),"01:01:00:00:00")
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfRoundToYear" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor year.
;..........................................................................................................................................
#EndFunction

:skip_udfroundtoyear
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfroundtoquarter",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfroundtoquarter

#DefineFunction udfRoundToQuarter (sYmdHms, iMode)
Mode = Min(1,Max(0,iMode))
sYear = ItemExtract(1,sYmdHms,":")
Select (ItemExtract(2,sYmdHms,":")/3)
Case 0
   iMonth = 1
   If !Mode Then If (sYmdHms>StrCat(sYear,":02:14:00:00:00")) Then iMonth = 4
   Break
Case 1
   iMonth = 4
   If !Mode Then If (sYmdHms>StrCat(sYear,":05:15:00:00:00")) Then iMonth = 7
   Break
Case 2
   iMonth = 7
   If !Mode Then If (sYmdHms>StrCat(sYear,":08:15:00:00:00")) Then iMonth = 10
   Break
Case 3
   iMonth = 10
   If !Mode Then If (sYmdHms>StrCat(sYear,":11:15:00:00:00")) Then iMonth = 13
   Break
EndSelect
sYmdHms = ItemReplace("01",2,sYmdHms,":")
sYmdHms = TimeAdd(sYmdHms,StrCat("0:",iMonth-1,":0:0:0:0"))
sYmdHms = StrCat(StrSub(sYmdHms,1,8),"01:00:00:00")
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfRoundToQuarter" returns a DateTime string.
; iMode=0 ... Round up or Down.
; iMode=1 ... Truncate to floor quarter.
;..........................................................................................................................................
#EndFunction

:skip_udfroundtoquarter
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfagedifference",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfagedifference

#DefineFunction udfAgeDifference (sYmdHms1, sYmdHms2, iMode) ; returns integer number
If !Min(1,Max(0,iMode))
   sYmdHms1 = StrCat(StrSub(sYmdHms1,1,10),":00:00:00")
   sYmdHms2 = StrCat(StrSub(sYmdHms2,1,10),":00:00:00")
EndIf
If (sYmdHms1>sYmdhms2)
   sYmdHms = TimeDiff(sYmdHms1,sYmdhms2)
Else
   sYmdHms = TimeDiff(sYmdHms2,sYmdhms1)
EndIf
Return (0+ItemExtract(1,sYmdHms,":"))
;..........................................................................................................................................
; Returns the difference in years between the two dates sYmdHms1 and sYmdHms2.
; iMode=0 ... The time part of the DateTime is ommitted resp. forced to "00:00:00".
; iMode=1 ... The time part of the DateTime strings is considered within the calculation.
;
; Detlev Dalitz.20020723
;..........................................................................................................................................
#EndFunction

:skip_udfagedifference
;==========================================================================================================================================



;==========================================================================================================================================
#DefineFunction udfYmdHmsToUnixSeconds (YmdHms) ; returns number UnixTimeStamp
Return (TimeDiffSecs(YmdHms,"1970:01:01:00:00:00"))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfUnixSecondsToYmdHms (Seconds) ;  returns datetime string
Return (TimeAdd("1970:01:01:00:00:00",StrCat("0:0:0:0:0:",Seconds)))
; Note: Unix Time cannot go past 68 years from 1970 (2038).
#EndFunction
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfhmstodecimalhour",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfhmstodecimalhour

#DefineFunction udfHmsToDecimalHour (Hms)
iCount = ItemCount(Hms,":")
If (iCount<3) Then Return (0)
iSeconds = ItemExtract(iCount  ,Hms,":")
iMinutes = ItemExtract(iCount-1,Hms,":")
iHours   = ItemExtract(iCount-2,Hms,":")
Return (iHours + (iMinutes/60.0) + (iSeconds/3600.0))
;..........................................................................................................................................
; This Function "udfHmsToDecimal" converts a Hms string
; into a decimal number of hours, e.g. from "12:56:34" to 12.942778.
; Note: Hms must be a ItemList of at least three Items, e.g. "123:45:34",
; representing "Hours:Minutes:Seconds", otherwise the udf returns zero.
; It is possible to feed a YmdHms datetime string as input parameter.
; Only the last three Items Hours, Minutes, Seconds will be extracted.
; Note: iHours, iMinutes, iSeconds must be evaluated to integer numbers. No special validation here.
;..........................................................................................................................................
#EndFunction

:skip_udfhmstodecimalhour
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfdecimalhourtoymdhms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfdecimalhourtoymdhms

#DefineFunction udfDecimalHourToYmdHms (fDecHour)
Return (TimeDiff(TimeAdd("1900:01:01",StrCat("0:0:0:0:0:",Int(fDecHour*3600))),"1900:1:1"))
;..........................................................................................................................................
; This Function "udfDecimalHourToYmdHms" converts a decimal number of hours
; into a YmdHms datetime string representing a time range of
; Years, Months, Days, Hours, Minutes, and Seconds,
; e.g. from  12.942778 to "0000:00:00:12:56:34",
; e.g. from 125.084167 to "0000:00:05:05:05:03".
;..........................................................................................................................................
#EndFunction

:skip_udfdecimalhourtoymdhms
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfymdhmstofloat",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfymdhmstofloat

#DefineFunction udfYmdHmsToFloat (sYmdHms)
sYmdHms = TimeAdd(sYmdHms,"0:0:0:0:0:0") ; make valid datetime string
iDayAdjust=693960
iSecondsPerDay=86400
iDay=TimeJulianDay(sYmdHms)
iDay=iDay-iDayAdjust
ihh=ItemExtract(4,sYmdHms,":")
imm=ItemExtract(5,sYmdHms,":")
iss=ItemExtract(6,sYmdHms,":")
iSeconds=3600*ihh + 60*imm + iss
fFraction=1.0*iSeconds/iSecondsPerDay
fDateTime=iDay+fFraction
Return (fDateTime)
;..........................................................................................................................................
; This Function "udfYmdHmsToFloat" returns a number in float format
; that represents the timepoint given by a YmdHms DateTime string.
; This float number is compatible with the double number that is created by
; the Microsoft Windows system function "SystemTimeToVariantTime".
; It is the default Win32 time/date data format supported by Windows NT and Windows 95.
;
; Examples:
; "1899:12:29:00:00:00" --> -1.0
; "1899:12:30:00:00:00" --> 0.0
; "1899:12:31:00:00:00" --> 1.0
; "1900:01:01:00:00:00" --> 2.0
; "1900:01:02:00:00:01" --> 3.00001157407407
; "1900:01:03:00:00:02" --> 4.00002314814815
; "2003:06:20:07:20:00" --> 37792.305555555556
;
;
; Detlev Dalitz.20030620
; based on request by "Beat beat.riederer@dbs.ch, Thursday, June 19, 2003 07:53 AM"
; answered by "Marty marty+bbs@winbatch.com, Thursday, June 19, 2003 11:16 PM"
;..........................................................................................................................................
#EndFunction

:skip_udfymdhmstofloat
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udffloattoymdhms",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udffloattoymdhms

#DefineFunction udfFloatToYmdHms (fDateTime)
iDayAdjust=693960
iSecondsPerDay=86400
iDay=Int(Floor(fDateTime))
fFraction=fDateTime-iDay
iDay=iDay+iDayAdjust
iSeconds=Int(fFraction*iSecondsPerDay)
sYmdHms=TimeJulToYmd(iDay)
sYmdHms=TimeAdd(sYmdHms,StrCat("0:0:0:0:0:",iSeconds)) ; make valid datetime string
Return (sYmdHms)
;..........................................................................................................................................
; This Function "udfFloatToYmdHms" returns a DateTime string
; that represents the Datetime given by a float number.
; The float number has to be compatible with the double number that is created by
; the Microsoft Windows system function "SystemTimeToVariantTime".
; It is the default Win32 time/date data format supported by Windows NT and Windows 95.
;
; Examples:
; -1.0                --> "1899:12:29:00:00:00"
; 0.0                 --> "1899:12:30:00:00:00"
; 1.0                 --> "1899:12:31:00:00:00"
; 2.0                 --> "1900:01:01:00:00:00"
; 3.00001157407407    --> "1900:01:02:00:00:01"
; 4.00002314814815    --> "1900:01:03:00:00:02"
; 37792.305555555556  --> "2003:06:20:07:19:55" ; should be "2003:06:20:07:20:00"
; There seems to be some WinBatch related number rounding problem on the seconds fraction part.
;
; Detlev Dalitz.20030620.20031020.
;..........................................................................................................................................
#EndFunction

:skip_udffloattoymdhms
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfstrdateto3char",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfstrdateto3char

#DefineFunction udfStrDateTo3Char (sYmdHms)
Return (StrCat(StrSub(ItemExtract(1,sYmdHms,":"),4,1),Num2Char(64+ItemExtract(2,sYmdHms,":")),Num2Char((ItemExtract(3,sYmdHms,":")&31)+48+7*((ItemExtract(3,sYmdHms,":")&31)>9))))
;..........................................................................................................................................
; "Date To Three Character String"
; This Function "udfStrDateTo3Char" converts the date portion of a datetime string into a three-character string.
; The resolution is one day.  The range is one decade.
; This string is suitable for use as the prefix for a file name.
;
; The return value is composed of:
; 1) the last digit of the year (0..9)
; 2) the month represented by a letter (A..L)
; 3) the day represented by an alphanumeric (1..9, A..V), that is (1..9, 10..31)
;
; Note: No validation of input sYmdHms here. sYmdHms must contain a valid date.
;..........................................................................................................................................
#EndFunction

:skip_udfstrdateto3char
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfstrdateto4char",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfstrdateto4char

#DefineFunction udfStrDateTo4Char (sYmdHms)
Return (StrCat(StrSub(ItemExtract(1,sYmdHms,":"),4,1),Num2Char(64+ItemExtract(2,sYmdHms,":")),ItemExtract(3,sYmdHms,":")))
;..........................................................................................................................................
; "Date To Four Character String"
; This Function "udfStrDateTo4Char" converts the date portion of a datetime string into a four-character string.
; The resolution is one day.  The range is one decade.
; This string is suitable for use as the prefix for a file name.
;
; The return value is composed of:
; 1) the last digit of the year (0..9)
; 2) the month represented by a letter (A..L)
; 3) the day (01..31)
;
; Note: No validation of input sYmdHms here. sYmdHms must contain a valid date.
;..........................................................................................................................................
#EndFunction

:skip_udfstrdateto4char
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfstrdateto8char",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfstrdateto8char

#DefineFunction udfStrDateTo8Char (sYmdHms)
Return (StrCat(StrSub(ItemExtract(1,sYmdHms,":"),4,1),Num2Char(64+ItemExtract(2,sYmdHms,":")),ItemExtract(3,sYmdHms,":"),ItemExtract(4,sYmdHms,":"),ItemExtract(5,sYmdHms,":")))
;..........................................................................................................................................
; "Date And Time To Eight Character String"
; This Function "udfStrDateTo8Char" converts a datetime string into an eight-character string
; that can be used as a (DOS short) file name.
; The range is one decade. The resolution is one minute.
;
; The return value is composed of:
;    1) the last digit of the year (0..9)
;    2) the month represented by a letter (A..L)
;    3) the day (01..31)
;    4) the hour (00..23)
;    5) the minutes (00..59)
;
; Note: No validation of input sYmdHms here. sYmdHms must contain a valid date.
;..........................................................................................................................................
#EndFunction

:skip_udfstrdateto8char
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfcalendar",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfcalendar

#DefineFunction udfCalendar (sYmdHms)

iDayWidthMax  = 3 ; Default=Minimum=3; Maybe enlarge this value to spread the table in horizontal direction.
iDayMax       = 7
iWeekWidthMax = 3
iLineMax      = (iDayMax*iDayWidthMax)+iWeekWidthMax+StrLen(@CRLF)
iRowMax       = 8
iCalSizeMax   = iLineMax*iRowMax
iOffsCrLf     = iLineMax-2
iOffsYear     = (iDayMax*iDayWidthMax)-1
iOffsMonth    = 0
iOffsWeek     = 1+iOffsYear+iLineMax+iLineMax
iOffsDayNames = iLineMax
iOffsDayTab   = iOffsDayNames+iLineMax

sMonthNameList = "Januar,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember"
sDayNameList = "Mo,Di,Mi,Do,Fr,Sa,So"
;sMonthNameList = "January,February,March,April,May,June,July,August,September,October,November,December"
;sDayNameList = "Mo,Tu,We,Th,Fr,Sa,Su"

iYear  = 0+ItemExtract(1,sYmdHms,":")
iMonth = 0+ItemExtract(2,sYmdHms,":")
sMonthName = ItemExtract(iMonth,sMonthNameList,",")

hbbCal = BinaryAlloc(iCalSizeMax)
BinaryEodSet(hbbCal,iCalSizeMax)
BinaryReplace(hbbCal,""," ",@TRUE)

While (iOffsCrLf<iCalSizeMax)
   BinaryPokeStr(hbbCal,iOffsCrLf,@CRLF)
   iOffsCrLf = iOffsCrLf+iLineMax
EndWhile

For iCol=1 To iDayMax
   BinaryPokeStr(hbbCal,iOffsDayNames,ItemExtract(iCol,sDayNameList,","))
   iOffsDayNames = iOffsDayNames+iDayWidthMax
Next

BinaryPokeStr(hbbCal,iOffsYear,iYear)
BinaryPokeStr(hbbCal,iOffsMonth,sMonthName)


sYmdHms = ItemReplace("01",3,sYmdHms,":")
iDow01   = (TimeJulianDay(sYmdHms)+5) mod 7 ; with 0..6 = Sunday..Saturday
If !iDow01 Then iDow01 = 7
sMonday  = TimeAdd(TimeSubtract(sYmdHms,StrCat("0:0:",iDow01)),"0:0:1")

sYmdHms = sMonday
iOffsRow = iOffsDayTab
iOffsCol = iOffsRow
iDay = 0
sWeek = ""
While 1
   For iCol=1 To iDayMax
      iMonthWork = 0+ItemExtract(2,sYmdHms,":")
      If (iMonth==iMonthWork)
         iDay = iDay+1
         BinaryPokeStr(hbbCal,iOffsCol,StrFixLeft(iDay," ",2))

         If (sWeek=="")
            sWeek = StrCat("W",StrFixLeft(udfWeekOfYear(sYmdHms),"0",2))
            BinaryPokeStr(hbbCal,iOffsWeek,sWeek)
         EndIf
      EndIf
      iOffsCol = iOffsCol + iDayWidthMax
      sYmdHms = TimeAdd(sYmdHms,StrCat("0:0:1"))
   Next

   iYearWork = 0+ItemExtract(1,sYmdHms,":")
   If (iYear<iYearWork) Then Break
   iMonthWork = 0+ItemExtract(2,sYmdHms,":")
   If (iMonth<iMonthWork) Then Break

   iOffsRow = iOffsRow+iLineMax
   iOffsCol = iOffsRow
   iOffsWeek = iOffsWeek+iLineMax
   sWeek = ""
EndWhile

sCal = BinaryPeekStr(hbbCal,0,iCalSizeMax)
BinaryFree(hbbCal)

Return (sCal)
;..........................................................................................................................................
; This Function "udfCalendar" returns a small calender table for the given year and month.
;
;   +------------------------+
;   |Januar              2003|
;   |Mo Di Mi Do Fr Sa So    |
;   |       1  2  3  4  5 W01|
;   | 6  7  8  9 10 11 12 W02|
;   |13 14 15 16 17 18 19 W03|
;   |20 21 22 23 24 25 26 W04|
;   |27 28 29 30 31       W05|
;   |                        |
;   +------------------------+
;
; Detlev Dalitz.20020721
;..........................................................................................................................................
#EndFunction

:skip_udfcalendar
;==========================================================================================================================================



;==========================================================================================================================================
If ItemLocate("udfgetseason",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetseason

#DefineFunction udfGetSeason (sYmdHms)
sDateList   = "03:21,06:22,09:23,12:22"
sSeasonList = "Winter,Frühling,Sommer,Herbst"
;sSeasonList = "Winter,Spring,Summer,Fall"
iSeasonMax = 4
sYmdHms = StrSub(sYmdHms,6,-1)
iSeason = !(sYmdHms<StrCat(ItemExtract(iSeasonMax,sDateList,","),":00:00:00"))
If !iSeason
   For iSeason=1 To iSeasonMax
      If (sYmdHms<StrCat(ItemExtract(iSeason,sDateList,","),":00:00:00")) Then Break
   Next
EndIf
Return (ItemExtract(iSeason,sSeasonList,","))
;..........................................................................................................................................
; "Date To Season Name"
; This Function "udfGetSeason" returns the name of the Season for the given date.
;..........................................................................................................................................
#EndFunction

:skip_udfgetSeason
;------------------------------------------------------------------------------------------------------------------------------------------
If ItemLocate("udfgetzodiac",IntControl(77,103,0,0,0),@TAB) Then Goto skip_udfgetzodiac

#DefineFunction udfGetZodiac (sYmdHms)
sDateList   = "01:21,02:20,03:21,04:21,05:22,06:22,07:24,08:24,09:24,10:24,11:23,12:22"
sZodiacList = "Steinbock,Wassermann,Fische,Widder,Stier,Zwillinge,Krebs,Löwe,Jungfrau,Waage,Skorpion,Schütze"
;sZodiacList = "Capricorn,Aquarius,Pisces,Aries,Taurus,Gemeni,Cancer,Leo,Virgo,Libra,Scorpio,Sagittarius"
iZodiacMax = 12
sYmdHms = StrSub(sYmdHms,6,-1)
iZodiac = !(sYmdHms<StrCat(ItemExtract(iZodiacMax,sDateList,","),":00:00:00"))
If !iZodiac
   For iZodiac=1 To iZodiacMax
      If (sYmdHms<StrCat(ItemExtract(iZodiac,sDateList,","),":00:00:00")) Then Break
   Next
EndIf
Return (ItemExtract(iZodiac,sZodiacList,","))
;..........................................................................................................................................
; "Date To Zodiac Name"
; This Function "udfGetZodiac" returns the name of the Zodiac sign for the given date.
;..........................................................................................................................................
#EndFunction

:skip_udfgetzodiac
;==========================================================================================================================================



;==========================================================================================================================================
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfEasterSunday_Gauss (sYmdHms) ; Returns DateTime string.
iYear = +ItemExtract(1,sYmdHms,":")
If (iYear<1900) Then Return ""
If (iYear>2099) Then Return ""
a = iYear mod 19
b = iYear mod 4
c = iYear mod 7
d = (19*a + 24) mod 30
e = (2*b + 4*c + 6*d + 5) mod 7
iDay = d + e + 22 ; = 22.03.yyyy + d + e
iMonth = 3
If (iDay<1)||(iDay>31)
   iMonth = 4
   iDay = d + e - 9  ; April.
   If (iDay==26) Then Day = 19
   If (iDay==25)
      If (d==28)
         If (e==6)
            If (a>10) Then iDay = 18
         EndIf
      EndIf
   EndIf
EndIf
Return (TimeAdd(StrCat(iYear,":",iMonth,":",iDay),"0:0:0")) ; Return normalized valid datetime string.
;..........................................................................................................................................
; Algorithm by Carl Friedrich Gauss (1777 - 1855)   (* valid years = 1900..2099 *)
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfEasterSunday_Schlyter (sYmdHms) ; Returns DateTime string.
iYear = +ItemExtract(1,sYmdHms,":")
a = iYear mod 19
b = iYear / 100
c = iYear mod 100
d = b / 4
e = b mod 4
f = (b + 8) / 25
g = (b - f + 1) / 3
h = (19*a + b - d - g + 15) mod 30
i = c / 4
k = c mod 4
l = (32 + 2*e + 2*i - h - k) mod 7
m = (a + 11*h + 22*l) / 451
n = (h + l - 7*m + 22) - 1
;n = (h + l - 7*m + 22) - 1
Return (TimeAdd(StrCat(iYear,":3:1"),StrCat("0:0:",n))) ; Return normalized valid datetime string.
;..........................................................................................................................................
; Dieser Algorithmus basiert nicht auf der Berechnung von Gauss und
; kommt ohne Ausnahmen aus (lt. Paul Schlyter).
; Werte ueber 31 bezeichnen den Tag im April-31,
; Werte darunter bezeichnen den Tag im Maerz.
; Note: Is Year>2568 invalid?
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfEasterSunday_Lilius_Clavius (sYmdHms) ; Returns DateTime string.
iYear = +ItemExtract(1,sYmdHms,":")
iGoldenNo = (iYear mod 19) + 1
iCentury = (iYear / 100) + 1
iLeapCent = (3 * iCentury / 4) - 12
iLunarCorr = ((8 * iCentury + 5) / 25) - 5
iSun = (5 * iYear / 4) - iLeapCent - 10
iEpact = Abs(11 * iGoldenNo + 20 + iLunarCorr - iLeapCent) mod 30
If (((iEpact == 25) && (iGoldenNo > 11)) || (iEpact == 24)) Then  iEpact = iEpact + 1
iFullMoon = 44 - iEpact
If (iFullMoon < 21) Then iFullMoon = iFullMoon + 30
iDay = iFullMoon + 7 - ((iSun + iFullMoon) mod 7)
If (iDay > 31)
   iDay = iDay - 31
   iMonth = 4
Else
   iMonth = 3
EndIf
Return (TimeAdd(StrCat(iYear,":",iMonth,":",iDay),"0:0:0")) ; Return normalized valid datetime string.
;..........................................................................................................................................
; Find Easter Sunday for a Given Year.
; Algorithm by Lilius & Clavius (16th Century)
; Donald Knuth - Art of Computer Programming 1.3.2 ex 14 (2nd set)
; Note: Is Year>2568 invalid?
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfEasterSunday_Passah (sYmdHms) ; Returns DateTime string.
aPassah = Arrayize("04:14,04:03,03:23,04:11,03:31,04:18,04:08,03:28,04:16,04:05,03:25,04:13,04:02,03:22,04:10,03:30,04:17,04:07,03:27",",")
iYear = ItemExtract(1,sYmdHms,":")
sYmd = StrCat(iYear,":",aPassah[iYear mod 19])
Return (TimeAdd(sYmd,StrCat("0:0:",7-((TimeJulianDay(sYmd)+5) mod 7)))) ; Return normalized valid datetime string.
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
; Dispatcher for testing.
#DefineFunction udfEasterSunday (YmdHms) ; Returns DateTime string.
;   Return (udfEasterSunday_Gauss(YmdHms))
;   Return (udfEasterSunday_Schlyter(YmdHms))
;   Return (udfEasterSunday_Lilius_Clavius(YmdHms))
Return (udfEasterSunday_Passah(YmdHms))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================




;==========================================================================================================================================
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGetTimezoneInfo()
TIME_ZONE_ID_INVALID  = -1
TIME_ZONE_ID_UNKNOWN  = 0
TIME_ZONE_ID_STANDARD = 1
TIME_ZONE_ID_DAYLIGHT = 2
@0 = ""
@58 = ":"
@000 = "0:0:0"
sResult = @0
sStandardDate = @0
iStandardBias = @0
sStandardName = @0
sDaylightDate = @0
iDaylightBias = @0
sDaylightName = @0
iCurrentBias  = @0
iYearNow = ItemExtract(1,TimeYmdHms(),@58)
hBB = BinaryAlloc(172) ; Buffer for TIME_ZONE_INFORMATION structure.
BinaryEodSet(hBB,172)
iResult = DllCall(StrCat(DirWindows(1),"Kernel32.dll"),long:"GetTimeZoneInformation",lpbinary:hBB)
sResult = StrCat(iResult,StrFill(@TAB,7))
Switch iResult
Case TIME_ZONE_ID_INVALID
Case TIME_ZONE_ID_UNKNOWN
   Break
Case TIME_ZONE_ID_DAYLIGHT
Case TIME_ZONE_ID_STANDARD
   iCurrentBias = BinaryPeek4(hBB,0)
   iMonth = BinaryPeek2(hBB,70)
   If (iMonth>0)
      iWeekDay    = BinaryPeek2(hBB,72)
      iOccurrence = BinaryPeek2(hBB,74)
      iHour       = BinaryPeek2(hBB,76)
      sStandardDate = TimeAdd(ItemReplace(iHour,4,udfGetNthDOWInMonth(StrCat(iYearNow,@58,iMonth,@58,1),iOccurrence,iWeekDay),@58),@000)
      iStandardBias = BinaryPeek4(hBB,84)
   EndIf
   iMonth = BinaryPeek2(hBB,154)
   If (iMonth>0)
      iWeekDay    = BinaryPeek2(hBB,156)
      iOccurrence = BinaryPeek2(hBB,158)
      iHour       = BinaryPeek2(hBB,160)
      sDaylightDate = TimeAdd(ItemReplace(iHour,4,udfGetNthDOWInMonth(StrCat(iYearNow,@58,iMonth,@58,1),iOccurrence,iWeekDay),@58),@000)
      iDaylightBias = BinaryPeek4(hBB,168)
   EndIf
   BinaryConvert(hBB,3,0,0,0) ; Ugly but works.
   sStandardName = BinaryPeekStr(hBB,2,32)
   sDaylightName = BinaryPeekStr(hBB,44,32)
   sResult = StrCat(iResult,@TAB,iCurrentBias,@TAB,sStandardDate,@TAB,iStandardBias,@TAB,sStandardName,@TAB,sDaylightDate,@TAB,iDaylightBias,@TAB,sDaylightName)
   Break
EndSwitch
BinaryFree(hBB)
Return (sResult)
;..........................................................................................................................................
;   This function returns a tab delimited list of 8 items,
;   containing information about Standard and Daylight TimeZone settings.
;
;   1.
;   Status of the TIME_ZONE_ID.
;      e.g. "2"
;
;      TIME_ZONE_ID_INVALID  = -1
;
;      TIME_ZONE_ID_UNKNOWN  = 0 ...
;         The system cannot determine the current time zone.
;         Windows NT/2000/XP:
;         This value is returned if daylight saving time is not used in the current time zone, because there are no transition dates.
;
;      TIME_ZONE_ID_STANDARD = 1
;         The system is operating in the range covered by the StandardDate member of the TIME_ZONE_INFORMATION structure.
;         Windows 95/98/Me:
;         This value is returned if daylight saving time is not used in the current time zone, because there are no transition dates.
;
;      TIME_ZONE_ID_DAYLIGHT = 2
;         The system is operating in the range covered by the DaylightDate member of the TIME_ZONE_INFORMATION structure.
;
;   2.
;   Current bias for local time translation on this computer, in minutes.
;   The bias is the difference, in minutes, between Coordinated Universal Time (UTC) and local time.
;   All translations between UTC and local time are based on the following formula:
;   UTC = local time + bias
;      e.g. (GMT-10:00) Hawaii ==>iCurrentBias=600
;
;   3.
;   StandardDate
;      A YmdHms datetime string.
;      e.g. "2003:10:26:03:00:00"
;
;   4.
;   StandardBias
;      Bias value to be used during local time translations that occur during standard time.
;      This member is ignored if a value for the StandardDate member is not supplied.
;      This value is added to the value of the Bias member to form the bias used during standard time.
;      In most time zones, the value of this member is zero.
;
;   5.
;   StandardName
;      A string associated with standard time on this operating system.
;      For example, this member could contain "EST" to indicate Eastern Standard Time.
;      This string is not used by the operating system, it has only descriptive information.
;      e.g. "(MEZ) Mitteleuropäische Zeit"
;
;   6.
;   DaylightDate
;      a YmdHms datetime string.
;      e.g. "2003:03:30:02:00:00"
;
;   7.
;   DaylightBias
;      Bias value to be used during local time translations that occur during daylight saving time.
;      This member is ignored if a value for the DaylightDate member is not supplied.
;      This value is added to the value of the Bias member to form the bias used during daylight saving time.
;      In most time zones, the value of this member is – 60.
;
;   8.
;   DaylightName
;      A string associated with daylight saving time on this operating system.
;      For example, this member could contain "PDT" to indicate Pacific Daylight Time.
;      This string is not used by the operating system, it has only descriptive information.
;      e.g. "(MEZ) - Mitteleurop. Sommerzeit"
;
;..........................................................................................................................................
; Detlev Dalitz.20030920
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================




;==========================================================================================================================================
; User Defined Functions for the calculation of German Holidays.
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_AscherMittwoch (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
Aschermittwoch = TimeSubtract(EasterSunday,"0:0:40:0:0:0")
While (udfJulianDayOfWeek(Aschermittwoch)!=3)
   Aschermittwoch = TimeSubtract(Aschermittwoch,"0:0:1:0:0:0")
EndWhile
Return (Aschermittwoch)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_PalmSonntag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
Palmsonntag = TimeSubtract(EasterSunday,"0:0:7:0:0:0")
Return (Palmsonntag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_KarFreitag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
Karfreitag = TimeSubtract(EasterSunday,"0:0:2:0:0:0")
Return (Karfreitag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_OsterSonntag (YmdHms) ; returns datetime string
Return (udfEasterSunday(YmdHms))
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_OsterMontag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
Ostermontag = TimeAdd(EasterSunday,"0:0:1:0:0:0")
Return (Ostermontag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_WeisserSonntag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
WeisserSonntag = TimeAdd(EasterSunday,"0:0:7:0:0:0")
Return (WeisserSonntag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_ChristiHimmelfahrt (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
ChristiHimmelfahrt = TimeAdd(EasterSunday,"0:0:39:0:0:0")
Return (ChristiHimmelfahrt)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_PfingstSonntag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
PfingstSonntag = TimeAdd(EasterSunday,"0:0:49:0:0:0")
Return (PfingstSonntag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_PfingstMontag (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
PfingstMontag = TimeAdd(EasterSunday,"0:0:50:0:0:0")
Return (PfingstMontag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_Fronleichnam (YmdHms) ; returns datetime string
EasterSunday = udfEasterSunday(YmdHms)
Fronleichnam = TimeAdd(EasterSunday,"0:0:60:0:0:0")
Return (Fronleichnam)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_MariaeHimmelfahrt (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
MariaeHimmelfahrt = StrCat(Year,":08:15:00:00:00")
Return (MariaeHimmelfahrt)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_TagDerEinheit (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
TagDerEinheit = StrCat(Year,":10:03:00:00:00")
Return (TagDerEinheit)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_Reformationstag (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
Reformationstag = StrCat(Year,":10:31:00:00:00")
Return (Reformationstag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_HeiligAbend (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
HeiligAbend = StrCat(Year,":12:24:00:00:00")
Return (HeiligAbend)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_ErsterWeihnachten (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
ErsterWeihnachtstag = StrCat(Year,":12:25:00:00:00")
Return (ErsterWeihnachtstag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_ZweiterWeihnachten (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
ZweiterWeihnachtstag = StrCat(Year,":12:26:00:00:00")
Return (ZweiterWeihnachtstag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_Silvester (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
Silvester = StrCat(Year,":12:31:00:00:00")
Return (Silvester)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_Neujahr (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
Neujahr = StrCat(Year,":01:01:00:00:00")
Return (Neujahr)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_ErsterAdvent (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
ErsterAdvent = StrCat(Year,":12:24:00:00:00")
While (udfJulianDayOfWeek(ErsterAdvent)!=0)
   ErsterAdvent = TimeSubtract(ErsterAdvent,"0:0:1:0:0:0")
EndWhile
ErsterAdvent = TimeSubtract(ErsterAdvent,"0:0:21:0:0:0")
Return (ErsterAdvent)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_ZweiterAdvent (YmdHms) ; returns datetime string
ErsterAdvent = udfGD_ErsterAdvent(YmdHms)
ZweiterAdvent = TimeAdd(ErsterAdvent,"0:0:7:0:0:0")
Return (ZweiterAdvent)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_DritterAdvent (YmdHms) ; returns datetime string
ErsterAdvent = udfGD_ErsterAdvent(YmdHms)
DritterAdvent = TimeAdd(ErsterAdvent,"0:0:14:0:0:0")
Return (DritterAdvent)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_VierterAdvent (YmdHms) ; returns datetime string
ErsterAdvent = udfGD_ErsterAdvent(YmdHms)
VierterAdvent = TimeAdd(ErsterAdvent,"0:0:21:0:0:0")
Return (VierterAdvent)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_BussUndBettag (YmdHms) ; returns datetime string
BussUndBettag = udfGD_ErsterAdvent(YmdHms)
While (udfJulianDayOfWeek(BussUndBettag)!=3)
   BussUndBettag = TimeSubtract(BussUndBettag,"0:0:1:0:0:0")
EndWhile
BussUndBettag = TimeSubtract(BussUndBettag,"0:0:7:0:0:0")
Return (BussUndBettag)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_HeiligeDreiKoenige (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
HeiligeDreiKoenige = StrCat(Year,":01:06:00:00:00")
Return (HeiligeDreiKoenige)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_Allerheiligen (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
Allerheiligen = StrCat(Year,":11:01:00:00:00")
Return (Allerheiligen)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGD_TagDerArbeit (YmdHms) ; returns datetime string
year = ItemExtract(1,YmdHms,":")
TagDerArbeit = StrCat(Year,":05:01:00:00:00")
Return (TagDerArbeit)
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfNameOfGD (YmdHms) ; returns string (fast speed)
;Feste Feiertage
mmdd = StrSub(YmdHms,6,5)
NamesFix = "(Silvester),Zweiter Weihnachtstag,Erster Weihnachtstag,Heiligabend,Allerheiligen,(Reformationstag),Tag der Deutschen Einheit,(Mariä Himmelfahrt),Tag der Arbeit,(Heilige Drei Könige),Neujahr"
DaysFix  = "12:31,12:26,12:25,12:24,11:01,10:31,10:03,08:15,05:01,01:06,01:01"
d = ItemLocate(mmdd,DaysFix,",")
If (d>0) Then Return (ItemExtract(d,NamesFix,","))

;Advent
ErsterAdvent  = udfGD_ErsterAdvent(YmdHms)
If (YmdHms==ErsterAdvent ) Then Return ("Erster Advent")
ZweiterAdvent = TimeAdd(ErsterAdvent,"0:0:7")
If (YmdHms==ZweiterAdvent) Then Return ("Zweiter Advent")
DritterAdvent = TimeAdd(ErsterAdvent,"0:0:14")
If (YmdHms==DritterAdvent) Then Return ("Dritter Advent")
VierterAdvent = TimeAdd(ErsterAdvent,"0:0:21")
If (YmdHms==VierterAdvent) Then Return ("Vierter Advent")

;Bewegliche Feiertage
d = TimeDiffDays(YmdHms,udfEasterSunday(YmdHms))
If (d==-7) Then Return ("(Palmsonntag)")
If (d==-2) Then Return ("Karfreitag")
If (d== 0) Then Return ("Ostersonntag")
If (d== 1) Then Return ("Ostermontag")
If (d== 7) Then Return ("(Weißer Sonntag)")
If (d==39) Then Return ("Christi Himmelfahrt")
If (d==49) Then Return ("Pfingstsonntag")
If (d==50) Then Return ("Pfingstmontag")
If (d==60) Then Return ("(Fronleichnam)")

Aschermittwoch = udfGD_AscherMittwoch(YmdHms)
If (YmdHms==Aschermittwoch) Then Return ("(Aschermittwoch)")
BussUndBettag = udfGD_BussUndBettag(YmdHms)
If (YmdHms==BussUndBettag) Then Return ("(Buß- und Bettag)")

Return ("")
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfNameOfGD2 (YmdHms) ; returns string (slow speed)
If (YmdHms==udfGD_Silvester         (YmdHms)) Then Return ("(Silvester)")
If (YmdHms==udfGD_ZweiterWeihnachten(YmdHms)) Then Return ("Zweiter Weihnachtstag")
If (YmdHms==udfGD_ErsterWeihnachten (YmdHms)) Then Return ("Erster Weihnachtstag")
If (YmdHms==udfGD_HeiligAbend       (YmdHms)) Then Return ("Heiligabend")
If (YmdHms==udfGD_Allerheiligen     (YmdHms)) Then Return ("Allerheiligen")
If (YmdHms==udfGD_BussUndBettag     (YmdHms)) Then Return ("(Buß- und Bettag)")
If (YmdHms==udfGD_VierterAdvent     (YmdHms)) Then Return ("Vierter Advent")
If (YmdHms==udfGD_DritterAdvent     (YmdHms)) Then Return ("Dritter Advent")
If (YmdHms==udfGD_ZweiterAdvent     (YmdHms)) Then Return ("Zweiter Advent")
If (YmdHms==udfGD_ErsterAdvent      (YmdHms)) Then Return ("Erster Advent")
If (YmdHms==udfGD_Reformationstag   (YmdHms)) Then Return ("(Reformationstag)")
If (YmdHms==udfGD_TagDerEinheit     (YmdHms)) Then Return ("Tag der Deutschen Einheit")
If (YmdHms==udfGD_MariaeHimmelfahrt (YmdHms)) Then Return ("(Mariä Himmelfahrt)")
If (YmdHms==udfGD_Fronleichnam      (YmdHms)) Then Return ("(Fronleichnam)")
If (YmdHms==udfGD_PfingstMontag     (YmdHms)) Then Return ("Pfingstmontag")
If (YmdHms==udfGD_PfingstSonntag    (YmdHms)) Then Return ("Pfingstsonntag")
If (YmdHms==udfGD_ChristiHimmelfahrt(YmdHms)) Then Return ("Christi Himmelfahrt")
If (YmdHms==udfGD_TagDerArbeit      (YmdHms)) Then Return ("Tag der Arbeit")
If (YmdHms==udfGD_WeisserSonntag    (YmdHms)) Then Return ("(Weisser Sonntag)")
If (YmdHms==udfGD_OsterMontag       (YmdHms)) Then Return ("Ostermontag")
If (YmdHms==udfGD_OsterSonntag      (YmdHms)) Then Return ("Ostersonntag")
If (YmdHms==udfGD_KarFreitag        (YmdHms)) Then Return ("Karfreitag")
If (YmdHms==udfGD_PalmSonntag       (YmdHms)) Then Return ("(Palmsonntag)")
If (YmdHms==udfGD_AscherMittwoch    (YmdHms)) Then Return ("(Aschermittwoch)")
If (YmdHms==udfGD_HeiligeDreiKoenige(YmdHms)) Then Return ("(Heilige Drei Könige)")
If (YmdHms==udfGD_Neujahr           (YmdHms)) Then Return ("Neujahr")
Return ("")
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfGDHashTable (YmdHms, Mode) ; (middle speed)
; (Mode=0="", Mode=1=Name of German Holiday, Mode=2=List of German Holidays)
year = ItemExtract(1,YmdHms,":")
FirstJan = StrCat(year,":01:01:00:00:00")
day_count = udfDaysInYear(year)-1

GoSub SetHashTableParameters

retval = ""
Switch Mode
Case 0 ; Create Hash Table
   GoSub OpenWriteHashTable
   Break
Case 1 ; Retrieve Name of GD from hash table
   If !(udfIsValidDateTime(YmdHms)) Then Break
   If !(FileExist(hash_filepathname)) Then Break
   GoSub OpenReadHashTable
   day_date = TimeAdd(YmdHms,"0:0:0:0:0:0") ; make valid datetime string
   GoSub RetrieveNameOfGD
   BinaryFree(hash_bb)
   Break
Case 2 ; Make List Of GD Names from hash table
   If !(udfIsValidDateTime(YmdHms)) Then Break
   If !(FileExist(hash_filepathname)) Then Break ; caller have to create hashtable ...
   GoSub OpenReadHashTable
   GoSub MakeListOfGDNames
   BinaryFree(hash_bb)
   Break
EndSwitch
Return (retval)

:SetHashTableParameters
tempfile = FileCreateTemp("TMP")
FileDelete(tempfile) ; we only need the folderpath
tempfolder = FilePath(tempfile)
hash_filepathname = StrCat(tempfolder,"HASH",year,".BIN")
hash_entries         = 26 ; number of German Holidays
hash_offset_day_date = 0
hash_size_day_date   = 19 ; StrLen("0000:00:00:00:00:00")
hash_offset_day_name = hash_offset_day_date + hash_size_day_date
hash_size_day_name   = 30
hash_recsize  =  hash_size_day_date + hash_size_day_name
hash_entries   = Int(hash_entries * 1.5) ; reserve some more hash space
hash_tablesize = hash_entries * hash_recsize
Return

:OpenWriteHashTable ; overwrites existing file without permission!
hash_bb = BinaryAlloc(hash_tablesize)
For day=0 To day_count
   day_date = TimeAdd(FirstJan,StrCat("0:0:",day))
   day_name = udfNameOfGD(day_date)
   If (day_name>"")
      hash_offset = BinaryHashRec(hash_bb, hash_recsize, hash_offset_day_date, hash_size_day_date, day_date)
      BinaryPokeStr(hash_bb, hash_offset + hash_offset_day_name, day_name)
   EndIf
Next day
; if (!FileExist(hash_filepathname)) then BinaryWrite(hash_bb,hash_filepathname)
BinaryWrite(hash_bb,hash_filepathname)
BinaryFree(hash_bb)
Return

:OpenReadHashTable
hash_tablesize = FileSize(hash_filepathname)
hash_bb = BinaryAlloc(hash_tablesize)
BinaryRead(hash_bb,hash_filepathname)
Return

:RetrieveNameOfGD
LastErrorMode = ErrorMode(@OFF)
LastError()
hash_offset = BinaryHashRec(hash_bb, hash_recsize, hash_offset_day_date, hash_size_day_date, day_date)
ErrorMode(LastErrorMode)
If (LastError()==0)
   retval = BinaryPeekStr(hash_bb, hash_offset + hash_offset_day_name, hash_size_day_name)
   If (retval=="") Then BinaryPoke(hash_bb,hash_offset,0) ; housekeeping the hashtable
Else
   retval = ""
EndIf
Return

:MakeListOfGDNames
itemlist = ""
For day=0 To day_count
   day_date = TimeAdd(FirstJan,StrCat("0:0:",day))
   GoSub RetrieveNameOfGD
   If (retval>"")
      newitempos = ItemCount(itemlist,@LF) + 1
      newitem = StrCat(udfTimeDMY(day_date)," ",retval)
      itemlist = ItemInsert(newitem, newitempos, itemlist, @LF)
   EndIf
Next day
retval = itemlist
Return

#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================



;==========================================================================================================================================
; User Defined Function for string formatting. Uses Date and Time functions.
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfTimeFormatStr (YmdHms, TaggedStr); returns string formatted as defined in TaggedStr
IntControl(73,2,0,0,0) ; Install ErrorHandler for sure.
DTArray = Arrayize(YmdHms,":")
bb = BinaryAlloc(StrLen(TaggedStr)*3) ; reserve working space
BinaryEodSet(bb,0)
BinaryPokeStr(bb,0,TaggedStr)
structure = BinaryTagInit(bb,"{{","}}")
While @TRUE
   structure = BinaryTagFind(structure)
   If (structure=="") Then Break
   keyword = BinaryTagExtr(structure, 1)
   Value = "???"   ; keyword not found error value
   If (keyword>"") Then GoSub %keyword%
   structure = BinaryTagRepl(structure,Value)
EndWhile
FormattedStr = BinaryPeekStr(bb,0,BinaryEodGet(bb))
BinaryFree(bb)
Return (FormattedStr)

;--- the labels are the keywords are the labels -----------------------------------------

:YYYY   ; Year (fix 4 Digits)
Value = DTArray[0]
Return

:YY     ; Year (fix 2 Digits)
Value = StrSub(DTArray[0],3,2)
Return

:Y      ; Year (var 1..2 Digits)
Value = 0+StrSub(DTArray[0],3,2)
Return

:MM     ; Month (fix 2 Digits)
Value = DTArray[1]
Return

:M      ; Month (var 1..2 Digits)
Value = 0+DTArray[1]
Return
; Value = DTArray[1]
; If (StrSub(DTArray[1],1,1)=="0") then Value = StrSub(DTArray[1],2,1)

:DD     ; Day (fix 2 Digits)
Value = DTArray[2]
Return

:D      ; Day (var 1..2 Digits)
Value = 0+DTArray[2]
Return
; Value = DTArray[2]
; If (StrSub(DTArray[2],1,1)=="0") then Value = StrSub(DTArray[2],2,1)

:HHMMSS
:THHMMSS ; Time (fix 8 Digits)
Value = StrCat(DTArray[3],":",DTArray[4],":",DTArray[5])
Return

:HHMM
:THHMM   ; Time (fix 5 Digits)
Value = StrCat(DTArray[3],":",DTArray[4])
Return

:HH
:THH    ; TimeHours (fix 2 Digits)
Value = DTArray[3]
Return

:H
:TH     ; TimeHours (var 1..2 Digits)
Value = 0+DTArray[3]
Return
; Value = DTArray[3]
; If (StrSub(DTArray[3],1,1)=="0") then Value = StrSub(DTArray[3],2,1)

:MMI
:TMM    ; TimeMinutes (fix 2 Digits)
Value = DTArray[4]
Return

:MI
:TM     ; TimeMinutes (var 1..2 Digits)
Value = 0+DTArray[4]
Return
; Value = DTArray[4]
; If (StrSub(DTArray[4],1,1)=="0") then Value = StrSub(DTArray[4],2,1)

:SS
:TSS    ; TimeSeconds (fix 2 Digits)
Value = DTArray[5]
Return

:S
:TS     ; TimeSeconds (var 1..2 Digits)
Value = 0+DTArray[5]
Return
; Value = DTArray[5]
; If (StrSub(DTArray[5],1,1)=="0") then Value = StrSub(DTArray[5],2,1)

:NOML
:MMMM   ; NameOfMonth Long
Value = udfNameOfMonth(YmdHms,0)
Return

:NOM2
:MMM2   ; NameOfMonth Short2 (fix 2 Byte)
Value = udfNameOfMonth(YmdHms,2)
Return

:NOM3
:MMM3   ; NameOfMonth Short3 (fix 3 Byte)
Value = udfNameOfMonth(YmdHms,3)
Return

:NODL
:DDDD   ; NameOfDay Long
Value = udfNameOfDay(YmdHms,0)
Return

:NOD2
:DDD2   ; NameOfDay Short2 (fix 2 Byte)
Value = udfNameOfDay(YmdHms,2)
Return

:NOD3
:DDD3   ; NameOfDay Short3 (fix 3 Byte)
Value = udfNameOfDay(YmdHms,3)
Return

:WOYL
:WOY2
:WWY    ; WeekOfYear Long (fix 2 Digits)
Value = StrFixLeft(udfWeekOfYear(YmdHms),"0",2)
Return

:WOY
:WY     ; WeekOfYear Short (var 1..2 Digits)
Value = udfWeekOfYear(YmdHms)
Return

:DOYL
:DOY3
:DDY    ; DayOfYear Long (fix 3 Digits)
Value = StrFixLeft(udfDayOfYear(YmdHms),"0",3)
Return

:DOY
:DY     ; DayOfYear (var 1..3 Digits)
Value = udfDayOfYear(YmdHms)
Return

:DOW
:DW     ; DayOfWeek (fix 1 Digit)
Value = udfDayOfWeek(YmdHms)
Return

:WBERRORHANDLER
wberror = LastError()
wberrmsg = ""
wberrmsg = StrCat(wberrmsg,"LastError Value = ",wberror,@LF)
If !wberror Then wberror = -1
wberrmsg = StrCat(wberrmsg,"LastError String = ",IntControl(34,wberror,0,0,0),@LF)
; line in script that caused Error
wberrmsg = StrCat(wberrmsg,"wberrorhandlerline = ",wberrorhandlerline,@LF)
; offset into script of error line, in bytes
wberrmsg = StrCat(wberrmsg,"wberrorhandleroffset = ",wberrorhandleroffset,@LF)
; variable being assigned on error line, or "" if none
wberrmsg = StrCat(wberrmsg,"wberrorhandlerassignment = ",wberrorhandlerassignment,@LF)
Message("WBERRORHANDLER",wberrmsg)
IntControl(73,2,0,0,0)
Return
;----------------------------------------------------------------------------------------
; examples:
; TaggedStr="Today is {{DDDD}}, {{DD}}. {{MMMM}} {{YYYY}}, Week #{{WY}}, Day #{{DY}}"
; TaggedStr="Year/Week/Day: {{YYYY}}/{{WWY}}/{{DDY}}"
;----------------------------------------------------------------------------------------
; Y       ; Year               (var 1..2 Digits)
; YY      ; Year               (fix 2 Digits)
; YYYY    ; Year               (fix 4 Digits)
;
; M       ; Month              (var 1..2 Digits)
; MM      ; Month              (fix 2 Digits)
; MMM2    ; NameOfMonth Short2 (fix 2 Chars)
; MMM3    ; NameOfMonth Short3 (fix 3 Chars)
; MMMM    ; NameOfMonth Long   (var 3..9 Chars)
;
; D       ; Day                (var 1..2 Digits)
; DD      ; Day                (fix 2 Digits)
; DDD2    ; NameOfDay Short2   (fix 2 Chars)
; DDD3    ; NameOfDay Short3   (fix 3 Chars)
; DDDD    ; NameOfDay Long     (var 6..9 Chars)
;
; THHMMSS ; TimeHMS            (fix 8 Digits)
; THHMM   ; TimeHM             (fix 5 Digits)
; THH     ; TimeHours          (fix 2 Digits)
; TH      ; TimeHours          (var 1..2 Digits)
; TMM     ; TimeMinutes        (fix 2 Digits)
; TM      ; TimeMinutes        (var 1..2 Digits)
; TSS     ; TimeSeconds        (fix 2 Digits)
; TS      ; TimeSeconds        (var 1..2 Digits)
;
; WWY     ; WeekOfYear Long    (fix 2 Digits)
; WY      ; WeekOfYear Short   (var 1..2 Digits)
;
; DDY     ; DayOfYear Long     (fix 3 Digits)
; DY      ; DayOfYear          (var 1..3 Digits)
;
; DW      ; DayOfWeek          (fix 1 Digit)
;----------------------------------------------------------------------------------------
; --- alternative keywords ---
; NOD2    ; NameOfDay Short2   (fix 2 Chars)
; NOD3    ; NameOfDay Short3   (fix 3 Chars)
; NODL    ; NameOfDay Long     (var 6..9 Chars)
;
; NOM2    ; NameOfMonth Short2 (fix 2 Chars)
; NOM3    ; NameOfMonth Short3 (fix 3 Chars)
; NOML    ; NameOfMonth Long   (var 3..9 Chars)
;
; HHMMSS  ; TimeHMS            (fix 8 Digits)
; HHMM    ; TimeHM             (fix 5 Digits)
; HH      ; TimeHours          (fix 2 Digits)
; H       ; TimeHours          (var 1..2 Digits)
; MMI     ; TimeMinutes        (fix 2 Digits)
; MI      ; TimeMinutes        (var 1..2 Digits)
; SS      ; TimeSeconds        (fix 2 Digits)
; S       ; TimeSeconds        (var 1..2 Digits)
;
; WOYL    ; WeekOfYear Long    (fix 2 Digits)
; WOY2    ; WeekOfYear Long    (fix 2 Digits)
; WOY     ; WeekOfYear Short   (var 1..2 Digits)
;
; DOYL    ; DayOfYear Long     (fix 3 Digits)
; DOY3    ; DayOfYear Long     (fix 3 Digits)
; DOY     ; DayOfYear          (var 1..3 Digits)
;
; DOW     ; DayOfWeek          (fix 1 Digit)
;----------------------------------------------------------------------------------------
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------
;==========================================================================================================================================



;##########################################################################################################################################
;##########################################################################################################################################
; --- test main ---------------------------------------------
;If (IntControl(77,80,0,0,0)>0) Then Return

GoSub Test_DateTime_Functions_1
GoSub Test_DateTime_Functions_2
GoSub Test_DateTime_Functions_3
GoSub Test_DateTime_Functions_4
GoSub Test_FormatString
GoSub Test_GermanDays

;------------------------------------------------------------
;just for testing
;DisplayAllAssignedUDFs
;list = IntControl(77, 103, 0, 0, 0)
;AskItemList("UDF's defined", list, @tab, @unsorted, @single)
;
;DropAllAssignedUDFs
;IntControl (78, 0, 0, 0, 0)
;DisplayAllAssignedUDFs
;list = IntControl(77, 103, 0, 0, 0)
;AskItemList("UDF's defined", list, @tab, @unsorted, @single)
;------------------------------------------------------------

Message("DateTime Functions"," Test done.")
Exit
;##########################################################################################################################################
;##########################################################################################################################################



;==========================================================================================================================================
:Test_FormatString
;------------------------------------------------------------------------------------------------------------------------------------------
TaggedStr = ""
TaggedStr = StrCat(TaggedStr,"Heute ist {{DDD2}} {{D}} {{M}} {{Y}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Heute ist {{DDD3}} {{D}} {{M}} {{YY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Heute ist {{DDDD}}, {{DD}}.{{MM}}.{{YYYY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Heute ist {{DDD2}}., {{D}}. {{MMM3}}. {{YYYY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Heute ist {{DDDD}}, der {{D}}. {{MMMM}} {{YYYY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Jetzt ist es {{TH}} Uhr, {{TM}} Minuten und {{TS}} Sekunden.",@CRLF)
TaggedStr = StrCat(TaggedStr,"Jetzt ist es {{THH}} Uhr, {{TMM}} Minuten und {{TSS}} Sekunden.",@CRLF)
TaggedStr = StrCat(TaggedStr,"Jetzt ist es {{THHMM}} Uhr.",@CRLF)
TaggedStr = StrCat(TaggedStr,"Jetzt ist es {{THHMMSS}} Uhr.",@CRLF)
TaggedStr = StrCat(TaggedStr,"Kalenderwoche {{WY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Kalenderwoche {{YYYY}}W{{WWY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Kalenderwoche {{YYYY}}W{{WWY}}{{DW}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Tag des Jahres {{DY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Tag des Jahres {{DDY}}/{{YYYY}}",@CRLF)
TaggedStr = StrCat(TaggedStr,"Today is {{DDDD}}, {{DD}}. {{MMMM}} {{YYYY}}, Week {{WY}}, Day {{DY}}",@CRLF)

now = TimeYmdHms()
OutStr = udfTimeFormatStr(now,TaggedStr)
OutStr= StrReplace(OutStr,@CRLF,@TAB)
IntControl(63,200,200,800,800)
AskItemlist("Test: TimeFormatString", OutStr, @TAB, @UNSORTED, @SINGLE)
;------------------------------------------------------------------------------------------------------------------------------------------
Return ; from Test_FormatString
;==========================================================================================================================================



;==========================================================================================================================================
:Test_DateTime_Functions_1
;------------------------------------------------------------------------------------------------------------------------------------------
testdate = "2001:13:01"
testdatetime = "2001:12:01:00:00:60"
now = TimeYmdHms()
OutStr = ""
OutStr = StrCat(OutStr, "Testdate                                    = ", testdate, @CRLF)
OutStr = StrCat(OutStr, "udfIsValidDate, gültig?                     = ", udfSayNoYes(udfIsValidDate(testdate)), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "Testdatetime                                = ", testdatetime, @CRLF)
OutStr = StrCat(OutStr, "udfIsValidDate, gültig?                     = ", udfSayNoYes(udfIsValidDate(testdatetime)), @CRLF)
OutStr = StrCat(OutStr, "udfIsValidDateTime, gültig?                 = ", udfSayNoYes(udfIsValidDateTime(testdatetime)), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "Now                                         = ", now, @CRLF)
OutStr = StrCat(OutStr, "udfIsValidDateTime, gültig?                 = ", udfSayNoYes(udfIsValidDateTime(now)), @CRLF,@CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToUnixSeconds                      = ", udfYmdHmsToUnixSeconds(now), @CRLF)
OutStr = StrCat(OutStr, "udfUnixSecondsToYmdHms                      = ", udfUnixSecondsToYmdHms(udfYmdHmsToUnixSeconds(now)), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfDayOfYear, Tag im Jahr                   = ", udfDayOfYear(now), @CRLF)
OutStr = StrCat(OutStr, "udfJulianDayOfWeek, Wochentag Nummer        = ", udfJulianDayOfWeek(now), @CRLF)
OutStr = StrCat(OutStr, "udfDayOfWeek, Wochentag Nummer              = ", udfDayOfWeek(now), @CRLF)
OutStr = StrCat(OutStr, "udfNameOfDay, Wochentag Name, 2 chars       = ", udfNameOfDay(now,2), @CRLF)
OutStr = StrCat(OutStr, "udfNameOfDay, Wochentag Name, lang          = ", udfNameOfDay(now,0), @CRLF)
OutStr = StrCat(OutStr, "udfWeekOfYear, Kalenderwoche Nummer         = ", udfWeekOfYear(now), @CRLF)
OutStr = StrCat(OutStr, "udfWeekOfYear, Next week, 7 days added      = ", udfWeekOfYear(TimeAdd(Now,"0:0:7")), @CRLF)
OutStr = StrCat(OutStr, "udfNameOfMonth, Monat Name, 3 chars         = ", udfNameOfMonth(now,3), @CRLF)
OutStr = StrCat(OutStr, "udfNameOfMonth, Monat Name, lang            = ", udfNameOfMonth(now,0), @CRLF)
OutStr = StrCat(OutStr, "udfDaysInMonth, Tage im Monat               = ", udfDaysInMonth(now), @CRLF)
OutStr = StrCat(OutStr, "udfIsLastDayInMonth, Letzter Tag im Monat?  = ", udfSayNoYes(udfIsLastDayInMonth(now)), @CRLF)
OutStr = StrCat(OutStr, "udfDaysInYear, Tage im Jahr                 = ", udfDaysInYear(now), @CRLF)
OutStr = StrCat(OutStr, "udfIsJulianLeapYear, Schaltjahr?            = ", udfSayNoYes(udfIsJulianLeapYear(now)), @CRLF)
OutStr = StrCat(OutStr, "udfIsLeapYear, Schaltjahr?                  = ", udfSayNoYes(udfIsLeapYear(now)), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Gauss            = "           , udfEasterSunday_Gauss(now), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Schlyter         = "           , udfEasterSunday_Schlyter(now), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Lilius_Clavius   = "           , udfEasterSunday_Lilius_Clavius(now), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Passah           = "           , udfEasterSunday_Passah(now), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Gauss            = "           , udfEasterSunday_Gauss(udfSetYear(now,1+udfGetYear(now))), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Schlyter         = "           , udfEasterSunday_Schlyter(udfSetYear(now,1+udfGetYear(now))), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Lilius_Clavius   = "           , udfEasterSunday_Lilius_Clavius(udfSetYear(now,1+udfGetYear(now))), @CRLF)
OutStr = StrCat(OutStr, "udfEasterSunday_Passah           = "           , udfEasterSunday_Passah(udfSetYear(now,1+udfGetYear(now))), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfTimeDMY, dd.mm.yyyy           = "           , udfTimeDMY(now), @CRLF)
OutStr = StrCat(OutStr, "udfTimeDMYShort, ddd dd.mm.yyyy  = "           , udfTimeDMYShort(now), @CRLF)
OutStr = StrCat(OutStr, "udfTimeDMYLong, dddd dd.mm.yyyy  = "           , udfTimeDMYLong(now), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToHTTPStamp (%now%, 1)  = "           , udfYmdHmsToHTTPStamp(now,1), @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToHTTPStamp (%now%, 2)  = "           , udfYmdHmsToHTTPStamp(now,2), @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToHTTPStamp (%now%, 3)  = "           , udfYmdHmsToHTTPStamp(now,3), @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToHTTPStamp (%now%, 4)  = "           , udfYmdHmsToHTTPStamp(now,4), @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToHTTPStamp (%now%, 5)  = "           , udfYmdHmsToHTTPStamp(now,5), @CRLF, @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToYwd (%now%, 0)      = "             , udfYmdHmsToYwd(now,0), @CRLF)
OutStr = StrCat(OutStr, "udfYmdHmsToYwd (%now%, 1)      = "             , udfYmdHmsToYwd(now,1), @CRLF)
OutStr = StrCat(OutStr, "udfYwdToYmdHms (""2002W492"")  = "             , udfYwdtoYmdHms("2002W492"), @CRLF)
OutStr = StrReplace(OutStr,@CRLF,@TAB)
IntControl(28,1,0,0,0)
IntControl(63,100,100,900,900)
AskItemlist("Test: Datum und Zeit Funktionen", OutStr, @TAB, @UNSORTED, @SINGLE)
;------------------------------------------------------------------------------------------------------------------------------------------
Return ; from Test_DateTime_Functions_1
;==========================================================================================================================================



;==========================================================================================================================================
:Test_DateTime_Functions_2
;------------------------------------------------------------------------------------------------------------------------------------------
:test1
now1 = TimeYmdHms()
now2 = "2001:12:31:01:00:00"
now3 = "2004:02:28:01:00:00"
now4 = "2004:02:29:01:00:00"

msgtitle = "Demo udfIsLastDayOfMonth (datetimestr)"
For i=1 To 4
   msgtext  = ""
   msgtext  = StrCat(msgtext,"Now is ",now%i%,@LF,@LF)
   msgtext  = StrCat(msgtext,"Is now the last day of month?",@LF)
   msgtext  = StrCat(msgtext,udfSayNoYes(udfIsLastDayOfMonth(now%i%)))
   Message(msgtitle,msgtext)
Next


:test2
now1 = TimeYmdHms()
now2 = "2001:01:01:01:00:00"
now3 = "2001:01:02:01:00:00"

msgtitle = "Demo udfIsFirstDayOfMonth (datetimestr)"
For i=1 To 3
   msgtext  = ""
   msgtext  = StrCat(msgtext,"Now is ",now%i%,@LF,@LF)
   msgtext  = StrCat(msgtext,"Is now the first day of month?",@LF)
   msgtext  = StrCat(msgtext,udfSayNoYes(udfIsFirstDayOfMonth(now%i%)))
   Message(msgtitle,msgtext)
Next


:test3
now1 = TimeYmdHms()
now2 = "2001:01:15:01:00:00"
now3 = "2004:02:29:01:00:00"
day1 = 1
day2 = 15
day3 = 32 ; "last day" of month

msgtitle = "Demo udfIsNthDayOfMonth (datetimestr, n)"
For i=1 To 3
   msgtext  = ""
   msgtext  = StrCat(msgtext,"Now is ",now%i%,@LF,@LF)
   msgtext  = StrCat(msgtext,"Is now the ",day%i%,". day of month?",@LF)
   msgtext  = StrCat(msgtext,udfSayNoYes(udfIsNthDayOfMonth(day%i%,now%i%)))
   Message(msgtitle,msgtext)
Next


Drop(day1,day2,day3,i,msgtext,msgtitle,now1,now2,now3,now4)

;------------------------------------------------------------------------------------------------------------------------------------------
Return ; from Test_DateTime_Functions_2
;==========================================================================================================================================



;==========================================================================================================================================
:Test_DateTime_Functions_3
;------------------------------------------------------------------------------------------------------------------------------------------
Today     = TimeYmdHms()
Sunday    = udfGetSundayOfWeek    (Today)
Monday    = udfGetMondayOfWeek    (Today)
Tuesday   = udfGetTuesdayOfWeek   (Today)
Wednesday = udfGetWednesdayOfWeek (Today)
Thursday  = udfGetThursdayOfWeek  (Today)
Friday    = udfGetFridayOfWeek    (Today)
Saturday  = udfGetSaturdayOfWeek  (Today)

sMsgTitle = "Demo  udfGet...dayOfWeek (YmdHms)"
sMsgText = ""
sMsgText = StrCat(sMsgText,"Today"    ,@TAB,@TAB," = ",Today    ,@LF)
sMsgText = StrCat(sMsgText,@LF,"This Week:",@LF)
sMsgText = StrCat(sMsgText,"Sunday"   ,@TAB,@TAB," = ",Sunday   ,@LF)
sMsgText = StrCat(sMsgText,"Monday"   ,@TAB,@TAB," = ",Monday   ,@LF)
sMsgText = StrCat(sMsgText,"Tuesday"  ,@TAB,@TAB," = ",Tuesday  ,@LF)
sMsgText = StrCat(sMsgText,"Wednesday"     ,@TAB," = ",Wednesday,@LF)
sMsgText = StrCat(sMsgText,"Thursday" ,@TAB,@TAB," = ",Thursday ,@LF)
sMsgText = StrCat(sMsgText,"Friday"   ,@TAB,@TAB," = ",Friday   ,@LF)
sMsgText = StrCat(sMsgText,"Saturday" ,@TAB,@TAB," = ",Saturday ,@LF)

Pause(sMsgTitle,sMsgText)

Drop(Today,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday,sMsgTitle,sMsgText)
;------------------------------------------------------------------------------------------------------------------------------------------
Return ; from Test_DateTime_Functions_3
;==========================================================================================================================================




;==========================================================================================================================================
:Test_DateTime_Functions_4
;------------------------------------------------------------------------------------------------------------------------------------------
Today1 = TimeYmdHms()
Today2 = "2002:07:20" ; Saturday
Today3 = "2002:07:21" ; Sunday
Today4 = "2002:07:22" ; Monday

bIsWeekDay1 = udfIsWeekDay(Today1)
bIsWeekDay2 = udfIsWeekDay(Today2)
bIsWeekDay3 = udfIsWeekDay(Today3)
bIsWeekDay4 = udfIsWeekDay(Today4)

bIsWeekendDay1 = udfIsWeekendDay(Today1)
bIsWeekendDay2 = udfIsWeekendDay(Today2)
bIsWeekendDay3 = udfIsWeekendDay(Today3)
bIsWeekendDay4 = udfIsWeekendDay(Today4)

Drop(Today1,Today2,Today3,Today4)
Drop(bIsWeekDay1,bIsWeekDay2,bIsWeekDay3,bIsWeekDay4)
Drop(bIsWeekendDay1,bIsWeekendDay2,bIsWeekendDay3,bIsWeekendDay4)


DecHour1 = udfHmsToDecimalHour(TimeYmdHms())  ; a decimal number e.g. 10.901667
DecHour2 = udfHmsToDecimalHour("12:56:34")    ; 12.942778
DecHour3 = udfHmsToDecimalHour("123:123:123") ; 125.084167
DecHour4 = udfHmsToDecimalHour("56:34")       ; 0

YmdHms1 = udfDecimalHourToYmdHms(125.084167)  ; "0000:00:05:05:05:03"
YmdHms2 = udfDecimalHourToYmdHms(72)          ; "0000:00:03:00:00:00"
YmdHms3 = udfDecimalHourToYmdHms(4.7550)      ; "0000:00:00:04:45:18"
YmdHms4 = udfDecimalHourToYmdHms(12.942778)   ; "0000:00:00:12:56:34"

Drop(DecHour1,DecHour2,DecHour3,DecHour4,YmdHms1,YmdHms2,YmdHms3,YmdHms4)



fDateTime1 = udfYmdHmsToFloat("1899:12:29:12:00:00") ; --> -0.5
fDateTime2 = udfYmdHmsToFloat("1899:12:30:00:00:00") ; --> 0.0
fDateTime3 = udfYmdHmsToFloat("1899:12:31:00:00:00") ; --> 1.0
fDateTime4 = udfYmdHmsToFloat("1900:01:01:00:00:00") ; --> 2.0
fDateTime5 = udfYmdHmsToFloat("1900:01:02:00:00:01") ; --> 3.00001157407407
fDateTime6 = udfYmdHmsToFloat("1900:01:03:00:00:02") ; --> 4.00002314814815
fDateTime7 = udfYmdHmsToFloat(TimeYmdHms())

Drop(fDateTime1,fDateTime2,fDateTime3,fDateTime4,fDateTime5,fDateTime6,fDateTime7)



sYmdHms1 = udfFloatToYmdHms(-0.5)               ; --> "1899:12:29:12:00:00"
sYmdHms2 = udfFloatToYmdHms(0.0)                ; --> "1899:12:30:00:00:00"
sYmdHms3 = udfFloatToYmdHms(1.0)                ; --> "1899:12:31:00:00:00"
sYmdHms4 = udfFloatToYmdHms(2.0)                ; --> "1900:01:01:00:00:00"
sYmdHms5 = udfFloatToYmdHms(3.00001157407407)   ; --> "1900:01:02:00:00:01"
sYmdHms6 = udfFloatToYmdHms(4.00002314814815)   ; --> "1900:01:03:00:00:02"
sYmdHms7 = udfFloatToYmdHms(37792.305555555556) ; --> "2003:06:20:07:19:55"

Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4,sYmdHms5,sYmdHms6,sYmdHms7)



iCount1 = udfGetCountDOWInMonth(TimeYmdHms(),-1) ;
iCount2 = udfGetCountDOWInMonth("2002:07:31:00:00:00",1) ; There are 5 Mondays in July 2002.

Drop(iCount1,iCount2)


sYmdHms1 = udfGetNthDOWInMonth("2002:07:05",1,1)  ; 1st Monday in Month July 2002
sYmdHms2 = udfGetNthDOWInMonth("2002:07:05",4,1)  ; 4th Monday in Month July 2002
sYmdHms3 = udfGetNthDOWInMonth("2002:07:05",10,1) ; 5th Monday in Month July 2002
sYmdHms4 = udfGetNthDOWInMonth("2002:07:05",0,1)  ; 1st Monday in Month July 2002
sYmdHms5 = udfGetNthDOWInMonth("2002:07:05",5,0)  ; 5th Sunday in Month July 2002
sYmdHms6 = udfGetNthDOWInMonth(TimeYmdHms(),3,3)  ; 3rd Wednesday in current Month

Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4,sYmdHms5,sYmdHms6)


sYmdHms1 = udfGetLastDayOfMonth("2000:01:01")  ; Last day is "2000:01:31"
sYmdHms2 = udfGetLastDayOfMonth("2000:02:01")  ; Last day is "2000:02:29"
sYmdHms3 = udfGetLastDayOfMonth("2000:03:01")  ; Last day is "2000:03:31"
sYmdHms4 = udfGetLastDayOfMonth("2000:04:01")  ; Last day is "2000:04:30"

Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4)


sYmdHms1 = udfGetLastDayOfMonth("2000:01:01:12:12:12")  ; Last day is "2000:01:31:12:12:12"
sYmdHms2 = udfGetLastDayOfMonth("2000:02:01:12:12:12")  ; Last day is "2000:02:29:12:12:12"
sYmdHms3 = udfGetLastDayOfMonth("2000:03:01:12:12:12")  ; Last day is "2000:03:31:12:12:12"
sYmdHms4 = udfGetLastDayOfMonth("2000:04:01:12:12:12")  ; Last day is "2000:04:30:12:12:12"

Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4)


; I would prefer this udfGetLastDayOfMonth_2.
sYmdHms1 = udfGetLastDayOfMonth_2("2000:12:24")  ; Last day is "2000:12:31"
sYmdHms2 = udfGetLastDayOfMonth_2("2000:02:24")  ; Last day is "2000:02:29"
sYmdHms3 = udfGetLastDayOfMonth_2("2000:03:24")  ; Last day is "2000:03:31"
sYmdHms4 = udfGetLastDayOfMonth_2("2000:04:24")  ; Last day is "2000:04:30"

Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4)


sString1 = udfStrDateTo3Char(TimeYmdHms()) ; e.g. "2GJ"
sString2 = udfStrDateTo3Char("1999:02:13") ; "9BD"
sString3 = udfStrDateTo3Char("1999:02:14") ; "9BE"
sString4 = udfStrDateTo3Char("2004:05:30") ; "4EU"
sString5 = udfStrDateTo3Char("1994:05:30") ; "4EU"

Drop(sString1,sString2,sString3,sString4,sString5)


sString1 = udfStrDateTo4Char(TimeYmdHms()) ; e.g. "2G19"
sString2 = udfStrDateTo4Char("1999:02:13") ; "9B13"
sString3 = udfStrDateTo4Char("1999:02:14") ; "9B14"
sString4 = udfStrDateTo4Char("2004:05:30") ; "4E30"
sString5 = udfStrDateTo4Char("1994:05:30") ; "4E30"

Drop(sString1,sString2,sString3,sString4,sString5)


sString1 = udfStrDateTo8Char(TimeYmdHms()) ; e.g. "2G192341"
sString2 = udfStrDateTo8Char("1999:02:13:13:09:00") ; "9B131309"
sString3 = udfStrDateTo8Char("1999:02:14:13:10:00") ; "9B131310"
sString4 = udfStrDateTo8Char("2004:05:30:09:30:00") ; "4E300930"
sString5 = udfStrDateTo8Char("1994:05:30:09:30:00") ; "4E300930"

Drop(sString1,sString2,sString3,sString4,sString5)


iYear    = udfGetYear   (TimeYmdHms())
iMonth   = udfGetMonth  (TimeYmdHms())
iDay     = udfGetDay    (TimeYmdHms())
iHour    = udfGetHour   (TimeYmdHms())
iMinute  = udfGetMinute (TimeYmdHms())
iSecond  = udfGetSecond (TimeYmdHms())

sYmdHms1 = udfSetYear   (TimeYmdHms(),2004)
sYmdHms2 = udfSetMonth  (TimeYmdHms(),10)
sYmdHms3 = udfSetDay    (TimeYmdHms(),5)
sYmdHms4 = udfSetHour   (TimeYmdHms(),7)
sYmdHms5 = udfSetMinute (TimeYmdHms(),15)
sYmdHms6 = udfSetSecond (TimeYmdHms(),180)

Drop(iDay,iHour,iMinute,iMonth,iSecond,iYear)
Drop(sYmdHms1,sYmdHms2,sYmdHms3,sYmdHms4,sYmdHms5,sYmdHms6)



iSeconds = 93664
iMode = 0
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "1 Day  2 Hours  1 Minute  4 Seconds"
iMode = 1
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "1@TAB2@TAB1@TAB4"


iSeconds = 3664
iMode = 0
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "0 Days  1 Hour  1 Minute  4 Seconds"
iMode = 1
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "0@TAB1@TAB1@TAB4"


iSeconds = 936640
iMode = 0
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "10 Days  20 Hours  10 Minutes  40 Seconds"
iMode = 1
sText = udfSecondsToDhms(iSeconds,iMode) ; ==> "10@TAB20@TAB10@TAB40"

Drop(iMode,iSeconds,sText)



sYmd = udfGetYmd(TimeYmdHms())
sHms = udfGetHms(TimeYmdHms())

sYmdHms1 = udfSetYmd (TimeYmdHms(), "2004:10:05")  ; Set the date part.
sYmdHms1 = udfSetYmd (TimeYmdHms(), "2004:18:37")  ; Set the date part to "2005:07:07"

sYmdHms2 = udfSetHms (TimeYmdHms(), "11:55:00")    ; Set the time part.
sYmdHms3 = udfSetHms (TimeYmdHms(), "48:120:1800") ; Set the date and time part to (2 days + 2 hours + 30 minutes) into the future.

Drop(sHms,sYmd)
Drop(sYmdHms1,sYmdHms2,sYmdHms3)


:test_weekofyear
sYmdHms = "1975:12:29:00:00:00" ; Monday
woy1 = udfWeekOfYear (sYmdHms)  ; woy = 53

sYmdHms = "1975:12:31:00:00:00" ; Wednesday
woy2 = udfWeekOfYear (sYmdHms)  ; woy = 53

sYmdHms = "1976:01:01:00:00:00" ; Thursday
woy3 = udfWeekOfYear (sYmdHms)  ; woy = 1

sYmdHms = "1976:01:02:00:00:00" ; Friday
woy3 = udfWeekOfYear (sYmdHms)  ; woy = 1

sYmdHms