This line looks wrong to me:
setvar HOL_DAY !HOL_DAY + ( !HOL_YWK / 100 ) * 36524
I think it should be:
setvar HOL_DAY !HOL_DAY - ( !HOL_YWK / 100 ) * 36524
Steve Cooper
> -----Original Message-----
> From: HP-3000 Systems Discussion
> [mailto:[log in to unmask]] On Behalf Of Dave Powell, MMfab
> Sent: Wednesday, May 13, 2009 1:35 PM
> To: [log in to unmask]
> Subject: [HP3000-L] holiday function
>
> Long ago, Tracy Pierce posted a command-file "datetest" to
> tell whether a
> day was a holiday (search for "happy holidays" Sept 26, 2002).
> I finally needed something like that, but I wanted the following main
> changes:
>
> 1: Boolean function syntax, so I could say
> :if holiday() then
> instead of
> :xeq datetest
> :if WhichVariableName = DontRememberWhatValue then
> and also because I just think user-functions are cool.
> 2: *MUCH* easier to add or disable specific holidays according to
> site-specific policies or even other countries' rules.
> 3: Then disable Veterans Day, Presidents Day & MLK Day,
> because we don't
> take them.
> 4: Make it easy to add special one-off holidays like the day
> before | after
> Christmas at the last minute when the company announces them.
>
>
> Along the way I also added midnight-protection and partial input
> date-checking. Also made it more readable, at least to me -- YMMV.
>
>
> Most of the "fun" came in the day-of-week calculation. I
> didn't understand
> that part of Tracy's script, or trust myself to adapt it
> without messing up,
> so I found a second method and used both, with a warning if
> the results
> didn't agree. Surprise, surprise, they disagree about
> 12/25/2100, although
> they agree on dates I tested within the expected life-span of
> MPE. So I
> shoveled in a third formula and found a day-of-week
> calculator spreadsheet,
> both of which agree with the 2nd method.
> So, anyone who uses Tracy's original command file and plans
> to still run it
> in 2100 might need to make a change :)
>
>
>
> I'd appreciate it if the wise ones could check for errors,
> clarify which
> day-of-week formula is "best" etc, etc. And if anyone has an
> MPE version of
> the "Babwani" day-of-week formula, I'll toss that in too.
>
>
> Anyway, here is my preliminary version:
>
>
> option nolist
> parm CCYYMMDD = ""
> if bound (HOL_ERRORS) or bound (HOL_DAY)
> deletevar HOL_@
> endif
> setvar HOL_ERRORS 0
> if "!CCYYMMDD" = ""
> setvar HOL_CYMD HPYYYYMMDD
> setvar HOL_DAY !HPDAY
> if HOL_CYMD <> HPYYYYMMDD
> # if the date has changed, we just hit midnite and the
> # day-of-week we just set might be the new day; in this
> # case set the date & day-of-week again, and we should
> # be ok (unless the following 2 commands take 24 hours :)
> setvar HOL_CYMD HPYYYYMMDD
> setvar HOL_DAY !HPDAY
> endif
> else
> setvar HOL_CYMD "!CCYYMMDD"
> if not numeric (HOL_CYMD)
> echo **date parm, if entered, must be numeric**
> setvar HOL_ERRORS HOL_ERRORS + 1
> endif
> if len (HOL_CYMD) <> 8
> echo **date parm must be exactly 8 digits, unless omitted**
> setvar HOL_ERRORS HOL_ERRORS + 1
> elseif numeric (HOL_CYMD)
> if rht (HOL_CYMD, 2) > "31"
> echo **last 2 digits of date parm can't be more than 31**
> setvar HOL_ERRORS HOL_ERRORS + 1
> elseif rht (HOL_CYMD, 2) = "00"
> echo **last 2 digits of date parm can't be "00"**
> setvar HOL_ERRORS HOL_ERRORS + 1
> endif
> if str (HOL_CYMD, 5, 2) > "12"
> echo **bytes 5 & 6 of date parm can't be more than 12**
> setvar HOL_ERRORS HOL_ERRORS + 1
> elseif str (HOL_CYMD, 5, 2) = "00"
> echo **characters 5 & 6 of date parm can't be "00"**
> setvar HOL_ERRORS HOL_ERRORS + 1
> endif
> endif
> if HOL_ERRORS > 0
> echo **exiting because the date-parm was not a valid**
> echo **8-digit date in yyyymmdd format **
> return FALSE
> endif
> endif
>
> # -------------------------------------------------------
> # do not casually modify above here
> #
> # Take any special / unofficial holidays here
> # OK to replace any dates that are past with the date of a
> # holiday the company just announced (Jewish new year,
> # days before / after Christmas & New Years, etc, etc)
>
> if HOL_CYMD="20080929" or HOL_CYMD="20081008" &
> or HOL_CYMD="20081226" or HOL_CYMD="20090102"
> echo It's a special company holiday :)
> return TRUE
> endif
>
> # do not casually modify below here
> # -------------------------------------------------------
>
> setvar HOL_YYYY str (HOL_CYMD, 1, 4)
> setvar HOL_MM str (HOL_CYMD, 5, 2)
> setvar HOL_DD str (HOL_CYMD, 7, 2)
>
> #
> # Set day of week, unless already set because processing "today"
> #
> if not bound (HOL_DAY)
> # 1st, the method in the original "datetest" command file
> setvar HOL_DAY str("000031059090120151181212243273304334", &
> !HOL_MM * 3 - 2, 3)
> setvar HOL_DAY !HOL_DAY + !HOL_DD
> IF !HOL_MM > 2 and ( !HOL_YYYY / 4 * 4 = !HOL_YYYY )
> setvar HOL_DAY HOL_DAY + 1
> ENDIF
> setvar HOL_YWK !HOL_YYYY - 1
> setvar HOL_DAY !HOL_DAY + ( !HOL_YWK / 400 ) * 146097
> setvar HOL_YWK !HOL_YWK mod 400
> setvar HOL_DAY !HOL_DAY + ( !HOL_YWK / 100 ) * 36524
> setvar HOL_YWK !HOL_YWK mod 100
> setvar HOL_DAY !HOL_DAY + ( !HOL_YWK / 4 ) * 1461
> setvar HOL_YWK !HOL_YWK mod 4
> setvar HOL_DAY !HOL_DAY + ( !HOL_YWK * 365 )
> setvar HOL_DAY ( HOL_DAY mod 7 ) + 1
> deletevar HOL_YWK
>
> # Next, the method posted to the 3000-l by Mike Hornsby 06/04/2004
> # except, add 1 at the end because his was 0-6 and we need
> # 1-7.
> setvar HOL_XYR !HOL_YYYY-((12-!HOL_MM)/10)
> setvar HOL_XMONTH !HOL_MM+(((12-!HOL_MM)/10)*12)
> setvar HOL_XDAY !HOL_DD+(!HOL_XMONTH*2)+(((!HOL_XMONTH+1)*6)/10)
> setvar HOL_XLEAP_YR (HOL_XYR/4) - (HOL_XYR/100) + (HOL_XYR/400)
> setvar HOL_XDAY (HOL_XDAY+HOL_XYR+HOL_XLEAP_YR+1) mod 7 + 1
>
> # Next, day-of-week with my adaption of a "Zeller" formula
> # off the internet.
> if HOL_MM < "03"
> setvar HOL_ZMONTH !HOL_MM + 12
> setvar HOL_ZYEAR !HOL_YYYY - 1
> else
> setvar HOL_ZMONTH !HOL_MM
> setvar HOL_ZYEAR !HOL_YYYY
> endif
> setvar HOL_ZDAY ( &
> ((13 * HOL_ZMONTH + 3) / 5) + !HOL_DD + HOL_ZYEAR &
> + (HOL_ZYEAR/4) - (HOL_ZYEAR/100) + (HOL_ZYEAR/400) &
> + 1 ) mod 7 + 1
>
> # Now, see if the day-of-week calcs agree
> if HOL_DAY <> HOL_XDAY &
> or HOL_DAY <> HOL_ZDAY &
> or HOL_ZDAY <> HOL_XDAY
> setvar HOL_ERRORS HOL_ERRORS + 1
> echo **day-of-week error**
> echo HOL_DAY = !HOL_DAY
> echo HOL_XDAY = !HOL_XDAY
> echo HOL_ZDAY = !HOL_ZDAY
> endif
> setvar HOL_DAY HOL_ZDAY
> deletevar HOL_X@, HOL_Z@
> ENDIF
>
> #
> # Now check for specific regular holidays, month-by-month.
> if HOL_MM = "01"
> if HOL_DD = "01"
> echo It's New Years Day
> return TRUE
> endif
> if ( !HOL_DAY=2 and !HOL_DD>=15 and !HOL_DD<=21 )
> echo (It's Martin Luther King day - but do we get it?)
> # return TRUE
> endif
> return FALSE
> elseif HOL_MM = "02"
> if (!HOL_DAY=2 and !HOL_DD>=15 and !HOL_DD<=21)
> echo (It's President's Day - but do we get it?)
> # return TRUE
> endif
> return FALSE
> elseif HOL_MM = "05"
> if (!HOL_DAY=2 and !HOL_DD>=25 and !HOL_DD<=31)
> echo It's Memorial Day
> return TRUE
> endif
> return FALSE
> elseif HOL_MM = "07"
> if HOL_DD = "04"
> echo It's July 4th
> return TRUE
> endif
> return FALSE
> elseif HOL_MM = "09"
> if ( !HOL_DAY=2 and !HOL_DD>=1 and !HOL_DD<=7 )
> echo It's Labor Day
> return TRUE
> endif
> return FALSE
> elseif HOL_MM = "11"
> if HOL_DD = "11"
> echo (it's Veterans Day - but do we get it ?)
> # return TRUE
> endif
> if ( !HOL_DAY=5 and !HOL_DD>=22 and !HOL_DD<=28 )
> echo It's Thanksgiving
> return TRUE
> endif
> if ( !HOL_DAY=6 and !HOL_DD>=23 and !HOL_DD<=29 )
> echo It's the day after Thanksgiving
> return TRUE
> endif
> return FALSE
> elseif HOL_MM = "12"
> if HOL_DD = "25"
> echo It's Christmas
> return TRUE
> endif
> return FALSE
> endif
>
> # showvar HOL_@
> return FALSE
> # Function "holiday" to return 'TRUE' on company holidays
> # Dave Powell, MMfab, Inc 05/12/2009
> #
> # Syntax if holiday () then <checks today>
> # calc holiday (20090511)
> # if holiday ("20090511") then
> # calc holiday (SomeDateVariable)
> # etc
> # or, for a company that sometimes has a few people in
> # Saturday morning, but its not like a real workday
> # setvar OFFDAY HOLIDAY() or HPDAY=1
> # setvar WORKDAY HPDAY<7 and not OFFDAY
> # setvar MAYBEDAY not ( OFFDAY or WORKDAY )
> # etc
> #
> # Logic adapted from the "datetest" command file
> # posted by Tracy Pierce on the HP-3000L on 09/26/2002
> #
> # Variable-naming convention:
> # - 'DD', "MM", "YYYY" etc mean string variables with the
> # length you might guess from the name.
> # - 'DAY', "YEAR", "MONTH" mean integer-type variables.
> #
> # Changes / "improvements" in this file over original "datetest"
> # - Function syntax, so you can say
> # if holiday() then
> # instead of
> # xeq datetest
> # if IForgetTheVariableName = WhatWasThatValue then
> # - Separate "if"s for each holiday, to make it easier to
> # turn them on or off depending on your site's policies.
> # - Then turns off some holidays I don't I think I can
> # count on MMfab always taking.
> # - It echoes the name of whatever holiday it thinks it is,
> # do make debugging easier.
> # - Has a spot to put in extra / unofficial days off when
> # the company announces them (like the day before / after
> # Christmas).
> # - Returns true if the holiday falls on a Saturday or Sunday,
> # except Easter Sunday, which is ugly.
> # - Midnite protection.
> # - Checks that the date is numeric, with plausible month & day
> # (does not check that the day is too high for that month)
> # - More readable ?
> # - Calculates day-of-week three ways and compares them, as an
> # extra double-check since I don't understand any of
> # these calculations :(
> # Downgrades:
> # - Won't try to guess the century -- cannot handle 6-digit
> # input.
> #
> #
> # Any errors return "FALSE" on the assumption that the programmer,
> # at least, can't take a holiday until he fixes the bug :)
> #
> #
> # Day-of-Week note:
> # The 3 methods mostly agree, but 12-25-2100 is a Sunday
> # according to method 1, but a Saturday according to methods
> # 2 & 3. Babwani's modified 2007 date-calc spreadsheet also
> # says Saturday.
>
> * To join/leave the list, search archives, change list settings, *
> * etc., please visit http://raven.utc.edu/archives/hp3000-l.html *
>
* To join/leave the list, search archives, change list settings, *
* etc., please visit http://raven.utc.edu/archives/hp3000-l.html *
|