-- TIME AND DATE -- -- -- © March 2002 - October 2005, OpenSpark Interactive Ltd -- -- ---------------------------------------------------------------------- -- 051023 JN: Added ConvertToDate(), ConvertDateToInteger(), -- GetUnixTimeStamp() and GetDateFromTimeStamp() ---------------------------------------------------------------------- on ConvertToDate(aString) -------------------------------------------- -- INPUT: should be a string of integers between -- "19040101" and "20991231" -- OUTPUT: Returns a date object corresponding to the string. -------------------------------------------------------------------- vString = chars(aString, 1, 8) vInteger = value(vString) if vInteger < 19040101 then xCeption(#date, "Date is before 1 January 1904: "&aString) vInteger = 19040101 else if vInteger > 20991231 then xCeption(#date, "Date is after 31 December 2099: "&aString) vInteger = 20991231 end if return date(vInteger) end ConvertToDate on ConvertDateToInteger(aDate) --------------------------------------- -- INPUT: should be a date object. If not, the current -- systemDate is used instead -- OUTPUT: Returns an 8-digit integer with the format YYYYMMDD -------------------------------------------------------------------- vString = GetDate(aDate, [#format: #yyyymmdd, #delimiter: ""]) vInteger = value(vString) return vInteger end ConvertDateToInteger on GetUnixTimeStamp(aDate) ------------------------------------------- -- INPUT: should be a date object. If not, the current -- systemDate is used instead. Input dates should be in the -- range 1 January 1970 to 19 January 2038. -- OUTPUT: Returns the integer number of seconds since midnight on -- on 1 January 1970, or an error symbol if the date is out -- of range. -------------------------------------------------------------------- if ilk(aDate) <> #date then aDate = the systemDate end if vEpoch = date(19700101) -- seconds = 0 if aDate < vEpoch then return #dateOutOfRange end if vDays = aDate - vEpoch vSeconds = (vDays * 86400) + aDate.seconds if vSeconds < 0 then -- aDate is greater than 03:14:07 on 19 January 2038 return #dateOutOfRange end if return vSeconds end GetUnixTimeStamp on GetDateFromTimeStamp(anInteger) ----------------------------------- -- INPUT: should be a positive integer, corresponding to -- the number of seconds since midnight on 1 January 1970 -- OUTPUT: Returns a date object in the range 1 January 1970 to -- 19 January 2038, or an error symbol -------------------------------------------------------------------- if not integerP(anInteger) then return #integerExpected else if anInteger < 0 then return #outOfRange end if vEpoch = date(19700101) -- seconds = 0 vSecondsPerDay = 86400 vDays = anInteger / vSecondsPerDay vSeconds = anInteger mod vSecondsPerDay vDate = vEpoch + vDays vDate.seconds = vSeconds return vDate end GetDateFromTimeStamp on GetTime(aDateObject, anOptionsList) ------------------------------- -- INPUT: can be a date object or a floating point -- number such as 20020322.35999, where the integer part -- represents year * 10000 + month * 100 + day and the -- decimal part represents the number of seconds since the -- beginning of the day. -- can be a property list with the structure -- [#AM_PM: , -- #seconds: , -- #padZeroes: , -- #delimiter: ] -- OUTPUT: a string with the format "9:59 am" (by default) or any of -- the following formats, if is used: -- "9:59" / "21:59" -- #AM_PM: 0 -- "9:59:59 am" -- #seconds: 1 -- "09:59 am" -- #padZeroes: 1 -- "9-59-59" -- #delimiter: "-" -------------------------------------------------------------------- if ilk(anOptionsList) <> #propList then anOptionsList = [:] end if tAM_PM = anOptionsList[#AM_PM] if not integerP(tAM_PM) then tAM_PM = TRUE end if tShowSeconds = anOptionsList[#seconds] if not integerP(tShowSeconds) then tShowSeconds = FALSE end if tPadZeroes = anOptionsList[#padZeroes] if not integerP(tPadZeroes) then tPadZeroes = FALSE end if tDelimiter = anOptionsList[#delimiter] if not stringP(tDelimiter) then tDelimiter = ":" end if case ilk(aDateObject) of #date: tSeconds = aDateObject.seconds #integer: -- no seconds data is available tSeconds = 0 #float: tSeconds = integer((aDateObject-bitXor(aDateObject,0)) * 100000) otherwise: tSeconds = (the systemDate).seconds end case tMinutes = tSeconds / 60 tHours = tMinutes / 60 tMinutes = tMinutes mod 60 if tMinutes < 10 then tMinutes = "0"&tMinutes end if if tAM_PM then if tHours > 11 then tHours = ((tHours - 1) mod 12 + 1) tHalfDay = " pm" else tHalfDay = " am" end if else tHalfDay = "" end if if tPadZeroes then if tHours < 10 then tHours = "0"&tHours end if end if if tShowSeconds then tSeconds = tSeconds mod 60 if tSeconds < 10 then tSeconds = tDelimiter&"0"&tSeconds else tSeconds = tDelimiter&tSeconds end if else tSeconds = "" end if return tHours&tDelimiter&tMinutes&tSeconds&tHalfDay end GetTime on GetDate(aDateObject, anOptionsList) -------------------------------- -- INPUT: can be a date object or a floating point -- number such as 20020322.35999, where the integer part -- represents year * 10000 + month * 100 + day and the -- decimal part represents the number of seconds since the -- beginning of the day. -- can be a property list with the structure -- [#format: <#ddmmyy | #mmddyy | #yymmdd>, -- #century: , -- #padZeroes: , -- #delimiter: , -- #language: ] -- To do: -- #useNames: , -- #months: , -- #days: , -- OUTPUT: a string with the format "3/22/2002" (by default) or any -- combination of the following formats, if -- is used: -- "22/3/2002" -- #format: #ddmmyy -- "3/22/02" -- #century: 0 -- "03/22/2002" -- #padZeroes: 1 -- "3-22-2002" -- #delimiter: "-" -------------------------------------------------------------------- if ilk(anOptionsList) <> #propList then anOptionsList = [:] end if tIlk = ilk(aDateObject) case tIlk of #integer, #float: aDateObject = bitXor(aDateObject, 0) -- clips decimal part tYear = aDateObject / 10000 tMonth = (aDateObject mod 10000) / 100 tDay = aDateObject mod 100 otherwise: if tIlk = #date then -- Use the given date else case tIlk of #propList: anOptionsList = aDateObject #symbol: tFormat = aDateObject end case aDateObject = the systemDate end if tYear = aDateObject.year tMonth = aDateObject.month tDay = aDateObject.day end case if voidP(tFormat) then tFormat = anOptionsList[#format] end if tCentury = anOptionsList[#century] if not integerP(tCentury) then tCentury = TRUE end if tPadZeroes = anOptionsList[#padZeroes] if not integerP(tPadZeroes) then tPadZeroes = (tFormat = #yyyymmdd) end if tDelimiter = anOptionsList[#delimiter] if not stringP(tDelimiter) then tDelimiter = "/" end if if not tCentury then tYear = string(tYear).char[3..4] end if if tPadZeroes then if tMonth < 10 then tMonth = "0"&tMonth end if if tDay < 10 then tDay = "0"&tDay end if end if tDelimiter = anOptionsList[#delimiter] if not stringP(tDelimiter) then tDelimiter = "/" end if case tFormat of #yyyymmdd:-- 20021220 return tYear&tMonth&tDay #mdy: -- Dec 20 2002 tMonth = GetDateName(#mth, tMonth) return tMonth&&tDay&&tYear #ddmmyy: -- 20/12/2002 return tDay&tDelimiter&tMonth&tDelimiter&tYear #mmddyy: -- 12/20/2002 return tMonth&tDelimiter&tDay&tDelimiter&tYear #yymmdd: -- 20O2/12/20 return tYear&tDelimiter&tMonth&tDelimiter&tDay #d_m_y: -- 20 December, 2002 tMonth = GetDateName(#month, tMonth) return tDay&&tMonth&", "&tYear #m_d_y: -- December 20, 2002 tMonth = GetDateName(#month, tMonth) return tMonth&&tDay&", "&tYear #w_d_m_y: -- Friday 20 December, 2002 tWeekday = GetDateName(#day, GetWeekDay(aDateObject)) tMonth = GetDateName(#month, tMonth) return tWeekday&&tDay&&tMonth&", "&tYear #w_m_d_y: -- Friday December 20, 2002 tWeekday = GetDateName(#day, GetWeekDay(aDateObject)) tMonth = GetDateName(#month, tMonth) return tWeekday&&tMonth&&tDay&", "&tYear otherwise -- Use American #w_m_d_y format by default tWeekday = GetDateName(#day, GetWeekDay(aDateObject)) tMonth = GetDateName(#month, tMonth) return tWeekday&&tMonth&&tDay&", "&tYear -- return tMonth&tDelimiter&tDay&tDelimiter&tYear end case end GetDate on GetTimeAndDate(aDateObject, asFloat) ------------------------------ -- INPUT: can be a date object or a floating point -- number such as 20020322.43854, where the integer part -- represents year * 10000 + month * 100 + day and the -- decimal part represents the number of seconds since the -- beginning of the day. -- is ignored unless it is #float, in which case -- the date is returned in the format described above. -- OUTPUT: a floating point number if is #float or a -- string such as "12:09 on 3/22/2002". The exact format of -- the string depends on the separate GetTime() and -- GetDate() handlers. -------------------------------------------------------------------- if asFloat = #float then case ilk(aDateObject) of #float, #integer: return aDateObject #date: tYear = aDateObject.year * 10000 tMonth = aDateObject.month * 100 tSeconds = aDateObject.seconds / 100000.0 return tYear + tMonth + aDateObject.day + tSeconds otherwise: return GetTimeAndDate(the systemDate, #float) end case else case ilk(aDateObject) of #date, #float, #integer: -- continue otherwise: aDateObject = the systemDate end case end if -- Return date in human readable form return GetTime(aDateObject)&" on "&GetDate(aDateObject) end GetTimeAndDate on GetWeekDay(aDateObject) ------------------------------------------- -- Returns an integer between 1 and 7 indicating the day of the -- week: Monday = 1, Tuesday = 2 ... Sunday = 7 -- Example: -- put GetWeekDay([#day: 25, #month: 12, #year: 1998]) -- -- 5 --------------------------------------------------------------------- case ilk(aDateObject) of #date, #propList: -- trust that a propList has the right props otherwise: aDateObject = the systemDate end case tDay = aDateObject.day tMonth = aDateObject.month tYear = aDateObject.year -- Centuries are not leap years except when divisible by 400 -- To simplify, we'll ignore dates before 1901 or after 2099 if tYear < 1901 or tYear > 2099 then return #yearOutOfRange end if -- Determine what day February 28 will be in tYear -- We'll take the year 2000 as our starting point -- In 2000, February 28 is a Monday. Let's code Monday = 1 -- Tueday = 2 ... Sunday = 7 -- How many years after the year 2000 is tYear? tYearsFrom2000 = tYear - 2000 -- Are we in a leap year? isLeapYear = not (tYearsFrom2000 mod 4) -- How many leap years are there between tYear and 2000? tLeapYears = tYearsFrom2000 / 4 if not isLeapYear and tYearsFrom2000 > 0 then -- Add 1, since year 2000 is a leap year, but 2001/4 = 0 tLeapYears = tLeapYears + 1 end if feb28 = (tYearsFrom2000 + tLeapYears) mod 7 -- Look up tables for the 28th of each month if isLeapYear then -- Adjust for February 29 tAdjust = [4, 0, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3] else tAdjust = [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2] end if return 1 + (feb28 + tAdjust[tMonth] + tDay) mod 7 end GetWeekDay on GetDateName(aType, aValue, aLanguage) ----------------------------- -- INPUT: should be #month or #day -- should be a positive integer -- may be string language name -- OUTPUT: -------------------------------------------------------------------- -- Ensure that aValue is a positive integer in the appropriate range if integerP(aValue) then repeat while aValue < 1 aValue = aValue + 84 -- 7 * 12 end repeat case aType of #month, #mth: aValue = ((aValue - 1) mod 12) + 1 -- 1 to 12 #day, #d: aValue = ((aValue - 1) mod 7) + 1 -- 1 to 7 otherwise: -- cannot continue: fail gracefully return "" end case else -- cannot continue: fail gracefully return "" end if case aLanguage of "French", "français": case aType of #month: tStrings = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"] #day: tStrings = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"] end case otherwise: case aType of #month: tStrings = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] #mth: tStrings = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] #day: tStrings = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] #d: tStrings = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] end case end case return tStrings[aValue] end GetDateName