1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
[
/*
[holiday] by Steve Piercy
http://www.stevepiercy.com/
v 1.0 released on the [holiday(1,7,11,2009)] (Use this tag to find what is that date.)
=================
Description
=================
[holiday] determines the Nth day of the week for a given month and year, and optionally returns the next occurrence. Also returns an error in case invalid parameters are submitted, which can be displayed by [error_currenterror]. The defaults for month and year are the current month and year. This tag is handy for determining when holidays fall on a calendar. Requires the custom tag [leapyear].
=================
Usage
=================
The following two statements are equivalent.
[holiday(-ordinal=-1,-dayofweek=2,-month=5,-year=2009)]
[holiday(-1,2,5,2009)]
The following two statements are equivalent.
[holiday(-ordinal=-1,-dayofweek=2,-month=5,-next)]
[holiday(-1,2,5,-next)]
Example Holidays
----------------------------
Martin Luther King, Jr. Day (third Monday of January)
[holiday(3,2,1,year)]
Presidents Day (third Monday of February)
[holiday(3,2,2,year)]
Daylight Savings time begins (second Sunday of March)
[holiday(2,1,3,year)]
Mothers Day (second Sunday of May)
[holiday(2,1,5,year)]
Memorial Day (last Monday of May)
[holiday(-1,2,5,year)]
Fathers Day (you get the idea)
[holiday(3,1,6,year)]
Labor Day
[holiday(1,2,9,year)]
Columbus Day
[holiday(2,2,10,year)]
Daylight Savings Time ends
[holiday(1,1,11,year)]
Thanksgiving Day
[holiday(4,5,11,year)]
=================
Acknowledgments
=================
[holiday] is based on an idea from:
http://www.irt.org/articles/js050/index.htm
...with suggestions for improvement from Bil Corry.
...inspired by jQuery Datepicker:
http://keith-wood.name/datepick.html
*/
define_tag('leapyear',-required='year', -type='integer',
-description='Determines whether a given year is a leap year. Returns either TRUE or FALSE.');
#year%4 ? return (false);
#year%100 ? return (true);
#year%400 ? return (false);
return (true);
/define_tag;
define_tag('holiday',
-required='ordinal', -type='integer', // 1=first,...5=fifth, -1=last
-required='dayofweek', -type='integer', // 1=Sunday,..., 7=Saturday
-optional='month', -type='integer', // default is current month
-optional='year', -type='integer', // default is current year
-optional='next', // returns the next occurrence
-description='[holiday] determines the Nth day of the week for a given month and year, and optionally returns the next occurrence. Also returns an error in case invalid parameters are submitted, which can be displayed by [error_currenterror]. The defaults for month and year are the current month and year. This tag is handy for determining when holidays fall on a calendar. Requires the custom tag [leapyear].');
// avoid submission of conflicting or invalid parameters
if(local_defined('year') && local_defined('next'));
error_seterrormessage('Syntax error calling tag "holiday" with conflicting parameters. Only one of -year or -next parameters may be defined.');
error_seterrorcode(-9900);
return;
/if;
if(array(-1,1,2,3,4,5)!>>#ordinal);
error_seterrormessage('Syntax error calling tag "holiday" with invalid parameter (-ordinal=' + #ordinal + '). Valid values are -1, 1, 2, 3, 4, or 5.');
error_seterrorcode(-9900);
return;
/if;
if(series(1,7)!>>#dayofweek);
error_seterrormessage('Syntax error calling tag "holiday" with invalid parameter (-dayofweek=' + #dayofweek + '). Valid values are between 1 and 7.');
error_seterrorcode(-9900);
return;
/if;
if(local_defined('month'));
if(series(1,12)!>>#month);
error_seterrormessage('Syntax error calling tag "holiday" with invalid parameter (-month=' + #month + '). Valid values are between 1 and 12.');
error_seterrorcode(-9900);
return;
/if;
/if;
if(local_defined('year'));
if(#year<1000 || #year>9999);
error_seterrormessage('Syntax error calling tag "holiday" with invalid parameter (-year=' + #year + '). Valid values are between 1000 and 9999.');
error_seterrorcode(-9900);
return;
/if;
/if;
!local_defined('month') ? local('month') = date->month;
!local_defined('year') ? local('year') = date->year;
local_defined('next') ? local('next') = true | local('next') = false;
// set days per month
if(leapyear(#year));
local('dayspermonth' = array(31,29,31,30,31,30,31,31,30,31,30,31));
else;
local('dayspermonth' = array(31,28,31,30,31,30,31,31,30,31,30,31));
/if;
if(#ordinal > 0);
// get first day of the month
local('date') = date(-month=#month, -day=1, -year=#year, -hour=12);
// find first instance of dayofweek in the month
local('delta') = #dayofweek - #date->dayofweek;
if(#delta < 0);
#delta += 7;
/if;
#date->add(-day=#delta);
// adjust date to desired instance
#date->add(-day=7 * (#ordinal - 1));
else;
// get last day of the month
local('date') = date(-month=#month, -day=#dayspermonth->get(#month), -year=#year, -hour=12);
// find last instance of dayofweek in the month
local('delta') = #date->dayofweek - #dayofweek;
if(#delta < 0);
#delta += 7;
/if;
#date->subtract(-day=#delta);
/if;
// adjust to next date
if(#next && date>=#date);
#date->add(-year=1);
return(holiday(#ordinal,#dayofweek,#month,#date->year));
/if;
return(#date);
/define_tag;
]
|