Generating a calendar
by Roger Harris, February 13, 2006 21:12
I had a question from a user about generating calendars with ODBscript. ODBscript has some simple date arithmetic and formatting capabilities, but they can be quite powerful for many date-related problems, especially when combined. (The functions are described in the Users Guide.)
To generate a calendar, all you need to know is the weekday for the first day of the month and the number of days in the month. ODBscript does not have direct functions for getting those, but a little date arithmetic solves the problem. To get the weekday, you can make use of the fact that December 31, 1899, was a Sunday, so if you calculate the number of days between that date and any other date, then take MOD 7 of that number, you will get a number between 0 and 6, corresponding to Sunday through Saturday for that date. To get the number of days in the month, you can take the difference between the first of the month and the first of the next month, which you can easily get (without worrying about possibly rolling over to the next year) by adding one month to the date of the first of the given month.
The following function takes three parameters: a date, an optional link (a URL), and a flag saying whether or not you want the given date highlighted in the generated calendar. The generated calendar will be for the month of the given date, e.g. you can pass in the current date, $date_short$, to generate a calendar for the current month. The link is because, typically when you need a calendar for a Web page, you will want the days to be clickable links to some script or page that does something for the selected date, e.g. show some report. If "link" is specified, each calendar day will have a link to that URL with the date simply added to the end. (If the link is to a script, you can end the given URL with something like "?date=" so the added date will be taken as a value for a variable. I have also used a similar function for linking to static pages that were named using the date, which just requires modifying how the function adds the date to the URL.) The highlight flag parameter, which should be 0 (false) or 1 (true) is useful when you want to highlight the specified date (e.g. if it's the current date or possibly a date selected from a calendar on a previous page).
The function separates out the month, day, and year (and also gets the month name) from the given date by reformatting the date with only a partial date mask, e.g. just "m" to get the month, "d" to get the day, etc. The function then uses those values to do the weekday and number of days calculations mentioned above. (The first of the month is obtained by simply inserting the month and year into a date with a fixed "1" for the day.)
Then, with those numbers in hand, you just need a little logic for handling the table rows, and putting spaces in the unused day cells at the beginning and end of the table.
<% FUNCTION Calendar (date, link, hl) mo, moname, dy, yr, wd1, nd, n, d; SET mo=$format("m",$date$), moname=$format("Mmmm",$date$), dy=$format("d",$date$), yr=$format("yyyy",$date$), wd1=$mod($dateDiff("12/31/1899",$mo$"/1/"$yr$),7), nd=$dateDiff($mo$"/1/"$yr$,$dateAdd($mo$"/1/"$yr$,1,"mm/dd/yyyy","M")); %> <table border=1 cellpadding=5 cellspacing=0> <tr><th colspan=7 align=center>$moname$ $yr$ </th></tr> <tr bgcolor="#f0f0f0"> <th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th> </tr> <% SET n=0, d=0; WHILE $d$ <= $nd$; IF $n$ = 0; %> <tr> <% ENDIF; IF $d$ = 0; IF $n$ = $wd1$; SET d = 1; ELSE; %> <td> </td> <% ENDIF; ENDIF; IF $d$ > 0; %> <td $if($hl$ AND $d$=$dy$,"bgcolor=#ffffc0")>$if($link$,"<a href="$link$$mo$"/"$d$"/"$yr$">") $d$ $if($link$,"</a>")</td> <% SET d = $d$ + 1; ENDIF; SET n = $n$ + 1; IF $n$ > 6; %> </tr> <% SET n = 0; ENDIF; ENDWHILE; IF $n$ > 0; WHILE $n$ < 7; %> <td> </td> <% SET n = $n$ + 1; ENDWHILE; %> </tr> <% ENDIF; %> </table> <% RETURN %>
As an example of using the function, the following generates three calendars: last month, the current month, and next month, with the current date in the current month highlighted. The dates for last month and next month are obtained by simply subtracting and adding 1 month to the current date in $date_short$ (see the Users Guide for more details), and those dates are not highlighted. The link is a URL to a script on odbscript.com named showinput.odb, which simply displays all input with a SHOWINPUT command (often useful for debugging).
<% SET link="http://odbscript.com/cgi-bin/odb.exe/odb/showinput.odb?date=" %> $Calendar($dateAdd($date_short$,-1,"mm/dd/yyyy","M"), $link$, 0) <p> $Calendar($date_short$, $link$, 1) <p> $Calendar($dateAdd($date_short$,1,"mm/dd/yyyy","M"), $link$, 0)
Following is the output (when run today, 2/13/2006):
January 2006 Sun Mon Tue Wed Thu Fri Sat 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
February 2006 Sun Mon Tue Wed Thu Fri Sat 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
March 2006 Sun Mon Tue Wed Thu Fri Sat 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
Name E-mail optional TopicMessage:
HTTP Link: Link text: