holidays.js
contains dates for government and secular
holidays. There are examples of fixed dates
(e.g. "1 April
" ), positional dates
(e.g. "2nd Sunday in May
") and relative dates
(e.g. "Tuesday on_or_after 2 November
").
astronomical.js
contains precalculated dates for events
tied to the motion of celestial bodies. Note that the dates are specific to a
particular time zone.
religious.js
contains dates for selected religious
holidays. It includes a good example of a table of dates for an event that does
not have a simple recurring date. It also has examples of dates relative to
another date.
personal.js
is a place where you can insert personal dates
such as birthdays and anniversaries. The example given can be easily modified.
calendar.html?plugin=friends.js,family.js
"
will load two plugin files named
friends.js
and
family.js
. This provides a mechanism to customize the notation
database in different ways on each activation of the
calendar.html
page.
selection.html
page is a demonstration of how to use the plugin
mechanism to customize your calendar notations. It dynamically builds a list of
calendar selections from a database specified in the selection.js
file. Take a moment to look at the file contents. Each call to
add_selection
adds another calendar selection to the page.
add_selection( "label", "file.js", ... )
selection.html
page, the calendar.html
page is
activated with the plugins that you specified. It is a simple matter to
customize the selection.js
file for any notation plugins that you
build yourself.
The selection page also performs another function that is not readily apparent. The enable/disable state for the notation database is maintained in a browser cookie for the duration of the current browser session. When you modify the contents of the notation database by using a different set of plugins, the old state values are no longer valid. The selection page corrects this by removing the old browser cookie before activating the calendar page. For this reason, I recommend using the selection page to activate the calendar page whenever you are switching from one set of plugins to another.
Notation.add_date( "date spec", "label", enable/disable )
add_date
constructor adds a new notation to the database. The
first argument is a date specification string (see
Date Specification Syntax).
The second argument is the label that appears on the calendar. The third
argument is the initial enable/disable state for the notation. Notations are
enabled by default so you can omit this argument in most cases. Specify
Notation.Disable
if you want the notation initially disabled. This
is useful for optional notations that the user can select as desired. The
calendar date cells become crowded if too many notations fall on the same
day.
Notation.append( "date spec" )
append
constructor is used to construct a table of notations.
Use the
add_date
constructor for the first table entry followed by the
append
constructor for each subsequent table entry.
A table is used to enter date specifications that do not follow a regular pattern for the day/month/year of occurrence. All the entries have a common label and share the same enable/disable state. During date resolution the table is searched sequentially until a date matching the current month and year is found. A table behaves as if the entries were connected by logical "or" clauses.
yearly |
matches all years This is the default when no year is specified. |
even |
matches even years |
odd |
matches odd years |
leap |
matches leap years |
YYYY |
matches the specified year where YYYY is a numberexample: 2004 |
XXXX thru YYYY |
matches the specified range of years example: 2004 thru 2008 |
N mod M |
matches all N = year mod M where
N and M are integersexample: 4 mod 5 matches
2004 and 2009 and 2014 ... |
A and B |
concatenate any of the explicit year selectors example: 2004 and 2006 thru 2008 and 2010 |
The majority of date specifications will use the yearly
selector.
Since this is the default, a year specification is rarely necessary. The
explicit year selectors are mainly used in tables where the day and/or month
components change from one year to the next. Combinations of the
mod
selector can generate any simply repeating pattern of years.
A specification like "XXXX thru YYYY thru ZZZZ
" is syntactically
incorrect. The parsing algorithm automatically collapses it to the equivalent
"XXXX thru ZZZZ
".
monthly |
matches all months This is the default when no month is specified. |
MMM |
matches the specified month where MMM isa month name: January ... December or its three letter abbreviation: Jan ... Dec |
MMM thru NNN |
matches the specified range of months example: May thru August |
A and B |
concatenate any of the explicit month selectors example: Dec thru Feb and June |
Explicit single month specifications seem to handle all cases of practical interest. The other options are there if you need them. A range specification treats the months cyclically with January as the successor to December.
daily |
selects all days in the month |
DD |
selects the specified day where DD is a numberexample: 14 |
DD thru EE |
selects the specified range of days example: 14 thru 18 |
N mod M |
selects all N = day mod M where
N and M are integersexample: 4 mod 7 selects
4 and 11 and 18 and 25 |
A and B |
concatenate any of the explicit day selectors example: 4 and 6 and 8 thru 10 |
Nth DAY in |
selects a day by name and position in the month where Nth is first, second, third, fourth, last or the abbreviation 1st, 2nd, 3rd, 4th and DAY is a day name: Sunday ... Saturday or its three letter abbreviation: Sun ... Sat example: 4th Wednesday in |
last day in |
selects the last day in the month |
The preceeding day selectors are terminal elements. A relative day selector is a recursive element. It specifies a day relative to another day. The process repeats until a terminal element is reached.
DAY before XX |
selects the specified day relative to another day where DAY is a day name: Sunday ... Saturday or its three letter abbreviation: Sun ... Sat |
weekday before XX |
selects a Monday ... Friday relative to another day |
The reference day XX may be any of the following. |
|
DD |
an explicit day where DD is a number (terminal) |
Nth DAY in last day in |
a positional day selector (terminal) |
DAY before XX |
a relative day selector (recursive reference) |
LABEL |
a reference to another date (recursive or terminal) |
examples:Wednesday before last Saturday in April |
The last form of the relative day selector must specify the label of a previously defined notation. Due to the way that tokens are parsed, the label cannot have any redundant blanks (i.e. "Extra Spaces"). You only need to specify enough of the target label to insure a correct match (i.e. "Big Long" will match "Big Long Rambling Label").
A relative date reference has additional peculiarities that require special handling. Notice that only the Day field is present in the date specification. The month and year must be determined from the referenced date. This brings up the topic of Date Resolution, which is covered in the next section.
Wednesday before 5 August
could fall outside the month of August!
You should beware of a relative day specification that falls near a monthly
boundary. A positional day specification is preferable because it will always
resolve to a day within the current month.
A relative day specification that references another date does not have its own
year and month specification. To determine whether the notation is applicable
for the current month and year it is necessary to first resolve the day
reference. This means extra processing overhead when scanning through the
notation database. However, a relative date reference that crosses a monthly
boundary will be correctly resolved. For example,
Sunday before Easter
could fall in either March or April depending
on the date of Easter for the current year. The date will be fully resolved
against the current date for Easter and the notation will appear on whichever
month is applicable. Relative date references are particularly useful when
referring to a date that is defined by a table of values.
Note that a referenced date cannot have a compound month specification
(e.g. March thru May
). The date resolution algorithm is not
capable of examining multiple choices for the month selection. For a compound
day specification, only the first day is resolved. The others are ignored.
The case of multiple year choices is handled by selecting the current year.
However, as a consequence of this simplification, a relative date reference can
never be selected across a year boundary. The resolved year will never match
the current year. To do this successfully, the algorithm would have to be
smart enough to examine either the preceding or following year selection. My
design choice was to keep the date resolution procedure simple and not pursue
rarely needed features. It is capable of following recursive date references,
that is, a reference to a date that references yet another date.